[Freeswitch-svn] [commit] r8545 - in freeswitch/trunk/libs/xmlrpc-c: . Windows doc examples examples/cpp include include/xmlrpc-c lib lib/abyss lib/abyss/example lib/abyss/example/conf lib/abyss/example/htdocs lib/abyss/src lib/curl_transport lib/expat lib/expat/gennmtab lib/expat/xmlparse lib/expat/xmltok lib/expat/xmlwf lib/libutil lib/libwww_transport lib/util lib/util/include lib/wininet_transport src src/cpp src/cpp/test src/test src/test/data tools tools/lib tools/lib/include tools/perl_packetsocket tools/turbocharger tools/xml-rpc-api2cpp tools/xmlrpc tools/xmlrpc_cpp_proxy tools/xmlrpc_pstream tools/xmlrpc_transport
Freeswitch SVN
mikej at freeswitch.org
Fri May 23 16:56:25 EDT 2008
Author: mikej
Date: Fri May 23 16:56:24 2008
New Revision: 8545
Added:
freeswitch/trunk/libs/xmlrpc-c/Makefile.srcdir.in
freeswitch/trunk/libs/xmlrpc-c/Makefile.version
freeswitch/trunk/libs/xmlrpc-c/Windows/CleanAll.bat
freeswitch/trunk/libs/xmlrpc-c/Windows/CleanWin32.bat
freeswitch/trunk/libs/xmlrpc-c/Windows/ReadMeOld.txt
freeswitch/trunk/libs/xmlrpc-c/Windows/UsingProxyDSP.txt
freeswitch/trunk/libs/xmlrpc-c/Windows/abyss.dsp
freeswitch/trunk/libs/xmlrpc-c/Windows/configwin32.dsp
freeswitch/trunk/libs/xmlrpc-c/Windows/curllink.h
freeswitch/trunk/libs/xmlrpc-c/Windows/delsln.bat
freeswitch/trunk/libs/xmlrpc-c/Windows/diffcfg.bat
freeswitch/trunk/libs/xmlrpc-c/Windows/gennmtab.dsp
freeswitch/trunk/libs/xmlrpc-c/Windows/mkvers.bat
freeswitch/trunk/libs/xmlrpc-c/Windows/mkvers1.bat
freeswitch/trunk/libs/xmlrpc-c/Windows/updcfg.bat
freeswitch/trunk/libs/xmlrpc-c/Windows/win32_config.h
freeswitch/trunk/libs/xmlrpc-c/Windows/xmlhttpsys.dsp
freeswitch/trunk/libs/xmlrpc-c/Windows/xmlparse.dsp
freeswitch/trunk/libs/xmlrpc-c/Windows/xmlrpc_cpp_proxy.dsp
freeswitch/trunk/libs/xmlrpc-c/Windows/xmlrpc_misc.dsp
freeswitch/trunk/libs/xmlrpc-c/Windows/xmlrpccpp.dsp
freeswitch/trunk/libs/xmlrpc-c/Windows/xmltok.dsp
freeswitch/trunk/libs/xmlrpc-c/common.mk
freeswitch/trunk/libs/xmlrpc-c/config.mk.in
freeswitch/trunk/libs/xmlrpc-c/dll-common.make
freeswitch/trunk/libs/xmlrpc-c/doc/INSTALL
freeswitch/trunk/libs/xmlrpc-c/dylib-common.make
freeswitch/trunk/libs/xmlrpc-c/examples/cpp/asynch_client.cpp
freeswitch/trunk/libs/xmlrpc-c/examples/cpp/pstream_client.cpp
freeswitch/trunk/libs/xmlrpc-c/examples/cpp/pstream_inetd_server.cpp
freeswitch/trunk/libs/xmlrpc-c/examples/cpp/xmlrpc_inetd_server.cpp
freeswitch/trunk/libs/xmlrpc-c/examples/cpp/xmlrpc_loop_server.cpp
freeswitch/trunk/libs/xmlrpc-c/examples/interrupted_client.c
freeswitch/trunk/libs/xmlrpc-c/examples/interrupted_server.c
freeswitch/trunk/libs/xmlrpc-c/examples/xmlrpc_inetd_server.c
freeswitch/trunk/libs/xmlrpc-c/examples/xmlrpc_socket_server.c
freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/abyss_opensslsock.h
freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/abyss_unixsock.h
freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/abyss_winsock.h
freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/base64.hpp
freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/c_util.h
freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/client_global.h
freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/client_transport.hpp
freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/inttypes.h
freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/packetsocket.hpp
freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/select_int.h
freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/server_pstream.hpp
freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/sleep_int.h
freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/string_int.h
freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/time_int.h
freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/util.h
freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/util_int.h
freeswitch/trunk/libs/xmlrpc-c/irix-common.make
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/HISTORY
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/example/
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/example/conf/
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/example/conf/abyss.conf
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/example/conf/mime.types
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/example/htdocs/
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/example/htdocs/index.htm
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/example/htdocs/pwrabyss.gif (contents, props changed)
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/abyss_info.h
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/channel.c
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/channel.h
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/chanswitch.c
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/chanswitch.h
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/conn.h
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/data.h
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/date.c
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/date.h
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/file.h
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/handler.c
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/handler.h
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/http.h
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/init.c
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/response.c
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/server.h
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/session.c
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/session.h
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/socket.h
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/socket_openssl.c
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/socket_unix.c
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/socket_unix.h
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/socket_win.c
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/socket_win.h
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/thread.h
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/thread_fork.c
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/thread_pthread.c
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/thread_windows.c
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/trace.h
freeswitch/trunk/libs/xmlrpc-c/lib/libutil/
freeswitch/trunk/libs/xmlrpc-c/lib/libutil/Makefile
freeswitch/trunk/libs/xmlrpc-c/lib/libutil/asprintf.c
freeswitch/trunk/libs/xmlrpc-c/lib/libutil/error.c
freeswitch/trunk/libs/xmlrpc-c/lib/libutil/make_printable.c
freeswitch/trunk/libs/xmlrpc-c/lib/libutil/memblock.c
freeswitch/trunk/libs/xmlrpc-c/lib/libutil/select.c
freeswitch/trunk/libs/xmlrpc-c/lib/libutil/sleep.c
freeswitch/trunk/libs/xmlrpc-c/lib/libutil/time.c
freeswitch/trunk/libs/xmlrpc-c/lib/libutil/utf8.c
freeswitch/trunk/libs/xmlrpc-c/lib/util/cmdline_parser_cpp.cpp
freeswitch/trunk/libs/xmlrpc-c/lib/util/include/assertx.hpp
freeswitch/trunk/libs/xmlrpc-c/lib/util/include/c_util.h
freeswitch/trunk/libs/xmlrpc-c/lib/util/include/cmdline_parser.hpp
freeswitch/trunk/libs/xmlrpc-c/lib/util/include/girmath.h
freeswitch/trunk/libs/xmlrpc-c/lib/util/include/girstring.h
freeswitch/trunk/libs/xmlrpc-c/lib/util/include/int.h
freeswitch/trunk/libs/xmlrpc-c/lib/util/include/stdargx.h
freeswitch/trunk/libs/xmlrpc-c/lib/util/include/string_parser.h
freeswitch/trunk/libs/xmlrpc-c/lib/util/include/unistdx.h
freeswitch/trunk/libs/xmlrpc-c/lib/util/string_parser.c
freeswitch/trunk/libs/xmlrpc-c/lib/util/stripcaseeq.c
freeswitch/trunk/libs/xmlrpc-c/missing
freeswitch/trunk/libs/xmlrpc-c/src/cpp/base64.cpp
freeswitch/trunk/libs/xmlrpc-c/src/cpp/curl.cpp
freeswitch/trunk/libs/xmlrpc-c/src/cpp/env_wrap.cpp
freeswitch/trunk/libs/xmlrpc-c/src/cpp/env_wrap.hpp
freeswitch/trunk/libs/xmlrpc-c/src/cpp/girerr.cpp
freeswitch/trunk/libs/xmlrpc-c/src/cpp/libwww.cpp
freeswitch/trunk/libs/xmlrpc-c/src/cpp/packetsocket.cpp
freeswitch/trunk/libs/xmlrpc-c/src/cpp/pstream.cpp
freeswitch/trunk/libs/xmlrpc-c/src/cpp/server_pstream.cpp
freeswitch/trunk/libs/xmlrpc-c/src/cpp/test/
freeswitch/trunk/libs/xmlrpc-c/src/cpp/test/Makefile
freeswitch/trunk/libs/xmlrpc-c/src/cpp/test/registry.cpp
freeswitch/trunk/libs/xmlrpc-c/src/cpp/test/registry.hpp
freeswitch/trunk/libs/xmlrpc-c/src/cpp/test/server_abyss.cpp
freeswitch/trunk/libs/xmlrpc-c/src/cpp/test/server_abyss.hpp
freeswitch/trunk/libs/xmlrpc-c/src/cpp/test/server_pstream.cpp
freeswitch/trunk/libs/xmlrpc-c/src/cpp/test/server_pstream.hpp
freeswitch/trunk/libs/xmlrpc-c/src/cpp/test/test.cpp
freeswitch/trunk/libs/xmlrpc-c/src/cpp/test/testclient.cpp
freeswitch/trunk/libs/xmlrpc-c/src/cpp/test/testclient.hpp
freeswitch/trunk/libs/xmlrpc-c/src/cpp/test/testclient_dummy.cpp
freeswitch/trunk/libs/xmlrpc-c/src/cpp/test/tools.cpp
freeswitch/trunk/libs/xmlrpc-c/src/cpp/test/tools.hpp
freeswitch/trunk/libs/xmlrpc-c/src/cpp/wininet.cpp
freeswitch/trunk/libs/xmlrpc-c/src/double.c
freeswitch/trunk/libs/xmlrpc-c/src/double.h
freeswitch/trunk/libs/xmlrpc-c/src/method.c
freeswitch/trunk/libs/xmlrpc-c/src/method.h
freeswitch/trunk/libs/xmlrpc-c/src/parse_value.c
freeswitch/trunk/libs/xmlrpc-c/src/parse_value.h
freeswitch/trunk/libs/xmlrpc-c/src/registry.c
freeswitch/trunk/libs/xmlrpc-c/src/registry.h
freeswitch/trunk/libs/xmlrpc-c/src/resource.c
freeswitch/trunk/libs/xmlrpc-c/src/system_method.c
freeswitch/trunk/libs/xmlrpc-c/src/system_method.h
freeswitch/trunk/libs/xmlrpc-c/src/test/Makefile
freeswitch/trunk/libs/xmlrpc-c/src/test/abyss.c
freeswitch/trunk/libs/xmlrpc-c/src/test/abyss.h
freeswitch/trunk/libs/xmlrpc-c/src/test/client_dummy.c
freeswitch/trunk/libs/xmlrpc-c/src/test/data/
freeswitch/trunk/libs/xmlrpc-c/src/test/data/req_no_params.xml
freeswitch/trunk/libs/xmlrpc-c/src/test/data/req_out_of_order.xml
freeswitch/trunk/libs/xmlrpc-c/src/test/data/req_value_name.xml
freeswitch/trunk/libs/xmlrpc-c/src/test/data/sample_add_call.xml
freeswitch/trunk/libs/xmlrpc-c/src/test/method_registry.c
freeswitch/trunk/libs/xmlrpc-c/src/test/method_registry.h
freeswitch/trunk/libs/xmlrpc-c/src/test/serialize_value.c
freeswitch/trunk/libs/xmlrpc-c/src/test/serialize_value.h
freeswitch/trunk/libs/xmlrpc-c/src/trace.c
freeswitch/trunk/libs/xmlrpc-c/src/version.c
freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_build.c
freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_client_global.c
freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_decompose.c
freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_server_info.c
freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_string.c
freeswitch/trunk/libs/xmlrpc-c/tools/common.mk
freeswitch/trunk/libs/xmlrpc-c/tools/lib/
freeswitch/trunk/libs/xmlrpc-c/tools/lib/Makefile
freeswitch/trunk/libs/xmlrpc-c/tools/lib/dumpvalue.c
freeswitch/trunk/libs/xmlrpc-c/tools/lib/include/
freeswitch/trunk/libs/xmlrpc-c/tools/lib/include/dumpvalue.h
freeswitch/trunk/libs/xmlrpc-c/tools/perl_packetsocket/
freeswitch/trunk/libs/xmlrpc-c/tools/perl_packetsocket/PacketSocket.pm
freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_cpp_proxy/
freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_cpp_proxy/Makefile
freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_cpp_proxy/proxyClass.cpp
freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_cpp_proxy/proxyClass.hpp
freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_cpp_proxy/systemProxy.cpp
freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_cpp_proxy/systemProxy.hpp
freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_cpp_proxy/xmlrpcMethod.cpp
freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_cpp_proxy/xmlrpcMethod.hpp
freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_cpp_proxy/xmlrpcType.cpp
freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_cpp_proxy/xmlrpcType.hpp
freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_cpp_proxy/xmlrpc_cpp_proxy.cpp
freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_pstream/
freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_pstream/Makefile
freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_pstream/test
freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_pstream/xmlrpc_pstream.cpp
freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_pstream/xmlrpc_pstream.html
freeswitch/trunk/libs/xmlrpc-c/transport_config.make
freeswitch/trunk/libs/xmlrpc-c/unix-common.make
freeswitch/trunk/libs/xmlrpc-c/xmlrpc-c-config.main
freeswitch/trunk/libs/xmlrpc-c/xmlrpc-c-config.test.main
freeswitch/trunk/libs/xmlrpc-c/xmlrpc_amconfig.h.in
Modified:
freeswitch/trunk/libs/xmlrpc-c/GNUmakefile
freeswitch/trunk/libs/xmlrpc-c/Makefile
freeswitch/trunk/libs/xmlrpc-c/README
freeswitch/trunk/libs/xmlrpc-c/Windows/ConfigureWin32.bat
freeswitch/trunk/libs/xmlrpc-c/Windows/ReadMeWin32.txt
freeswitch/trunk/libs/xmlrpc-c/Windows/UsingCURLinWin32.txt
freeswitch/trunk/libs/xmlrpc-c/Windows/cpptest.dsp
freeswitch/trunk/libs/xmlrpc-c/Windows/rpctest.dsp
freeswitch/trunk/libs/xmlrpc-c/Windows/transport_config_win32.h
freeswitch/trunk/libs/xmlrpc-c/Windows/xmlrpc.dsp
freeswitch/trunk/libs/xmlrpc-c/Windows/xmlrpc.dsw
freeswitch/trunk/libs/xmlrpc-c/Windows/xmlrpc_sample_add_asynch_client.dsp
freeswitch/trunk/libs/xmlrpc-c/Windows/xmlrpc_sample_add_server.dsp
freeswitch/trunk/libs/xmlrpc-c/Windows/xmlrpc_sample_add_server_w32httpsys.dsp
freeswitch/trunk/libs/xmlrpc-c/Windows/xmlrpc_sample_add_sync_client.dsp
freeswitch/trunk/libs/xmlrpc-c/Windows/xmlrpc_sample_auth_client.dsp
freeswitch/trunk/libs/xmlrpc-c/Windows/xmlrpc_win32_config.h
freeswitch/trunk/libs/xmlrpc-c/configure.in
freeswitch/trunk/libs/xmlrpc-c/doc/COPYING
freeswitch/trunk/libs/xmlrpc-c/doc/HISTORY
freeswitch/trunk/libs/xmlrpc-c/doc/TODO
freeswitch/trunk/libs/xmlrpc-c/examples/Makefile
freeswitch/trunk/libs/xmlrpc-c/examples/auth_client.c
freeswitch/trunk/libs/xmlrpc-c/examples/cpp/Makefile
freeswitch/trunk/libs/xmlrpc-c/examples/cpp/sample_add_client_complex.cpp
freeswitch/trunk/libs/xmlrpc-c/examples/cpp/xmlrpc_sample_add_client.cpp
freeswitch/trunk/libs/xmlrpc-c/examples/cpp/xmlrpc_sample_add_server.cpp
freeswitch/trunk/libs/xmlrpc-c/examples/gen_sample_add_xml.c
freeswitch/trunk/libs/xmlrpc-c/examples/synch_client.c
freeswitch/trunk/libs/xmlrpc-c/examples/xmlrpc_asynch_client.c
freeswitch/trunk/libs/xmlrpc-c/examples/xmlrpc_loop_server.c
freeswitch/trunk/libs/xmlrpc-c/examples/xmlrpc_sample_add_client.c
freeswitch/trunk/libs/xmlrpc-c/examples/xmlrpc_sample_add_server.c
freeswitch/trunk/libs/xmlrpc-c/examples/xmlrpc_sample_add_server_cgi.c
freeswitch/trunk/libs/xmlrpc-c/examples/xmlrpc_sample_add_server_w32httpsys.c
freeswitch/trunk/libs/xmlrpc-c/examples/xmlrpc_server_validatee.c
freeswitch/trunk/libs/xmlrpc-c/include/Makefile
freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/abyss.h
freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/base.h
freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/base.hpp
freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/base_int.h
freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/client.h
freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/client.hpp
freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/client_int.h
freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/client_simple.hpp
freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/girerr.hpp
freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/girmem.hpp
freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/oldcppwrapper.hpp
freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/registry.hpp
freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/server.h
freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/server_abyss.h
freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/server_abyss.hpp
freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/timeout.hpp
freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/transport.h
freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/xml.hpp
freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/xmlparser.h
freeswitch/trunk/libs/xmlrpc-c/lib/Makefile
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/Makefile
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/Makefile
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/conf.c
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/conn.c
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/data.c
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/file.c
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/http.c
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/main.c
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/server.c
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/socket.c
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/token.c
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/token.h
freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/trace.c
freeswitch/trunk/libs/xmlrpc-c/lib/curl_transport/Makefile
freeswitch/trunk/libs/xmlrpc-c/lib/curl_transport/xmlrpc_curl_transport.c
freeswitch/trunk/libs/xmlrpc-c/lib/expat/expat.html
freeswitch/trunk/libs/xmlrpc-c/lib/expat/gennmtab/Makefile
freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmlparse/xmlparse.c
freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmlparse/xmlparse.h
freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmltok/Makefile
freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmltok/xmldef.h
freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmltok/xmlrole.c
freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmltok/xmlrole.h
freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmltok/xmltok.c
freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmltok/xmltok.h
freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmltok/xmltok_impl.c
freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmltok/xmltok_ns.c
freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmlwf/xmlfile.c
freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmlwf/xmlwf.c
freeswitch/trunk/libs/xmlrpc-c/lib/libwww_transport/Makefile
freeswitch/trunk/libs/xmlrpc-c/lib/libwww_transport/xmlrpc_libwww_transport.c
freeswitch/trunk/libs/xmlrpc-c/lib/util/Makefile
freeswitch/trunk/libs/xmlrpc-c/lib/util/casprintf.c
freeswitch/trunk/libs/xmlrpc-c/lib/util/cmdline_parser.c
freeswitch/trunk/libs/xmlrpc-c/lib/util/getoptx.c
freeswitch/trunk/libs/xmlrpc-c/lib/util/include/bool.h
freeswitch/trunk/libs/xmlrpc-c/lib/util/include/casprintf.h
freeswitch/trunk/libs/xmlrpc-c/lib/util/include/cmdline_parser.h
freeswitch/trunk/libs/xmlrpc-c/lib/util/include/mallocvar.h
freeswitch/trunk/libs/xmlrpc-c/lib/util/include/pthreadx.h
freeswitch/trunk/libs/xmlrpc-c/lib/util/pthreadx_win32.c
freeswitch/trunk/libs/xmlrpc-c/lib/wininet_transport/Makefile
freeswitch/trunk/libs/xmlrpc-c/lib/wininet_transport/xmlrpc_wininet_transport.c
freeswitch/trunk/libs/xmlrpc-c/mkinstalldirs
freeswitch/trunk/libs/xmlrpc-c/src/Makefile
freeswitch/trunk/libs/xmlrpc-c/src/cpp/Makefile
freeswitch/trunk/libs/xmlrpc-c/src/cpp/XmlRpcCpp.cpp
freeswitch/trunk/libs/xmlrpc-c/src/cpp/client.cpp
freeswitch/trunk/libs/xmlrpc-c/src/cpp/client_simple.cpp
freeswitch/trunk/libs/xmlrpc-c/src/cpp/girmem.cpp
freeswitch/trunk/libs/xmlrpc-c/src/cpp/outcome.cpp
freeswitch/trunk/libs/xmlrpc-c/src/cpp/param_list.cpp
freeswitch/trunk/libs/xmlrpc-c/src/cpp/registry.cpp
freeswitch/trunk/libs/xmlrpc-c/src/cpp/server_abyss.cpp
freeswitch/trunk/libs/xmlrpc-c/src/cpp/value.cpp
freeswitch/trunk/libs/xmlrpc-c/src/cpp/xml.cpp
freeswitch/trunk/libs/xmlrpc-c/src/test/cgi.c
freeswitch/trunk/libs/xmlrpc-c/src/test/client.c
freeswitch/trunk/libs/xmlrpc-c/src/test/parse_xml.c
freeswitch/trunk/libs/xmlrpc-c/src/test/serialize.c
freeswitch/trunk/libs/xmlrpc-c/src/test/server_abyss.c
freeswitch/trunk/libs/xmlrpc-c/src/test/test.c
freeswitch/trunk/libs/xmlrpc-c/src/test/test.h
freeswitch/trunk/libs/xmlrpc-c/src/test/value.c
freeswitch/trunk/libs/xmlrpc-c/src/test/xml_data.c
freeswitch/trunk/libs/xmlrpc-c/src/test/xml_data.h
freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_array.c
freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_authcookie.c
freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_client.c
freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_data.c
freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_datetime.c
freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_expat.c
freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_libxml2.c
freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_parse.c
freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_serialize.c
freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_server_abyss.c
freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_server_cgi.c
freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_server_w32httpsys.c
freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_struct.c
freeswitch/trunk/libs/xmlrpc-c/tools/Makefile
freeswitch/trunk/libs/xmlrpc-c/tools/turbocharger/mod_gzip.c
freeswitch/trunk/libs/xmlrpc-c/tools/xml-rpc-api2cpp/DataType.cpp
freeswitch/trunk/libs/xmlrpc-c/tools/xml-rpc-api2cpp/DataType.hpp
freeswitch/trunk/libs/xmlrpc-c/tools/xml-rpc-api2cpp/Makefile
freeswitch/trunk/libs/xmlrpc-c/tools/xml-rpc-api2cpp/XmlRpcClass.cpp
freeswitch/trunk/libs/xmlrpc-c/tools/xml-rpc-api2cpp/XmlRpcClass.hpp
freeswitch/trunk/libs/xmlrpc-c/tools/xml-rpc-api2cpp/XmlRpcFunction.cpp
freeswitch/trunk/libs/xmlrpc-c/tools/xml-rpc-api2cpp/XmlRpcFunction.hpp
freeswitch/trunk/libs/xmlrpc-c/tools/xml-rpc-api2cpp/xml-rpc-api2cpp.cpp
freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc/Makefile
freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc/xmlrpc.c
freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc/xmlrpc.html
freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_transport/Makefile
freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_transport/xmlrpc_transport.c
freeswitch/trunk/libs/xmlrpc-c/xmlrpc_config.h.in
Log:
merged new xmlrpc-c revision 1472 from https://xmlrpc-c.svn.sourceforge.net/svnroot/xmlrpc-c/trunk
Modified: freeswitch/trunk/libs/xmlrpc-c/GNUmakefile
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/GNUmakefile (original)
+++ freeswitch/trunk/libs/xmlrpc-c/GNUmakefile Fri May 23 16:56:24 2008
@@ -1,80 +1,151 @@
-ifeq ($(SRCDIR)x,x)
-SRCDIR = $(CURDIR)
-endif
-SUBDIR = .
-BUILDDIR = $(SRCDIR)
-VPATH = .:$(SRCDIR)
+include Makefile.srcdir
-include $(SRCDIR)/Makefile.config
+BLDDIR = $(CURDIR)
+SUBDIR =
-SUBDIRS = include src lib tools
+export SRCDIR
+export BLDDIR
-PROGRAMS_TO_INSTALL = xmlrpc-c-config
+include $(BLDDIR)/Makefile.version
+include $(BLDDIR)/config.mk
+
+SUBDIRS = include lib src tools examples
+
+# The reason we don't build tools and examples by default is that they
+# contain executables, which require significantly more from the
+# environment to build than libraries. Ergo, they are signficantly
+# more likely to fail to build. Indeed, when 'tools' was built by
+# default, the majority of the reported build problems were with that.
+# Since they are ancillary to the package, building them by default is
+# not worth causing the whole build to fail.
-# We're in a transition between the bloated, complex GNU
-# Autoconf/Automake style of build, in which 'configure' creates all
-# the make files, to simpler static make files. Some directories have
-# been converted; some haven't. So we have the hack of putting
-# 'xmlrpc_config.h' as the first dependency of 'all' to make sure
-# 'configure runs before anything in the case that the user neglects
-# to run 'configure' before doing 'make'.
+# As with any subdirectory, to build 'tools' or 'examples', cd to the
+# subdirectory and make there.
+
+DEFAULT_SUBDIRS = include lib src
+
+PROGRAMS_TO_INSTALL = xmlrpc-c-config
-default: xmlrpc_config.h all
+default: xmlrpc-c-config xmlrpc-c-config.test $(DEFAULT_SUBDIRS:%=%/all)
.PHONY: all
all: xmlrpc-c-config xmlrpc-c-config.test $(SUBDIRS:%=%/all)
-# We don't want the transport_config.h rule in Makefile.common:
+# The examples subdirectory is special, because even the make file in there
+# is designed to be an example. So it has to be simple and as close as
+# possible to something a person could use outside of the Xmlrpc-c source
+# tree. One ramification of that is that it does not specify dependencies
+# on other parts of the Xmlrpc-c build. That means we must separately
+# ensure that the Xmlrpc-c libraries are built before making the example
+# programs.
+#
+# It also means that you have to manually clean the examples directory
+# in order to get the examples rebuilt after you modify the Xmlrpc-c
+# libraries.
+
+examples/all: xmlrpc-c-config.test lib/all src/all include/all
+
+# Parallel make (make --jobs) is not smart enough to coordinate builds
+# between submakes, so a naive parallel make would cause certain
+# targets to get built multiple times simultaneously. That is usually
+# unacceptable. So we introduce extra dependencies here just to make
+# sure such targets are already up to date before the submake starts,
+# for the benefit of parallel make. Note that we ensure that parallel
+# make works for 'make all' in the top directory, but it may still fail
+# for the aforementioned reason for other invocations.
+
+tools/all: include/all lib/all src/all
+src/all lib/all: include/all
+src/all: lib/all
+
+MAJOR := $(XMLRPC_MAJOR_RELEASE)
+MINOR := $(XMLRPC_MINOR_RELEASE)
+POINT := $(XMLRPC_POINT_RELEASE)
+version.h: $(SRCDIR)/Makefile.version
+ rm -f $@
+ echo "/* Generated by make file rule */" >>$@
+ echo "#define XMLRPC_C_VERSION" \
+ \"Xmlrpc-c $(MAJOR).$(MINOR).$(POINT)"\"" >>$@
+ echo "#define XMLRPC_VERSION_MAJOR $(MAJOR)" >>$@
+ echo "#define XMLRPC_VERSION_MINOR $(MINOR)" >>$@
+ echo "#define XMLRPC_VERSION_POINT $(POINT)" >>$@
+
+# We don't want common.mk's rule for version.h
+OMIT_VERSION_H = Y
+
+# We don't want common.mk's rule for transport_config.h
OMIT_TRANSPORT_CONFIG_H = Y
-transport_config.h: $(BUILDDIR)/Makefile.config
+
+include transport_config.make
+
+# shell_config is a fragment to place inside a Bourne shell program that
+# sets variables that tell how the build is configured.
+
+shell_config: $(BLDDIR)/config.mk
+ rm -f $@
+ @echo "Lots of echoes to '$@' suppressed here ..."
+ @echo '#' >>$@
+ @echo '#######################################################' >>$@
+ @echo "# From '$@'" >>$@
+ @echo '#######################################################' >>$@
+ @echo 'ENABLE_ABYSS_THREADS="$(ENABLE_ABYSS_THREADS)"' >>$@
+ @echo 'ENABLE_LIBXML2_BACKEND="$(ENABLE_LIBXML2_BACKEND)"' >>$@
+ @echo 'MUST_BUILD_WININET_CLIENT="$(MUST_BUILD_WININET_CLIENT)"'>>$@
+ @echo 'MUST_BUILD_CURL_CLIENT="$(MUST_BUILD_CURL_CLIENT)"' >>$@
+ @echo 'MUST_BUILD_LIBWWW_CLIENT="$(MUST_BUILD_LIBWWW_CLIENT)"' >>$@
+ @echo 'NEED_RPATH="$(NEED_RPATH)"' >>$@
+ @echo 'NEED_WL_RPATH="$(NEED_WL)RPATH)"' >>$@
+ @echo 'LSOCKET="$(LSOCKET)"' >>$@
+ @echo 'WININET_LDADD="$(WININET_LDADD)"' >>$@
+ @echo 'WININET_RPATH="$(WININET_RPATH)"' >>$@
+ @echo 'WININET_WL_RPATH="$(WININET_WL_RPATH)"' >>$@
+ @echo 'CURL_LDADD="$(CURL_LDADD)"' >>$@
+ @echo 'CURL_RPATH="$(CURL_RPATH)"' >>$@
+ @echo 'CURL_WL_RPATH="$(CURL_WL_RPATH)"' >>$@
+ @echo 'LIBWWW_LDADD="$(LIBWWW_LDADD)"' >>$@
+ @echo 'LIBWWW_RPATH="$(LIBWWW_RPATH)"' >>$@
+ @echo 'LIBWWW_WL_RPATH="$(LIBWWW_WL_RPATH)"' >>$@
+ @echo 'XMLRPC_MAJOR_RELEASE="$(XMLRPC_MAJOR_RELEASE)"' >>$@
+ @echo 'XMLRPC_MINOR_RELEASE="$(XMLRPC_MINOR_RELEASE)"' >>$@
+ @echo 'XMLRPC_POINT_RELEASE="$(XMLRPC_POINT_RELEASE)"' >>$@
+ @echo 'FEATURE_LIST="$(FEATURE_LIST)"' >>$@
+ @echo 'PREFIX="$(PREFIX)"' >>$@
+ @echo 'HEADERINST_DIR="$(HEADERINST_DIR)"' >>$@
+ @echo 'LIBINST_DIR="$(LIBINST_DIR)"' >>$@
+ @echo 'BLDDIR="$(BLDDIR)"' >>$@
+ @echo 'ABS_SRCDIR="$(ABS_SRCDIR)"' >>$@
+ @echo '#######################################################' >>$@
+
+# We don't want config.mk's xmlrpc-c-config.test rule:
+OMIT_XMLRPC_C_CONFIG_TEST = Y
+
+xmlrpc-c-config xmlrpc-c-config.test:%: %.main shell_config
rm -f $@
- echo '/* This file was generated by a make rule */' >>$@
-ifeq ($(MUST_BUILD_WININET_CLIENT),yes)
- echo '#define MUST_BUILD_WININET_CLIENT 1' >>$@
-else
- echo '#define MUST_BUILD_WININET_CLIENT 0' >>$@
-endif
-ifeq ($(MUST_BUILD_CURL_CLIENT),yes)
- echo '#define MUST_BUILD_CURL_CLIENT 1' >>$@
-else
- echo '#define MUST_BUILD_CURL_CLIENT 0' >>$@
-endif
-ifeq ($(MUST_BUILD_LIBWWW_CLIENT),yes)
- echo '#define MUST_BUILD_LIBWWW_CLIENT 1' >>$@
-else
- echo '#define MUST_BUILD_LIBWWW_CLIENT 0' >>$@
-endif
- echo "static const char * const XMLRPC_DEFAULT_TRANSPORT =" >>$@
-ifeq ($(MUST_BUILD_LIBWWW_CLIENT),yes)
- echo '"libwww";' >>$@
-else
- ifeq ($(MUST_BUILD_CURL_CLIENT),yes)
- echo '"curl";' >>$@
- else
- ifeq ($(MUST_BUILD_WININET_CLIENT),yes)
- echo '"wininet";' >>$@
- else
- @echo 'ERROR: no client XML transport configured'; rm $@; false
- endif
- endif
-endif
+ @echo "Echoes to '$@' suppressed here ..."
+ @echo '#! /bin/sh' >>$@
+ @echo '#' >>$@
+ @echo '# This file was generated by a make rule' >>$@
+ @echo '#' >>$@
+ cat shell_config >>$@
+ cat $< >>$@
+ chmod a+rx $@
.PHONY: clean clean-local
clean: $(SUBDIRS:%=%/clean) clean-common clean-local
clean-local:
- rm -f transport_config.h
+ rm -f transport_config.h version.h
.PHONY: distclean distclean-local
distclean: $(SUBDIRS:%=%/distclean) distclean-common distclean-local
distclean-local: clean-local
- rm -f config.log config.status Makefile.config libtool
- rm -f xmlrpc_config.h xmlrpc_amconfig.h stamp-h xmlrpc-c.spec
- rm -f xmlrpc-c-config xmlrpc-c-config.test
+ rm -f config.log config.status config.mk Makefile.srcdir
+ rm -f xmlrpc_config.h xmlrpc_amconfig.h stamp-h
+ rm -f shell_config xmlrpc-c-config xmlrpc-c-config.test
+ rm -f TAGS
-.PHONY: tags
-tags: $(SUBDIRS:%=%/tags) TAGS
+check: $(SUBDIRS:%=%/check)
DISTFILES =
@@ -82,29 +153,31 @@
distdir: distdir-common
.PHONY: install
-install: $(SUBDIRS:%=%/install) install-common install-compat-hdr
-
-.PHONY: install-compat-hdr
-install-compat-hdr:
-# Install old names of header files for backward compatibility
- cd $(DESTDIR)$(HEADERINST_DIR); \
- rm -f xmlrpc.h xmlrpc_client.h xmlrpc_server.h xmlrpc_cgi.h \
- xmlrpc_server_abyss.h xmlrpc_server_w32httpsys.h \
- XmlRpcCpp.h; \
- $(LN_S) xmlrpc-c/oldxmlrpc.h xmlrpc.h; \
- $(LN_S) xmlrpc-c/client.h xmlrpc_client.h; \
- $(LN_S) xmlrpc-c/server.h xmlrpc_server.h; \
- $(LN_S) xmlrpc-c/server_cgi.h xmlrpc_cgi.h; \
- $(LN_S) xmlrpc-c/server_abyss.h xmlrpc_server_abyss.h; \
- $(LN_S) xmlrpc-c/server_w32httpsys.h xmlrpc_server_w32httpsys.h; \
- $(LN_S) xmlrpc-c/oldcppwrapper.hpp XmlRpcCpp.h ;\
+install: $(DEFAULT_SUBDIRS:%=%/install) install-common
.PHONY: dep
-dep: $(SUBDIRS:%=%/dep)
+dep: version.h $(BLDDIR)/include/xmlrpc-c/config.h $(SUBDIRS:%=%/dep)
-xmlrpc-c-config xmlrpc-c-config.test xmlrpc_config.h xmlrpc_amconfig.h \
+xmlrpc_config.h xmlrpc_amconfig.h \
:%:%.in $(SRCDIR)/configure
$(SRCDIR)/configure
-include $(SRCDIR)/Makefile.common
+include $(SRCDIR)/common.mk
+
+# A trick to catch a common user error. When you don't run 'configure',
+# you don't have a Makefile.srcdir, which means $(SRCDIR) is null.
+
+/common.mk:
+ @echo =======================================
+ @echo = You must run Configure before Make. =
+ @echo =======================================
+ false
+
+# 'tags' generates/updates an Emacs tags file, anmed TAGS, in the current
+# directory. Use with Emacs command 'find-tag'.
+
+.PHONY: tags
+tags:
+ find . -name "*.c" -o -name "*.h" -o -name "*.cpp" -o -name "*.hpp" | \
+ etags -
Modified: freeswitch/trunk/libs/xmlrpc-c/Makefile
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/Makefile (original)
+++ freeswitch/trunk/libs/xmlrpc-c/Makefile Fri May 23 16:56:24 2008
@@ -7,8 +7,11 @@
# GNU Make uses a make file named "GNUmakefile" in preference to "Makefile"
# if it exists. This package contains a "GNUmakefile".
+default: all
+
all install clean dep depend:
@echo "You must use GNU Make to build this. You are running some "
@echo "other Make. GNU Make may be installed on your system with "
@echo "the name 'gmake'. If not, see http://www.gnu.org/software ."
@echo
+ false
Added: freeswitch/trunk/libs/xmlrpc-c/Makefile.srcdir.in
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/Makefile.srcdir.in Fri May 23 16:56:24 2008
@@ -0,0 +1 @@
+SRCDIR=@abs_srcdir@
Added: freeswitch/trunk/libs/xmlrpc-c/Makefile.version
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/Makefile.version Fri May 23 16:56:24 2008
@@ -0,0 +1,11 @@
+###############################################################################
+# This is not only a make file inclusion, but a source file for the program
+# 'mkvers' in the Windows build system. The latter is very particular about
+# the format of this file. Do not change white space, add comment lines, or
+# anything!
+#
+#
+###############################################################################
+XMLRPC_MAJOR_RELEASE = 1
+XMLRPC_MINOR_RELEASE = 14
+XMLRPC_POINT_RELEASE = 99
Modified: freeswitch/trunk/libs/xmlrpc-c/README
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/README (original)
+++ freeswitch/trunk/libs/xmlrpc-c/README Fri May 23 16:56:24 2008
@@ -36,51 +36,17 @@
configure the build to use that instead. There's no really pressing
reason to do that, though.
-Once you have the prerequisite libraries installed, you can issue
-these commands:
+BUILDING, INSTALLING
+--------------------
+
+See the file doc/INSTALL.
+
+In the simplest case, it's just a conventional
$ ./configure
$ make
$ make install
-(There's supposed to be a 'make check' step in there too, to validate
-that everything built OK, but it's broken right now - 2005.01.07).
-
-To see it work, run a simple server like this:
-
- $ examples/xmlrpc_sample_add_server 8080
-
-Then run a client that does an RPC to this server:
-
- $ examples/xmlrpc_sample_add_client
-
-(I don't mean to imply that the above are consecutive shell commands;
-They can't be, because the server program runs indefinitely).
-
-Also try other sample servers and clients, described in examples/README.
-
-
-You may want to pass a '--prefix' argument to 'configure'. See
-'./configure --help' for details.
-
-You may also want to disable client XML transports that you won't be
-using. In particular, the Libwww transport can be inconvenient, because
-it typically uses about 20 shared libraries. Any XML-RPC client
-program that uses Xmlrpc-c, whether or not the program uses any of the
-libwww facilities, must attach all those libraries, and that can take
-a significant amount of time.
-
-See './configure --help' for the options that disable certain transports.
-
-
-
-WINDOWS
--------
-
-All of the above is essentially for Unix-type operating systems. To
-build and use Xmlrpc-c on Windows, see the file
-Windows/ReadMeWin32.txt.
-
ADDITIONAL INFORMATION
----------------------
Added: freeswitch/trunk/libs/xmlrpc-c/Windows/CleanAll.bat
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/Windows/CleanAll.bat Fri May 23 16:56:24 2008
@@ -0,0 +1,48 @@
+ at echo This batch file requires a powerful XDELETE program. One
+ at echo that will REMOVE whole directories recursively ...
+ at echo If you do NOT have such a program, then abort now, and
+ at echo adjust the line below ...
+ at set TEMPX=xdelete -dfrm
+ at echo set TEMPX=%TEMPX%
+ at pause
+ at echo #####################################################
+ at echo ARE YOU SURE YOU WANT TO DO THIS? Ctrl+C to abort ...
+ at echo #####################################################
+ at pause
+ at echo CleanAll: Last chance ... ctrl+c to abort ...
+ at pause
+ at echo CleanAll: Cleaning the headers ...
+call CleanWin32
+ at echo CleanAll: and removing the SOLUTION files ...
+call delsln
+ at echo CleanAll: Cleaning the gennmtab generated header ...
+ at if EXIST ..\lib\expat\xmltok\nametab.h del ..\lib\expat\xmltok\nametab.h > nul
+ at echo CleanAll: Cleaning all built binaries ...
+ at if EXIST ..\bin\*.exe del ..\bin\*.exe > nul
+ at if EXIST ..\bin\*.exp del ..\bin\*.exp > nul
+ at if EXIST ..\bin\*.ilk del ..\bin\*.ilk > nul
+ at if EXIST ..\bin\*.lib del ..\bin\*.lib > nul
+ at if EXIST ..\lib\*.lib del ..\lib\*.lib > nul
+ at if EXIST ..\lib\*.dll del ..\lib\*.dll > nul
+ at echo CleanAll: Cleaning test data files ...
+ at if EXIST ..\bin\data\*.xml del ..\bin\data\*.xml > nul
+ at if EXIST ..\bin\data\. rd ..\bin\data > nul
+ at if EXIST ..\bin\. rd ..\bin > nul
+ at echo CleanAll: Cleaning old residual built binaries ... but none should exist ...
+ at if EXIST ..\lib\expat\gennmtab\Debug\. %TEMPX% ..\lib\expat\gennmtab\Debug
+ at if EXIST ..\lib\expat\gennmtab\Release\. %TEMPX% ..\lib\expat\gennmtab\Release
+ at if EXIST ..\lib\expat\xmlparse\Debug\. %TEMPX% ..\lib\expat\xmlparse\Debug
+ at if EXIST ..\lib\expat\xmlparse\DebugDLL\. %TEMPX% ..\lib\expat\xmlparse\DebugDLL
+ at if EXIST ..\lib\expat\xmlparse\Release\. %TEMPX% ..\lib\expat\xmlparse\Release
+ at if EXIST ..\lib\expat\xmlparse\ReleaseDLL\. %TEMPX% ..\lib\expat\xmlparse\ReleaseDLL
+ at if EXIST ..\lib\expat\xmlparse\ReleaseMinSizeDLL\. %TEMPX% ..\lib\expat\xmlparse\ReleaseMinSizeDLL
+ at if EXIST ..\lib\expat\xmltok\Debug\. %TEMPX% ..\lib\expat\xmltok\Debug
+ at if EXIST ..\lib\expat\xmltok\DebugDLL\. %TEMPX% ..\lib\expat\xmltok\DebugDLL
+ at if EXIST ..\lib\expat\xmltok\Release\. %TEMPX% ..\lib\expat\xmltok\Release
+ at if EXIST ..\lib\expat\xmltok\ReleaseDLL\. %TEMPX% ..\lib\expat\xmltok\ReleaseDLL
+ at echo CleanAll: Finally, cleaning the main intermediate directories ...
+ at if EXIST Debug\. %TEMPX% Debug
+ at if EXIST Release\. %TEMPX% Release
+ at echo .
+ at echo CleanAll: Phew ... all done ...
+ at echo .
Added: freeswitch/trunk/libs/xmlrpc-c/Windows/CleanWin32.bat
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/Windows/CleanWin32.bat Fri May 23 16:56:24 2008
@@ -0,0 +1,43 @@
+ at echo Windows build
+ at echo This batch file deletes the copied header files,
+ at echo Deleting Win32 header files...
+ at echo #####################################################
+ at echo IF YOU HAVE MADE CHANGES IN ..\xmlrpc_config.h, ..\include\xmlrpc-c\config.h etc ...
+ at echo THESE CHANGES WILL BE LOST!
+ at echo You should run diffcfg.bat first to check for changes,
+ at echo and updcfg.bat if you have made changes ...
+ at echo #####################################################
+ at echo ARE YOU SURE YOU WANT TO DO THIS? Ctrl+C to abort ...
+ at echo #####################################################
+ at pause
+ at set TEMP1=
+ at if NOT EXIST ..\include\xmlrpc-c\config.h goto DN1
+del ..\include\xmlrpc-c\config.h > nul
+ at set TEMP1=%TEMP1% ..\include\xmlrpc-c\config.h
+:DN1
+ at if NOT EXIST ..\xmlrpc_config.h goto DN2
+del ..\xmlrpc_config.h > nul
+ at set TEMP1=%TEMP1% ..\xmlrpc_config.h
+:DN2
+ at if NOT EXIST ..\transport_config.h goto DN3
+del ..\transport_config.h > nul
+ at set TEMP1=%TEMP1% ..\transport_config.h
+:DN3
+ at if NOT EXIST ..\version.h goto DN4
+del ..\version.h > nul
+ at set TEMP1=%TEMP1% ..\version.h
+:DN4
+ at if NOT EXIST ..\examples\config.h goto DN5
+del ..\examples\config.h > nul
+ at set TEMP1=%TEMP1% ..\examples\config.h
+:DN5
+ at if "%TEMP1%." == "." goto ALLDN
+ at echo DELETED win32 header files.
+ at echo %TEMP1%
+ at goto END
+
+:ALLDN
+ at echo NOne to DELETE ...
+ at goto END
+
+:END
Modified: freeswitch/trunk/libs/xmlrpc-c/Windows/ConfigureWin32.bat
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/Windows/ConfigureWin32.bat (original)
+++ freeswitch/trunk/libs/xmlrpc-c/Windows/ConfigureWin32.bat Fri May 23 16:56:24 2008
@@ -1,7 +1,35 @@
- at echo off
-echo creating Win32 header files...
-copy .\xmlrpc_win32_config.h ..\config.h
-copy .\xmlrpc_win32_config.h ..\xmlrpc_config.h
-copy .\transport_config_win32.h ..\transport_config.h
-echo completed creating win32 header files.
-pause
+ at REM Windows build
+ at REM This must be RUN once to establish some header files,
+ at REM that are generated by the automake process
+ at echo creating Win32 header files...once only
+ at set TEMPV=
+ at if EXIST ..\include\xmlrpc-c\config.h goto DN1
+copy .\win32_config.h ..\include\xmlrpc-c\config.h > nul
+ at set TEMPV=%TEMPV% ..\include\xmlrpc-c\config.h
+:DN1
+ at if EXIST ..\xmlrpc_config.h goto DN2
+copy .\xmlrpc_win32_config.h ..\xmlrpc_config.h > nul
+ at set TEMPV=%TEMPV% ..\xmlrpc_config.h
+:DN2
+ at if EXIST ..\transport_config.h goto DN3
+copy .\transport_config_win32.h ..\transport_config.h > nul
+ at set TEMPV=%TEMPV% ..\transport_config.h
+:DN3
+ at if EXIST ..\version.h goto DN4
+call mkvers
+ at set TEMPV=%TEMPV% ..\version.h
+:DN4
+ at if EXIST ..\examples\config.h goto DN5
+copy .\xmlrpc_win32_config.h ..\examples\config.h > nul
+ at set TEMPV=%TEMPV% ..\examples\config.h
+:DN5
+ at if "%TEMPV%." == "." goto ALLDN
+ at echo Generated the following win32 header files ...
+ at echo %TEMPV%
+ at goto END
+
+:ALLDN
+ at echo Using previous copies ... Use CleanWin32.bat to remove, and do again ...
+ at goto END
+
+:END
Added: freeswitch/trunk/libs/xmlrpc-c/Windows/ReadMeOld.txt
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/Windows/ReadMeOld.txt Fri May 23 16:56:24 2008
@@ -0,0 +1,125 @@
+Current information is in ReadMeWin32.txt.
+
+What follows is previous contents of that file.
+
+
+
+Markus Hoffrogge:
+
+Compilation for WIN32 is possible now again for version 1.6.10 - non
+CPP parts only. Project files have been tested under VicualStudio
+6.0. Build project all - this will build all other projects. CPP
+code is not compiled and adopted right now.
+
+This release excludes the option to compile an "http.sys" version of
+an XML-RPC server. If you do wish to build in the http.sys server, set
+the MUST_BUILD_HTTP_SYS_SERVER to 1 in the transport_config_win32.h
+and/or the transport_config.h file. Successful conpilation requires
+installation of the Microsoft Platform SDK for Windows XP SP2 (or
+later) to get the latest header and link libraries required to support
+this functionality. After installation, be sure to properly register
+the directories as documented in the Platform SDK help file topic
+"Installing the Platform SDK with Visual Studio". Download the
+Platform SDK from:
+http://www.microsoft.com/msdownload/platformsdk/sdkupdate/
+
+To create the three headers required for Win32 WinInet compilation,
+run the ConfigureWin32.bat found in the Windows directory. If you
+wish to alter the transports that are built to include curl or libwww,
+adjust the preprocessor definitions at the top of the
+transport_config_win32.h and/or the transport_config.h files. See the
+file UsingCURLinWin32.txt for more information on using the curl
+transport.
+
+To compile, open the xmlrpc.dsw file in Visual Studio 6 or greater.
+The project will convert and work fine in Visual Studio 2003 as well -
+other versions of Visual Studio were not tested.
+
+NOTE: If you get an error while opening or converting the project
+files, it is likely due to using WinRar or similar to decompress the
+distribution tarball. You can use WinZip or another utility to
+correctly decompress the .tgz file.
+
+Suggested testing for evaluation of the library involves a few
+projects. Here is a quick getting started guide:
+
+1) Set the Active Project to query_meerkat and build it in release or
+ debug modes. The dependent projects will be built automatically.
+ In the project settings dialog, add the argument for what you wish
+ to query meerkat for - "Windows" is a good query. Run the project.
+ This will query the meerkat server for articles related to windows
+ and output the results to the console.
+
+2) Set the Active Project to xmlrpc_sample_add_server and build it in
+ release or debug modes. The dependent projects will be built
+ automatically. In the project settings dialog, add the argument
+ for the port to 8080. This will run the server sample which adds
+ two numbers and returns a result. You should run this from a
+ command prompt instead of through Visual Studio so you may run the
+ sample client as well.
+
+3) Set the Active Project to xmlrpc_sample_add_sync_client or
+ xmlrpc_sample_add_async_client and build it in release or debug
+ modes. The dependent projects will be built automatically. This
+ will run the client sample which submits two numbers to be added to
+ the server application as described above and displays the result.
+ Note that the client example comes in the sync and async varieties.
+
+Steven Bone
+July 27, 2005
+sbone at pobox.com
+
+WIN32 CHANGES
+
+Changes from the 1.02 release for Win32:
+
+1) Option to easily disable the http.sys server for those who do not
+ need it or wish to download the Platform SDK.
+
+Changes from the 1.01 -> 1.02 release for Win32:
+
+1) Project files for gennmtab, xmlparse, and xmltok updated to include the
+ path to the xmlrpc_config.h file.
+
+2) Bugfix for WinInet authentication.
+
+3) Supports xmlrpc_xportparms, xmlrpc_wininet_xportparms added
+ *potential breaking change* - now by default we fail on invalid
+ SSL certs, use the xmlrpc_wininet_xportparms option to enable old
+ behavior.
+
+4) Added project file for xmlrpc_sample_auth_client
+
+5) Added project and src for a http.sys based xmlrpc-c server. See comments
+ in the source files. This supports Windows XP SP2 and Windows Server
+ 2003 and allows other http.sys based applications to bind to the same
+ port. In Server 2003, IIS uses http.sys and thus the XML-RPC server
+ can be run on the standard port 80 along with IIS. The sample also
+ supports https and basic authentication. It tested OK with
+ http://validator.xmlrpc.com/ Note that the Platform SDK headers and
+ link libraries for Windows XP SP2 or newer are required to compile
+ xmlrpc-c for this module. If you are not using this server, it is
+ safe to exclude the xmlrpc_server_w32httpsys.c file from the xmlrpc
+ project and these dependencies will not be required. You can get the
+ latest platform SDK at
+ http://www.microsoft.com/msdownload/platformsdk/sdkupdate/
+ Be sure after installation to choose the program to "register the PSDK
+ directories with Visual Studio" so the newer headers are found.
+
+6) Better support for libcurl. Updated project files,
+ transport_config_win32.h, added documentation UsingCURLinWin32.txt.
+
+Changes from the 1.00 -> 1.01 release for Win32:
+
+1) Project files now reflect static linking for the expat XML library.
+
+2) Example projects were created/updated to keep them in sync with the
+ distribution. The project files were moved into the Windows
+ directory
+
+3) Projects for the rpc and cpp tests were created. The
+ xmlrpc_win32_config.h defines the directory for the test files relative
+ to the output directory
+
+4) Major refactoring of the Wininet Transport.
+
Modified: freeswitch/trunk/libs/xmlrpc-c/Windows/ReadMeWin32.txt
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/Windows/ReadMeWin32.txt (original)
+++ freeswitch/trunk/libs/xmlrpc-c/Windows/ReadMeWin32.txt Fri May 23 16:56:24 2008
@@ -1,116 +1,64 @@
-Build Instructions For XML-RPC For C/C++ On Windows
----------------------------------------------------
-
-The following instructions do not fully work in this release. There
-is no trivial way to build this release for Windows. The last release
-that was known to build without special effort on the part of the user
-is 1.02.
-
-Since then, nobody has maintained the code for Windows, and changes that
-were made for other platforms broke some things for Windows. Most likely,
-anyone with a passing knowledge of building C code on Windows could
-update this code to work on Windows without any in-depth study of it. If
-you do so, please contribute your work to save other users the trouble.
-
-The majority of the work that needs to be done to make the code build on
-Windows is simply adjusting project files to reflect the fact that files
-have been created, deleted, and moved since they were written.
-
-
-This release includes the option to compile the "http.sys" version of the
-XMLRPC-C server. If you do not wish to build in the http.sys server,
-set the MUST_BUILD_HTTP_SYS_SERVER to 0 in the transport_config_win32.h and/or
-the transport_config.h file. Successful conpilation requires installation
-of the Microsoft Platform SDK for Windows XP SP2 (or later) to get the latest
-header and link libraries required to support this functionality. After
-installation, be sure to properly register the directories as documented
-in the Platform SDK help file topic "Installing the Platform SDK with
-Visual Studio". Download the Platform SDK from:
-http://www.microsoft.com/msdownload/platformsdk/sdkupdate/
-
-To create the three headers required for Win32 WinInet compilation, run the
-ConfigureWin32.bat found in the Windows directory. If you wish to alter the
-transports that are built to include curl or libwww, adjust the preprocessor
-definitions at the top of the transport_config_win32.h and/or
-the transport_config.h files. See the file UsingCURLinWin32.txt for
-more information on using the curl transport.
-
-To compile, open the xmlrpc.dsw file in Visual Studio 6 or greater. The
-project will convert and work fine in Visual Studio 2003 as well -
-other versions of Visual Studio were not tested.
-NOTE: If you get an error while opening or converting the project files,
-it is likely due to using WinRar or similar to decompress the distribution
-tarball. You can use WinZip or another utility to correctly decompress the
-.tgz file.
-
-Suggested testing for evaluation of the library involves a few projects.
-Here is a quick getting started guide:
-
-1) Set the Active Project to query_meerkat and build it in release or debug
- modes. The dependent projects will be built automatically. In the
- project settings dialog, add the argument for what you wish to query
- meerkat for - "Windows" is a good query. Run the project. This will
- query the meerkat server for articles related to windows and output the
- results to the console.
-
-2) Set the Active Project to xmlrpc_sample_add_server and build it in
- release or debug modes. The dependent projects will be built
- automatically. In the project settings dialog, add the argument for
- the port to 8080. This will run the server sample which adds two
- numbers and returns a result. You should run this from a command
- prompt instead of through Visual Studio so you may run the sample
- client as well.
-
-3) Set the Active Project to xmlrpc_sample_add_sync_client or
- xmlrpc_sample_add_async_client and build it in release or debug modes.
- The dependent projects will be built automatically. This will run
- the client sample which submits two numbers to be added to the server
- application as described above and displays the result. Note that the
- client example comes in the sync and async varieties.
-
-Steven Bone
-July 27, 2005
-sbone at pobox.com
-
-WIN32 CHANGES
-
-Changes from the 1.02 release for Win32:
-1) Option to easily disable the http.sys server for those who do not need
- it or wish to download the Platform SDK.
-
-Changes from the 1.01 -> 1.02 release for Win32:
-1) Project files for gennmtab, xmlparse, and xmltok updated to include the
- path to the xmlrpc_config.h file.
-2) Bugfix for WinInet authentication.
-3) Supports xmlrpc_xportparms, xmlrpc_wininet_xportparms added
- *potential breaking change* - now by default we fail on invalid
- SSL certs, use the xmlrpc_wininet_xportparms option to enable old
- behavior.
-4) Added project file for xmlrpc_sample_auth_client
-5) Added project and src for a http.sys based xmlrpc-c server. See comments
- in the source files. This supports Windows XP SP2 and Windows Server
- 2003 and allows other http.sys based applications to bind to the same
- port. In Server 2003, IIS uses http.sys and thus the XML-RPC server
- can be run on the standard port 80 along with IIS. The sample also
- supports https and basic authentication. It tested OK with
- http://validator.xmlrpc.com/ Note that the Platform SDK headers and
- link libraries for Windows XP SP2 or newer are required to compile
- xmlrpc-c for this module. If you are not using this server, it is
- safe to exclude the xmlrpc_server_w32httpsys.c file from the xmlrpc
- project and these dependencies will not be required. You can get the
- latest platform SDK at
- http://www.microsoft.com/msdownload/platformsdk/sdkupdate/
- Be sure after installation to choose the program to "register the PSDK
- directories with Visual Studio" so the newer headers are found.
-6) Better support for libcurl. Updated project files, transport_config_win32.h,
- added documentation UsingCURLinWin32.txt.
-
-Changes from the 1.00 -> 1.01 release for Win32:
-1) Project files now reflect static linking for the expat XML library.
-2) Example projects were created/updated to keep them in sync with the
- distribution. The project files were moved into the .\Windows
- directory
-3) Projects for the rpc and cpp tests were created. The
- xmlrpc_win32_config.h defines the directory for the test files relative
- to the output directory
-4) Major refactoring of the Wininet Transport.
\ No newline at end of file
+Build Instructions For XML-RPC For C/C++ On Windows
+---------------------------------------------------
+
+Latest Windows work was done by
+
+ Geoff McLane
+ 19 October, 2007
+ home: http://geoffair.net
+
+
+1. Run the batch file ConfigureWin32.bat, found in the Windows
+directory. This will copy four(4) headers to the appropriate folders.
+
+2. Load xmlrpc.dsw in MSVC[7,8] or later, and build the Release or Debug
+configurations. DLL configurations are not included, and may not compile.
+
+This build requires that you have a Microsoft SDK, or Plaform SDK
+installed, since among other things, it uses <http.h>, and
+HTTPAPI.LIB, from the SDK.
+
+Once built, the rpctest.exe, in the bin folder, should run with no errors,
+and the xmlrpc_sample_add_server.exe, using port 8080, and
+xmlrpc_sample_add_sync_client.exe should communicate ... proving 7+5 = 12 ;=))
+
+Have fun.
+
+PS: Several other batch files are included in the Windows folder ...
+
+delsln.bat - to delete all the MSVC7 and 8 solution file.
+
+diffcfg.bat - compare the headers in windows with the version used in
+the compile. Requires diff.exe to be in the path.
+
+updcfg.bat - copy the 3 manually maintained configuration files back
+to the Windows folder (for distribution).
+
+cleawin32.bat - deletes the headers used in the compile. That is does the
+opposite of ConfigureWin32.bat.
+
+cleanall.bat - to remove ALL the binary files created. Requires an xdelete
+program which will recursively delete an entire folder.
+
+
+There is some historical information in ReadMeOld.txt, which used to be
+the contents of this file. Some of it is still valid.
+
+
+Developing XML-RPC For C/C++ for Windows
+----------------------------------------
+
+If you fix or enhance something in the Windows build system, please send
+your updates to the Xmlrpc-c maintainer to be included in future releases
+so others don't have to repeat your work.
+
+Output of a Subversion 'diff' is usually the best way to send updates,
+but you can also send complete files or just a description of the
+change if that is easier.
+
+For the project files, we distribute only MSVC6-compatible DSP and DSW
+files (which are, of course, usable as input to later versions of MSVC
+as well). That means if you need to modify something in the project
+files and you are not using MSVC6, you must edit the project files
+manually as text files. Modifying them via the IDE would simply
+generate new files in a format that cannot be used with older MSVC.
Modified: freeswitch/trunk/libs/xmlrpc-c/Windows/UsingCURLinWin32.txt
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/Windows/UsingCURLinWin32.txt (original)
+++ freeswitch/trunk/libs/xmlrpc-c/Windows/UsingCURLinWin32.txt Fri May 23 16:56:24 2008
@@ -1,64 +1,128 @@
-Background:
-Lets say you need to support a xmlrpc-c client running as a service. In this
-situation you cannot use WinInet. Details of the restriction can be found on
-the libcurl website or various Microsoft KB articles. The alternative is to use
-libcurl. This document describes the steps required to use libcurl as your
-transport mechanism as supported by the latest files and projects provided in
-the xmlrpc-c distribution. The assumption is that you can successfully compile
-the distribution of xmlrpc-c.
-
-Overview:
-The default projects in xmlrpc-c create standalone executables that do not
-require other DLLs (release mode). While the case can be made for this
-behavior pro and con, it is beyond this document to justify it. Therefore, we
-need to create static link libraries for libcurl that mimics this behavior.
-Once the link libraries are created, we can then add them (plus the requisite
-curl headers) into the xmlrpc-c project. Finally, we enable the compilation of
-the curl transport file and tell xmlrpc-c that we will be using curl. Lastly,
-we build and test the project.
-
-Steps to use CURL with Win32 xmlrpc-c:
-1. Download the CURL source. In the include folder of the CURL distribution,
-copy the curl directory to the lib directory of xmlbpc-c. When you are done
-with this step, you should have a curl.h file located in the directory
-xmlrpc-c\lib\curl\. The xmlrpc project looks in this relative path for the
-necessary headers.
-
-2. In the CURL distribution, lib directory, is a file called Makefile.vc6. Edit
-this file. The line starting with CCNODBG should be changed to:
-CCNODBG = cl.exe /MT /O2 /DNDEBUG
-The /MT option links with the Multithreaded non-dll version of the c runtime.
-If this change is not made, the project will not link, as this is the default
-setting for the xmlrpc-c projects. In debug mode, we use the dll version of the
-c runtime as it makes memory leak checking tools work better.
-
-3. Open a command prompt window and run the vcvars32.bat file in your Visual C++
-distribution. If you are using Studio 2002 or 2003, use the Visual Studio
-Command Prompt from the Start menu to open the console.
-
-4. Compile release and debug mode libraries. For the purposes of this tutorial,
-we are going to build only the curl library without ssl or zlib support. In the
-command prompt, navigate to the curl\lib directory and execute the following
-commands:
-nmake -f Makefile.vc6 CFG=debug
-nmake -f Makefile.vc6 CFG=release
-
-5. The above step should have generated two static link libraries in the
-curl\lib directory: libcurl.lib and libcurld.lib. Copy these files into the
-root of the xmlrpc-c\lib\ directory. This step ends our involvement with the
-actual CURL distribution. The remainder of the steps are for XMLRPC-C.
-
-6. Open the xmlrpc-c Visual Studio workspace (Instructions for VC++ 6, other
-versions are slightly different). In File View, expand the xmlrpc project.
-Under Source Files there is an entry for xmlrpc_curl_transport.c This is not
-included in any build paths by default. To enable it for compilation, right
-click the file to change the settings. In the dropdown, select All
-Configurations. Pick the General tab and uncheck the Exclude File From Build
-setting. Press OK to save your changes to the project.
-
-7. In the Header Files section of the xmlrpc project is a file called
-transport_config.h. Edit this file to set the MUST_BUILD_CURL_CLIENT to 1,
-and if you wish to change the default transport to curl, change the
-XMLRPC_DEFAULT_TRANSPORT to curl.
-
-8. Compile and test one or more of the sample client projects.
+Background:
+
+Lets say you need to have a Xmlrpc-c client running as a service.
+In this situation you cannot use WinInet. Details of the restriction
+can be found on the libcurl website or various Microsoft KB articles.
+The alternative is to use libcurl. This document describes the steps
+required to use libcurl as your client XML transport mechanism.
+
+Overview:
+
+The default projects in Xmlrpc-c create standalone executables that do
+not require other DLLs (release mode). While the case can be made
+for this behavior pro and con, it is beyond this document to justify
+it. Therefore, we need to create static link libraries for libcurl
+that mimics this behavior. Once the link libraries are created, we
+can then add them (plus the requisite curl headers) into the Xmlrpc-c
+project. Finally, we enable the compilation of the curl transport
+file and tell Xmlrpc-c that we will be using curl. Lastly, we build
+and test the project.
+
+Steps to use CURL with Win32 Xmlrpc-c:
+
+1. Download the CURL source. In the include folder of the
+CURL distribution, copy the curl directory to the lib
+directory of xmlrpc-c. When you are done with this step, you should
+have a curl.h file located in the directory xmlrpc-c\lib\curl\. The
+xmlrpc project looks in this relative path for the necessary headers.
+
+2. In the CURL distribution, lib directory, is a file called
+Makefile.vc6. Edit this file. The line starting with CCNODBG should
+be changed to:
+
+CCNODBG = cl.exe /MT /O2 /DNDEBUG
+
+The /MT option links with the Multithreaded non-dll version of the c
+runtime. If this change is not made, the project will not link, as
+this is the default setting for the Xmlrpc-c projects.
+
+3. Open a command prompt window and run the vcvars32.bat file in your
+Visual C++ distribution. If you are using Studio 2002 or 2003, use
+the Visual Studio Command Prompt from the Start menu to open
+the console.
+
+4. Compile release and debug mode libraries. For the purposes of this
+tutorial, we are going to build only the curl library without ssl or
+zlib compression capability. In the command prompt, navigate to the
+curl\lib directory and execute the following commands:
+
+nmake -f Makefile.vc6 CFG=debug RTLIBCFG=static
+nmake -f Makefile.vc6 CFG=release RTLIBCFG=static
+
+5. The above step should have generated two static link libraries in
+the curl\lib directory: libcurl.lib and libcurld.lib. Copy these
+files into the root of the xmlrpc-c\lib\ directory. This step ends
+our involvement with the actual CURL distribution. The remainder of
+the steps are for Xmlrpc-c.
+
+6. Open the Xmlrpc-c Visual Studio workspace (Instructions for VC++ 6,
+other versions are slightly different). In File View, expand the
+xmlrpc project. Under "Source Files" there is an entry for
+xmlrpc_curl_transport.c This is not included in any build paths by
+default. To enable it for compilation, right click the file to change
+the settings. In the dropdown, select "All Configurations." Pick the
+General tab and uncheck the "Exclude File From Build" setting. Press
+OK to save your changes to the project.
+
+7. In the "Header Files" section of the xmlrpc project is a file
+called "transport_config.h". Edit this file to set the
+MUST_BUILD_CURL_CLIENT to 1, and if you wish to change the default
+transport to curl, change the XMLRPC_DEFAULT_TRANSPORT to "curl".
+
+8. Compile and test one or more of the sample client projects.
+
+USING MSVC8 - 2007/11/25
+========================
+
+This is for MSVC8, but most will apply to all version of Microsoft
+Visual Studio.
+
+Download the CURL source. Run the buildconf.bat to generate some
+additional files. This builds a 'dummy' hugehelp.c, but it can also
+be built using the src\mkhelp.pl Perl script. You may have to build
+you own VCPROJ file for CURL, if you want to use MSVC. It does
+provide a Makefile.vc6 as mentioned above.
+
+To build all the CURL library variations, use
+> nmake /nologo vc-all
+but note this will use the /MD[d] DLL runtime. Only by adding
+RTCFGLIB=static to each of the makefile commands will /MT[d] be
+used.
+
+Essentially, for building the static Debug or Release CURL libraries,
+it is all the sources in the curl\lib folder. Make sure you choose /MT
+and /MTd for the runtime, and build both using say the name libcurl.lib.
+
+When you have Debug\libcurl.lib and Release\libcurl.lib built, you
+are ready to build and link them with Xmlrpc-c.
+
+After running xmlrpc-c\Windows\configurewin32.bat, loading xmlrpc.dsw
+will convert all the projects to VCPROJ files. In the File View, in
+the xmlrpc project, in the properties of xmlrpc_curl_transport.c,
+change 'Exclude file from build' from 'yes' to 'no', for Debug
+and Release.
+
+In the 'Header Files' section, open the "transport_config.h" file,
+and change MUST_BUILD_CURL_CLIENT to 1, and the XMLRPC_DEFAULT_TRANSPORT
+to "curl", if desired.
+
+As usual, for each of the 'client' projects, and rpctest, in the properties,
+Linker section, you can add the library libcurl.lib on the Input tab, and
+the relative path to the library in the General tab to something like -
+..\..\curl\Debug and ..\..\curl\Release, or where ever you built or
+copied these static libraries too.
+
+Or you can adjust the Windows/curlink.h, to directly point to your
+respective Debug and Release static CURL libraries, either where you
+built them, or where you copied them too.
+
+Now, Xmlrpc-c should build using the CURL transport.
+
+Note, for the final linking, all RUNTIME libraries MUST be the SAME.
+A mixture of /MD and /MT will give big linkage problems. Any one project
+built with the alterate RUNTIME will show many items defined more than
+once. And of course, you can also NOT mix Debug with Release. That is
+/MDd with /MD, nor /MTd with /MT, or else there will be unresolved
+debug items.
+
+EOF
Added: freeswitch/trunk/libs/xmlrpc-c/Windows/UsingProxyDSP.txt
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/Windows/UsingProxyDSP.txt Fri May 23 16:56:24 2008
@@ -0,0 +1,51 @@
+
+Using xmlrpc_cpp_proxy.dsp
+
+While not included in the main xmlrpc.dsw file, this
+xmlrpc_cpp_proxy.dsp, if added as a project to the xmlrpc solution,
+will build bin\xmlrpc_cpp_proxy.exe and xmlrpc_cpp_proxyD.exe, for
+testing using the default WinINET transport.
+
+After you have loaded the xmlrpc_cpp_proxy.dsp, which adds an
+xmlrpc_cpp_proxy project, it is necessary to ADD a dependance on
+the xmlrpc library, to complete the link.
+
+To do this in say MSVC8, select the xmlrpc_cpp_proxy project, and right
+mouse click, and in the context menu, select 'Project Dependancies...'.
+And in the Project Dependancies dialog, check the xmlrpc proejct,
+then [Ok] ...
+
+To test your xmlrpc_cpp_proxy[D].exe -
+
+
+1. In a console start the server, like -
+
+bin/xmlrpc_sample_add_serverD 8080
+
+Note, since this server opens a socket, you may have to enable it on some
+anti-virus software that detects the socket being established, and
+'Unblock' it in the Windows Security Alert system dialog that appears.
+
+You can later remove this program from the Firewall exceptions, through
+Control Panel -> Windows Firewall, selecting the 'Exceptions' tab, where
+you can also disable this 'blocking' notification, but not recommended.
+
+The server should start, and report -
+Running XML-RPC server...
+
+
+2. In another console run the cpp proxy client, with say -
+
+bin>xmlrpc_cpp_proxyD http://localhost:8080/RPC2 null null
+
+The client should connect to the server, and output a 'null' header,
+and implementation file. If this functions, for a bigger example, try -
+
+bin>xmlrpc_cpp_proxyD http://localhost:8080/RPC2 system systemProxy
+
+and you should see a better example of a class header, and the
+implementation code ...
+
+20 December, 2007
+
+EOF
Added: freeswitch/trunk/libs/xmlrpc-c/Windows/abyss.dsp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/Windows/abyss.dsp Fri May 23 16:56:24 2008
@@ -0,0 +1,252 @@
+# Microsoft Developer Studio Project File - Name="abyss" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=abyss - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "abyss.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "abyss.mak" CFG="abyss - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "abyss - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "abyss - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "abyss - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release\Abyss"
+# PROP Intermediate_Dir "Release\Abyss"
+# PROP Target_Dir ""
+MTL=midl.exe
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\\" /I "..\include" /I "..\lib\util\include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "ABYSS_WIN32" /D "_THREAD" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib\abyss.lib"
+
+!ELSEIF "$(CFG)" == "abyss - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug\abyss"
+# PROP Intermediate_Dir "Debug\abyss"
+# PROP Target_Dir ""
+MTL=midl.exe
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\\" /I "..\include" /I "..\lib\util\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "ABYSS_WIN32" /D "_THREAD" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib\abyssD.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "abyss - Win32 Release"
+# Name "abyss - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\channel.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\chanswitch.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\conf.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\conn.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\data.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\date.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\file.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\handler.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\http.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\init.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\response.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\server.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\session.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\socket.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\socket_openssl.c
+# PROP Exclude_From_Build 1
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\socket_unix.c
+# PROP Exclude_From_Build 1
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\socket_win.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\thread_fork.c
+# PROP Exclude_From_Build 1
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\thread_pthread.c
+# PROP Exclude_From_Build 1
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\thread_windows.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\token.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\trace.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\abyss_info.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\channel.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\chanswitch.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\conn.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\data.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\date.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\file.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\handler.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\http.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\server.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\session.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\socket.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\socket_win.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\thread.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\token.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\trace.h
+# End Source File
+# End Group
+# End Target
+# End Project
Added: freeswitch/trunk/libs/xmlrpc-c/Windows/configwin32.dsp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/Windows/configwin32.dsp Fri May 23 16:56:24 2008
@@ -0,0 +1,97 @@
+# Microsoft Developer Studio Project File - Name="configwin32" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) External Target" 0x0106
+
+CFG=configwin32 - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "configwin32.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "configwin32.mak" CFG="configwin32 - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "configwin32 - Win32 Release" (based on "Win32 (x86) External Target")
+!MESSAGE "configwin32 - Win32 Debug" (based on "Win32 (x86) External Target")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+
+!IF "$(CFG)" == "configwin32 - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Cmd_Line "ConfigureWin32.bat"
+# PROP BASE Rebuild_Opt ""
+# PROP BASE Target_File "../config.h"
+# PROP BASE Bsc_Name ""
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Cmd_Line "ConfigureWin32.bat"
+# PROP Rebuild_Opt ""
+# PROP Target_File "../config.h"
+# PROP Bsc_Name ""
+# PROP Target_Dir ""
+
+!ELSEIF "$(CFG)" == "configwin32 - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Cmd_Line "ConfigureWin32.bat"
+# PROP BASE Rebuild_Opt ""
+# PROP BASE Target_File "../config.h"
+# PROP BASE Bsc_Name ""
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir ""
+# PROP Cmd_Line "ConfigureWin32.bat"
+# PROP Rebuild_Opt ""
+# PROP Target_File "../config.h"
+# PROP Bsc_Name ""
+# PROP Target_Dir ""
+
+!ENDIF
+
+# Begin Target
+
+# Name "configwin32 - Win32 Release"
+# Name "configwin32 - Win32 Debug"
+
+!IF "$(CFG)" == "configwin32 - Win32 Release"
+
+!ELSEIF "$(CFG)" == "configwin32 - Win32 Debug"
+
+!ENDIF
+
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
Modified: freeswitch/trunk/libs/xmlrpc-c/Windows/cpptest.dsp
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/Windows/cpptest.dsp (original)
+++ freeswitch/trunk/libs/xmlrpc-c/Windows/cpptest.dsp Fri May 23 16:56:24 2008
@@ -1,102 +1,121 @@
-# Microsoft Developer Studio Project File - Name="cpptest" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=cpptest - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "cpptest.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "cpptest.mak" CFG="cpptest - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "cpptest - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "cpptest - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName "cpptest"
-# PROP Scc_LocalPath ".."
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "cpptest - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release\cpptest"
-# PROP Intermediate_Dir "Release\cpptest"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\\" /I "..\src" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ..\lib\xmlrpc.lib /nologo /subsystem:console /machine:I386 /out:"..\bin\cpptest.exe"
-
-!ELSEIF "$(CFG)" == "cpptest - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug\cpptest"
-# PROP Intermediate_Dir "Debug\cpptest"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\\" /I "..\src" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ..\lib\xmlrpcD.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\bin\cpptest.exe" /pdbtype:sept
-
-!ENDIF
-
-# Begin Target
-
-# Name "cpptest - Win32 Release"
-# Name "cpptest - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=..\src\cpptest.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
+# Microsoft Developer Studio Project File - Name="cpptest" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=cpptest - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "cpptest.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "cpptest.mak" CFG="cpptest - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "cpptest - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "cpptest - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "cpptest - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release\cpptest"
+# PROP Intermediate_Dir "Release\cpptest"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I ".." /I "../include" /I "../lib/util/include" /I "../.." /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "ABYSS_WIN32" /D "CURL_STATICLIB" /D "_CRT_SECURE_NO_WARNINGS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 ..\lib\xmlrpccpp.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Ws2_32.lib Wininet.lib /nologo /subsystem:console /machine:I386 /out:"..\bin\cpptest.exe"
+
+!ELSEIF "$(CFG)" == "cpptest - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug\cpptest"
+# PROP Intermediate_Dir "Debug\cpptest"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../.." /I ".." /I "../include" /I "../lib/util/include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "ABYSS_WIN32" /D "CURL_STATICLIB" /D "_CRT_SECURE_NO_WARNINGS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\xmlrpccppD.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Ws2_32.lib Wininet.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\bin\cpptestD.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "cpptest - Win32 Release"
+# Name "cpptest - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\src\cpp\test\registry.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\cpp\test\server_abyss.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\cpp\test\server_pstream.cpp
+# PROP Exclude_From_Build 1
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\cpp\test\test.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\cpp\test\testclient_dummy.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\cpp\test\tools.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
Added: freeswitch/trunk/libs/xmlrpc-c/Windows/curllink.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/Windows/curllink.h Fri May 23 16:56:24 2008
@@ -0,0 +1,18 @@
+/* We use pragma statements to tell the linker what we need to link
+ with. Since Curl requires Winsock, Winmm, and libcurl, and no other
+ project does, we include this file into the Curl transport source code
+ to tell the linker to add these libs.
+
+ Alternatively, the USER can add the libraries to LINK with as
+ NEEDED!
+*/
+
+#ifdef _DEBUG
+#pragma comment( lib, "C:\\FG\\FGCOMXML\\curl\\build\\Debug\\Lib_curl.lib" )
+#else
+#pragma comment( lib, "C:\\FG\\FGCOMXML\\curl\\build\\Release\\Lib_curl.lib" )
+#endif
+
+#pragma comment( lib, "Winmm.lib" )
+#pragma comment( lib, "Ws2_32.lib" )
+#pragma comment( lib, "Wldap32.lib" )
Added: freeswitch/trunk/libs/xmlrpc-c/Windows/delsln.bat
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/Windows/delsln.bat Fri May 23 16:56:24 2008
@@ -0,0 +1,56 @@
+ at echo Delete the MSVC7 or MSVC8 soultion files ...
+ at echo *****************************************************
+ at echo ARE YOU SURE YOU WANT TO DO THIS? Ctrl+C to ABORT ...
+ at echo *****************************************************
+ at pause
+ at echo Deleting SOLUTION files ...
+ at if EXIST *.sln del *.sln > nul
+ at if EXIST *.vcproj del *.vcproj > nul
+ at if EXIST *.old echo Deleting *.old ...
+ at if EXIST *.old Del *.old > nul
+ at if EXIST *.bak echo Deleting *.bak ...
+ at if EXIST *.bak Del *.bak > nul
+ at if NOT EXIST temp*.* goto dntmp
+ at echo Delete temp*.* ...
+ at del temp*.* > nul
+:dntmp
+ at if NOT EXIST *.obj goto dnobj
+ at echo Delete *.obj ...
+ at del *.obj > nul
+:dnobj
+ at if NOT EXIST *.err goto dnerr
+ at echo Delete *.err ...
+ at del *.err > nul
+:dnerr
+ at if NOT EXIST *.pdb goto dnpdb
+ at echo Delete *.pdb ...
+ at del *.pdb > nul
+:dnpdb
+ at if NOT EXIST *.lst goto dnlst
+ at echo Delete *.lst ...
+ at del *.lst > nul
+:dnlst
+ at if EXIST *.pch echo Deleting *.pch ...
+ at if EXIST *.pch Del *.pch > nul
+ at if EXIST *.ilk echo Deleting *.ilk ...
+ at if EXIST *.ilk Del *.ilk > nul
+ at if EXIST *.NCB echo Deleting *.NCB ...
+ at if EXIST *.NCB Del *.NCB > nul
+ at if EXIST *.plg echo Deleting *.plg ...
+ at if EXIST *.plg Del *.plg > nul
+ at if EXIST *.OPT echo Deleting *.OPT ...
+ at if EXIST *.OPT Del *.OPT > nul
+ at if EXIST *.idb echo Deleting *.idb ...
+ at if EXIST *.idb Del *.idb > nul
+ at if EXIST *.aps echo Deleting *.aps ...
+ at if EXIST *.aps Del *.aps > nul
+ at if EXIST *.sbr echo Deleting *.sbr ...
+ at if EXIST *.sbr Del *.sbr > nul
+ at if NOT EXIST *.suo goto DNSUO
+ at attrib -S -R -H *.suo > nul
+ at if EXIST *.suo echo Deleting *.suo ...
+ at if EXIST *.suo Del *.suo > nul
+:DNSUO
+ at if EXIST *.user echo Deleting *.user ...
+ at if EXIST *.user Del *.user > nul
+ at echo All done ...
Added: freeswitch/trunk/libs/xmlrpc-c/Windows/diffcfg.bat
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/Windows/diffcfg.bat Fri May 23 16:56:24 2008
@@ -0,0 +1,6 @@
+diff -us win32_config.h ..\include\xmlrpc-c\config.h > tempcfg.diff
+diff -us xmlrpc_win32_config.h ..\xmlrpc_config.h >> tempcfg.diff
+diff -us transport_config_win32.h ..\transport_config.h >> tempcfg.diff
+diff -us xmlrpc_win32_config.h ..\examples\config.h >> tempcfg.diff
+np tempcfg.diff
+
Added: freeswitch/trunk/libs/xmlrpc-c/Windows/gennmtab.dsp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/Windows/gennmtab.dsp Fri May 23 16:56:24 2008
@@ -0,0 +1,112 @@
+# Microsoft Developer Studio Project File - Name="gennmtab" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=gennmtab - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "gennmtab.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "gennmtab.mak" CFG="gennmtab - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "gennmtab - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "gennmtab - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "gennmtab - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir ".\Release"
+# PROP BASE Intermediate_Dir ".\Release"
+# PROP BASE Target_Dir "."
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release\gennmtab"
+# PROP Intermediate_Dir "Release\gennmtab"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir "."
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"..\bin\gennmtab.exe"
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Desc=(R) Generating nametab.h ...
+PostBuild_Cmds=..\bin\gennmtab.exe >..\lib\expat\xmltok\nametab.h
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "gennmtab - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir ".\Debug"
+# PROP BASE Intermediate_Dir ".\Debug"
+# PROP BASE Target_Dir "."
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug\gennmtab"
+# PROP Intermediate_Dir "Debug\gennmtab"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir "."
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\bin\gennmtabD.exe"
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Desc=(D) Generating nametab.h ...
+PostBuild_Cmds=..\bin\gennmtabD.exe >..\lib\expat\xmltok\nametab.h
+# End Special Build Tool
+
+!ENDIF
+
+# Begin Target
+
+# Name "gennmtab - Win32 Release"
+# Name "gennmtab - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90"
+# Begin Source File
+
+SOURCE=..\lib\expat\gennmtab\gennmtab.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
Added: freeswitch/trunk/libs/xmlrpc-c/Windows/mkvers.bat
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/Windows/mkvers.bat Fri May 23 16:56:24 2008
@@ -0,0 +1,53 @@
+ at if EXIST ..\version.h goto SHOW
+ at if NOT EXIST ..\Makefile.version goto ERR1
+ at if NOT EXIST mkvers1.bat goto ERR2
+ at echo updating/creating ..\version.h ...
+ at set TEMP1=1
+ at for /F "skip=8 tokens=3" %%i in (..\Makefile.version) do @call mkvers1 %%i
+ at if "%TEMPX1%." == "." goto NOX1
+ at if "%TEMPX2%." == "." goto NOX1
+ at if "%TEMPX3%." == "." goto NOX1
+ at set TEMP1=..\version.h
+ at echo #ifndef XMLRPC_C_VERSION_INCLUDED > %TEMP1%
+ at echo #define XMLRPC_C_VERSION_INCLUDED >> %TEMP1%
+ at echo /* generated by Windows/mkvers.bat on %DATE% ... */ >> %TEMP1%
+ at echo #define XMLRPC_C_VERSION "Xmlrpc-c %TEMPX1%.%TEMPX2%.%TEMPX3%" >> %TEMP1%
+ at echo #define XMLRPC_VERSION_MAJOR %TEMPX1% >> %TEMP1%
+ at echo #define XMLRPC_VERSION_MINOR %TEMPX2% >> %TEMP1%
+ at echo #define XMLRPC_VERSION_POINT %TEMPX3% >> %TEMP1%
+ at echo #endif >> %TEMP1%
+type %TEMP1%
+ at echo ..\version.h set to the above ...
+ at set TEMP1=
+ at set TEMPX1=
+ at set TEMPX2=
+ at set TEMPX3=
+ at goto END
+
+:NOX1
+ at echo Some error occurred in the batch process ...
+ at goto NOVER
+
+:NOVER
+ at echo Failed to create ..\version.h .
+ at pause
+ at goto END
+
+
+:ERR1
+ at echo Can not locate ..\Makefile.version ... check name, location ...
+ at pause
+ at goto END
+:ERR2
+ at echo Can not locate mkvers1.bat ... check name, location ...
+ at pause
+ at goto END
+
+:SHOW
+ at echo ..\version.h already exist, with version ...
+ at type ..\version.h
+ at echo Delete this file if you wish to redo it ...
+ at pause
+ at goto END
+
+:END
Added: freeswitch/trunk/libs/xmlrpc-c/Windows/mkvers1.bat
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/Windows/mkvers1.bat Fri May 23 16:56:24 2008
@@ -0,0 +1,32 @@
+ at if "%1." == "." goto ERR2
+ at if "%TEMP1%." == "." goto ERR1
+ at if "%TEMP1%" == "1" goto SET1
+ at if "%TEMP1%" == "2" goto SET2
+ at if "%TEMP1%" == "3" goto SET3
+ at echo environment variable has an invalid value %TEMP1% ...
+ at goto ERR2
+
+:SET1
+ at set TEMPX1=%1
+ at set TEMP1=2
+ at goto END
+
+:SET2
+ at set TEMPX2=%1
+ at set TEMP1=3
+ at goto END
+
+:SET3
+ at set TEMPX3=%1
+ at set TEMP1=4
+ at goto END
+
+
+:ERR1
+ at echo Environment variable TEMP1 not set ...
+:ERR2
+ at echo This batch is only intended to be run from within UPDVERS.BAT ...
+ at pause
+ at goto END
+
+:END
Modified: freeswitch/trunk/libs/xmlrpc-c/Windows/rpctest.dsp
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/Windows/rpctest.dsp (original)
+++ freeswitch/trunk/libs/xmlrpc-c/Windows/rpctest.dsp Fri May 23 16:56:24 2008
@@ -1,236 +1,210 @@
-# Microsoft Developer Studio Project File - Name="rpctest" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=rpctest - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "rpctest.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "rpctest.mak" CFG="rpctest - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "rpctest - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "rpctest - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName "rpctest"
-# PROP Scc_LocalPath ".."
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "rpctest - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release\rpctest"
-# PROP Intermediate_Dir "Release\rpctest"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\\" /I "..\include" /I "../lib/util/include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "ABYSS_WIN32" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ..\lib\xmlrpc.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Ws2_32.lib Wininet.lib /nologo /subsystem:console /machine:I386 /out:"..\bin\rpctest.exe"
-# Begin Special Build Tool
-SOURCE="$(InputPath)"
-PostBuild_Desc=Copy test files
-PostBuild_Cmds=copy ..\src\testdata\*.* .
-# End Special Build Tool
-
-!ELSEIF "$(CFG)" == "rpctest - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug\rpctest"
-# PROP Intermediate_Dir "Debug\rpctest"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\\" /I "..\include" /I "../lib/util/include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "ABYSS_WIN32" /YX /FD /GZ /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 ..\lib\xmlrpcD.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Ws2_32.lib Wininet.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\bin\rpctestD.exe" /pdbtype:sept
-# Begin Special Build Tool
-SOURCE="$(InputPath)"
-PostBuild_Desc=Copy test files
-PostBuild_Cmds=copy ..\src\testdata\*.* .
-# End Special Build Tool
-
-!ENDIF
-
-# Begin Target
-
-# Name "rpctest - Win32 Release"
-# Name "rpctest - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=..\src\test\cgi.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\test\client.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\lib\abyss\src\conf.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\lib\abyss\src\conn.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\lib\abyss\src\data.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\lib\abyss\src\file.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\lib\abyss\src\http.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\test\parse_xml.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\test\serialize.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\lib\abyss\src\server.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\test\server_abyss.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\lib\abyss\src\socket.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\test\test.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\lib\abyss\src\thread.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\lib\abyss\src\token.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\lib\abyss\src\token.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\lib\abyss\src\trace.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\test\value.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\test\xml_data.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\xmlrpc_server_abyss.c
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=..\src\test\client.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\test\parse_xml.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\test\serialize.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\test\server_abyss.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\test\test.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\test\value.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\test\xml_data.h
-# End Source File
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# Begin Group "TestFiles"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE="..\src\testdata\http-req-simple.txt"
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\testdata\req_no_params.xml
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\testdata\req_out_of_order.xml
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\testdata\req_value_name.xml
-# End Source File
-# End Group
-# End Target
-# End Project
+# Microsoft Developer Studio Project File - Name="rpctest" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=rpctest - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "rpctest.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "rpctest.mak" CFG="rpctest - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "rpctest - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "rpctest - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "rpctest - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release\rpctest"
+# PROP Intermediate_Dir "Release\rpctest"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I ".." /I "../include" /I "../lib/util/include" /I "../.." /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "ABYSS_WIN32" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 ..\lib\xmlrpc.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Ws2_32.lib Wininet.lib /nologo /subsystem:console /machine:I386 /out:"..\bin\rpctest.exe"
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Desc=Copy test files
+PostBuild_Cmds=if not exist ..\Bin\data md ..\Bin\data copy ..\src\test\data\*.* ..\Bin\data
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "rpctest - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug\rpctest"
+# PROP Intermediate_Dir "Debug\rpctest"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../.." /I ".." /I "../include" /I "../lib/util/include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "ABYSS_WIN32" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\xmlrpcD.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Ws2_32.lib Wininet.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\bin\rpctestD.exe" /pdbtype:sept
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Desc=Copy test files
+PostBuild_Cmds=if not exist ..\Bin\data md ..\Bin\data copy ..\src\test\data\*.* ..\Bin\data
+# End Special Build Tool
+
+!ENDIF
+
+# Begin Target
+
+# Name "rpctest - Win32 Release"
+# Name "rpctest - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\src\test\abyss.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\test\cgi.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\test\client.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\util\casprintf.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\test\method_registry.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\test\parse_xml.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\test\serialize.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\test\serialize_value.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\test\server_abyss.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\test\test.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\token.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\test\value.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\test\xml_data.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\src\test\client.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\test\parse_xml.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\test\serialize.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\test\serialize_value.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\test\server_abyss.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\test\test.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\test\value.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\test\xml_data.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# Begin Group "TestFiles"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE="..\src\testdata\http-req-simple.txt"
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\testdata\req_no_params.xml
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\testdata\req_out_of_order.xml
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\testdata\req_value_name.xml
+# End Source File
+# End Group
+# End Target
+# End Project
Modified: freeswitch/trunk/libs/xmlrpc-c/Windows/transport_config_win32.h
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/Windows/transport_config_win32.h (original)
+++ freeswitch/trunk/libs/xmlrpc-c/Windows/transport_config_win32.h Fri May 23 16:56:24 2008
@@ -1,26 +1,13 @@
+/* Win32 version of transport_config.h.
+
+ For other platforms, this is generated automatically, but for Windows,
+ someone generates it manually. Nonetheless, we keep it looking as much
+ as possible like the automatically generated one to make it easier to
+ maintain (e.g. you can compare the two and see why something builds
+ differently for Windows that for some other platform).
+*/
#define MUST_BUILD_WININET_CLIENT 1
#define MUST_BUILD_CURL_CLIENT 0
#define MUST_BUILD_LIBWWW_CLIENT 0
-static const char * const XMLRPC_DEFAULT_TRANSPORT = "wininet";
-
-/*
-Set to zero if you do not wish to build the http.sys
-based XMLRPC-C Server
-*/
-#define MUST_BUILD_HTTP_SYS_SERVER 1
-
-/*
-We use pragma statements to tell the linker what we need to link with.
-Since Curl requires Winsock, Winmm, and libcurl, and no other
-project does, if we are building curl support we tell the linker
-what libs we need to add.
-*/
-#if MUST_BUILD_CURL_CLIENT > 0
-#ifdef _DEBUG
-#pragma comment( lib, "../lib/libcurld.lib" )
-#else
-#pragma comment( lib, "../lib/libcurl.lib" )
-#endif
-#pragma comment( lib, "Winmm.lib" )
-#pragma comment( lib, "Ws2_32.lib" )
-#endif
\ No newline at end of file
+static const char * const XMLRPC_DEFAULT_TRANSPORT =
+"wininet";
Added: freeswitch/trunk/libs/xmlrpc-c/Windows/updcfg.bat
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/Windows/updcfg.bat Fri May 23 16:56:24 2008
@@ -0,0 +1,9 @@
+ at echo This will COPY the current config.h, xmlrpc_config.h, transprt_config.h,
+ at echo version.h, overwriting files in this 'Windows' folder!
+ at echo ARE YOU SURE YOU WANT TO DO THIS??? Ctrl+C to abort ...
+ at pause
+copy ..\include\xmlrpc-c\config.h win32_config.h
+copy ..\xmlrpc_config.h xmlrpc_win32_config.h
+copy ..\transport_config.h transport_config_win32.h
+ at echo all done ...
+
Added: freeswitch/trunk/libs/xmlrpc-c/Windows/win32_config.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/Windows/win32_config.h Fri May 23 16:56:24 2008
@@ -0,0 +1,38 @@
+#ifndef XMLRPC_C_CONFIG_H_INCLUDED
+#define XMLRPC_C_CONFIG_H_INCLUDED
+
+/* This file, part of XML-RPC For C/C++, is meant to
+ define characteristics of this particular installation
+ that the other <xmlrpc-c/...> header files need in
+ order to compile correctly when #included in Xmlrpc-c
+ user code.
+
+ Those header files #include this one.
+
+ This file was created by a make rule.
+*/
+#define XMLRPC_HAVE_WCHAR 1
+#ifdef WIN32
+ /* SOCKET is a type defined by <winsock.h>. Anyone who
+ uses XMLRPC_SOCKET on a WIN32 system must #include
+ <winsock.h>
+ */
+ #define XMLRPC_SOCKET SOCKET
+ #define XMLRPC_HAVE_TIMEVAL 0
+ #define XMLRPC_HAVE_TIMESPEC 0
+#else
+ #define XMLRPC_SOCKET int
+ #define XMLRPC_HAVE_TIMEVAL 1
+ #define XMLRPC_HAVE_TIMESPEC 1
+#endif
+
+#if defined(_MSC_VER)
+ /* Newer MSVC has long long, but MSVC 6 does not */
+ #define XMLRPC_INT64 __int64
+ #define XMLRPC_INT32 __int32
+#else
+ #define XMLRPC_INT64 long long
+ #define XMLRPC_INT32 int
+#endif
+#endif
+
Added: freeswitch/trunk/libs/xmlrpc-c/Windows/xmlhttpsys.dsp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/Windows/xmlhttpsys.dsp Fri May 23 16:56:24 2008
@@ -0,0 +1,106 @@
+# Microsoft Developer Studio Project File - Name="xmlhttpsys" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=xmlhttpsys - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "xmlhttpsys.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "xmlhttpsys.mak" CFG="xmlhttpsys - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "xmlhttpsys - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "xmlhttpsys - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "xmlhttpsys - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir ".\Release"
+# PROP BASE Intermediate_Dir ".\Release"
+# PROP BASE Target_Dir "."
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release\xmlhttpsys"
+# PROP Intermediate_Dir "Release\xmlhttpsys"
+# PROP Target_Dir "."
+MTL=midl.exe
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I ".." /I "..\include" /D "NDEBUG" /D "XML_NS" /D "WIN32" /D "_WINDOWS" /D "XML_DTD" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib\xmlhttpsys.lib"
+
+!ELSEIF "$(CFG)" == "xmlhttpsys - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir ".\Debug"
+# PROP BASE Intermediate_Dir ".\Debug"
+# PROP BASE Target_Dir "."
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug\xmlhttpsys"
+# PROP Intermediate_Dir "Debug\xmlhttpsys"
+# PROP Target_Dir "."
+MTL=midl.exe
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I ".." /I "..\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "XML_DTD" /D "XML_NS" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib\xmlhttpsysD.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "xmlhttpsys - Win32 Release"
+# Name "xmlhttpsys - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90"
+# Begin Source File
+
+SOURCE=..\src\xmlrpc_server_w32httpsys.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
+# Begin Source File
+
+SOURCE=..\xmlrpc_config.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
Added: freeswitch/trunk/libs/xmlrpc-c/Windows/xmlparse.dsp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/Windows/xmlparse.dsp Fri May 23 16:56:24 2008
@@ -0,0 +1,106 @@
+# Microsoft Developer Studio Project File - Name="xmlparse" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=xmlparse - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "xmlparse.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "xmlparse.mak" CFG="xmlparse - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "xmlparse - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "xmlparse - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "xmlparse - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir ".\Release"
+# PROP BASE Intermediate_Dir ".\Release"
+# PROP BASE Target_Dir "."
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release\xmlparse"
+# PROP Intermediate_Dir "Release\xmlparse"
+# PROP Target_Dir "."
+LINK32=link.exe -lib
+MTL=midl.exe
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\lib\expat\xmltok" /I "..\lib\expat\xmlwf" /I ".." /I "..\lib\util\include" /I "..\include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "XML_DTD" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib\xmlparse.lib"
+
+!ELSEIF "$(CFG)" == "xmlparse - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir ".\Debug"
+# PROP BASE Intermediate_Dir ".\Debug"
+# PROP BASE Target_Dir "."
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug\xmlparse"
+# PROP Intermediate_Dir "Debug\xmlparse"
+# PROP Target_Dir "."
+LINK32=link.exe -lib
+MTL=midl.exe
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\lib\expat\xmltok" /I "..\lib\expat\xmlwf" /I ".." /I "..\lib\util\include" /I "..\include" /D "WIN32" /D "_WINDOWS" /D "XML_DTD" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib\xmlparseD.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "xmlparse - Win32 Release"
+# Name "xmlparse - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90"
+# Begin Source File
+
+SOURCE=..\lib\expat\xmlparse\xmlparse.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
+# Begin Source File
+
+SOURCE=..\lib\expat\xmlparse\xmlparse.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
Modified: freeswitch/trunk/libs/xmlrpc-c/Windows/xmlrpc.dsp
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/Windows/xmlrpc.dsp (original)
+++ freeswitch/trunk/libs/xmlrpc-c/Windows/xmlrpc.dsp Fri May 23 16:56:24 2008
@@ -1,258 +1,469 @@
-# Microsoft Developer Studio Project File - Name="xmlrpc" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Static Library" 0x0104
-
-CFG=xmlrpc - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "xmlrpc.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "xmlrpc.mak" CFG="xmlrpc - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "xmlrpc - Win32 Release" (based on "Win32 (x86) Static Library")
-!MESSAGE "xmlrpc - Win32 Debug" (based on "Win32 (x86) Static Library")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName "xmlrpc"
-# PROP Scc_LocalPath ".."
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "xmlrpc - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release\xmlrpc"
-# PROP Intermediate_Dir "Release\xmlrpc"
-# PROP Target_Dir ""
-MTL=midl.exe
-LINK32=link.exe -lib
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
-# ADD CPP /nologo /MT /W3 /GX /O2 /I "../lib/" /I "../lib/curl_transport" /I "../lib/util/include" /I "../include" /I "../" /I "../lib/expat/xmlparse" /I "../lib/w3c-libwww-5.3.2/Library/src" /I "../lib/abyss/src" /I "../lib/wininet_transport" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "ABYSS_WIN32" /D "CURL_STATICLIB" /FR /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo /out:"..\lib\xmlrpc.lib"
-
-!ELSEIF "$(CFG)" == "xmlrpc - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug\xmlrpc"
-# PROP Intermediate_Dir "Debug\xmlrpc"
-# PROP Target_Dir ""
-MTL=midl.exe
-LINK32=link.exe -lib
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
-# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../lib/" /I "../lib/curl_transport" /I "../lib/util/include" /I "../include" /I "../" /I "../lib/expat/xmlparse" /I "../lib/w3c-libwww-5.3.2/Library/src" /I "../lib/abyss/src" /I "../lib/wininet_transport" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "ABYSS_WIN32" /D "CURL_STATICLIB" /YX /FD /GZ /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo /out:"..\lib\xmlrpcD.lib"
-
-!ENDIF
-
-# Begin Target
-
-# Name "xmlrpc - Win32 Release"
-# Name "xmlrpc - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;cc"
-# Begin Source File
-
-SOURCE=..\lib\util\casprintf.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\lib\util\pthreadx_win32.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\xmlrpc_array.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\xmlrpc_authcookie.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\xmlrpc_base64.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\xmlrpc_builddecomp.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\xmlrpc_client.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\lib\curl_transport\xmlrpc_curl_transport.c
-# PROP Exclude_From_Build 1
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\xmlrpc_data.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\xmlrpc_datetime.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\xmlrpc_expat.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\xmlrpc_libxml2.c
-# PROP Exclude_From_Build 1
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\xmlrpc_parse.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\xmlrpc_registry.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\xmlrpc_serialize.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\xmlrpc_server_abyss.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\xmlrpc_server_w32httpsys.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\xmlrpc_struct.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\xmlrpc_strutil.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\xmlrpc_support.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\xmlrpc_utf8.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\lib\wininet_transport\xmlrpc_wininet_transport.c
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE="..\include\xmlrpc-c\abyss.h"
-# End Source File
-# Begin Source File
-
-SOURCE="..\include\xmlrpc-c\base.h"
-# End Source File
-# Begin Source File
-
-SOURCE=..\lib\util\include\bool.h
-# End Source File
-# Begin Source File
-
-SOURCE="..\include\xmlrpc-c\client.h"
-# End Source File
-# Begin Source File
-
-SOURCE="..\include\xmlrpc-c\client_int.h"
-# End Source File
-# Begin Source File
-
-SOURCE=..\lib\util\include\mallocvar.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\lib\util\include\pthreadx.h
-# End Source File
-# Begin Source File
-
-SOURCE="..\include\xmlrpc-c\server.h"
-# End Source File
-# Begin Source File
-
-SOURCE="..\include\xmlrpc-c\server_abyss.h"
-# End Source File
-# Begin Source File
-
-SOURCE="..\include\xmlrpc-c\server_cgi.h"
-# End Source File
-# Begin Source File
-
-SOURCE="..\include\xmlrpc-c\server_w32httpsys.h"
-# End Source File
-# Begin Source File
-
-SOURCE="..\include\xmlrpc-c\transport.h"
-# End Source File
-# Begin Source File
-
-SOURCE=..\transport_config.h
-# End Source File
-# Begin Source File
-
-SOURCE="..\include\xmlrpc-c\transport_int.h"
-# End Source File
-# Begin Source File
-
-SOURCE="..\include\xmlrpc-c\xmlparser.h"
-# End Source File
-# Begin Source File
-
-SOURCE=..\xmlrpc_config.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\lib\curl_transport\xmlrpc_curl_transport.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\lib\wininet_transport\xmlrpc_wininet_transport.h
-# End Source File
-# End Group
-# End Target
-# End Project
+# Microsoft Developer Studio Project File - Name="xmlrpc" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=xmlrpc - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "xmlrpc.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "xmlrpc.mak" CFG="xmlrpc - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "xmlrpc - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "xmlrpc - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "xmlrpc - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release\xmlrpc"
+# PROP Intermediate_Dir "Release\xmlrpc"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+MTL=midl.exe
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "../lib" /I "../lib/util/include" /I "../include" /I ".." /I "../lib/expat/xmlparse" /I "../lib/abyss/src" /I "../lib/wininet_transport" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "ABYSS_WIN32" /D "CURL_STATICLIB" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib\xmlrpc.lib"
+
+!ELSEIF "$(CFG)" == "xmlrpc - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug\xmlrpc"
+# PROP Intermediate_Dir "Debug\xmlrpc"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+MTL=midl.exe
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../lib" /I "../lib/util/include" /I "../include" /I ".." /I "../lib/expat/xmlparse" /I "../lib/abyss/src" /I "../lib/wininet_transport" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "ABYSS_WIN32" /D "CURL_STATICLIB" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib\xmlrpcD.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "xmlrpc - Win32 Release"
+# Name "xmlrpc - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;cc"
+# Begin Source File
+
+SOURCE=..\lib\libutil\asprintf.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\libutil\error.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\libutil\make_printable.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\libutil\memblock.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\method.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\util\pthreadx_win32.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\parse_value.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\registry.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\resource.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\libutil\select.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\libutil\sleep.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\system_method.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\libutil\time.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\trace.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\version.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\libutil\utf8.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\double.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\xmlrpc_array.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\xmlrpc_authcookie.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\xmlrpc_base64.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\xmlrpc_build.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\xmlrpc_client.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\xmlrpc_client_global.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\xmlrpc_server_info.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\curl_transport\xmlrpc_curl_transport.c
+
+!IF "$(CFG)" == "xmlrpc - Win32 Release"
+
+# ADD CPP /I "." /I "..\..\curl\include"
+# PROP Exclude_From_Build 1
+
+!ELSEIF "$(CFG)" == "xmlrpc - Win32 Debug"
+
+# ADD CPP /I "." /I "..\..\curl\include"
+# PROP Exclude_From_Build 1
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\xmlrpc_data.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\xmlrpc_datetime.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\xmlrpc_decompose.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\xmlrpc_expat.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\xmlrpc_libxml2.c
+# PROP Exclude_From_Build 1
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\xmlrpc_parse.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\xmlrpc_serialize.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\xmlrpc_server_abyss.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\xmlrpc_server_w32httpsys.c
+# PROP Exclude_From_Build 1
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\xmlrpc_string.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\xmlrpc_struct.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\wininet_transport\xmlrpc_wininet_transport.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\http.h
+# End Source File
+# Begin Source File
+
+SOURCE="..\include\xmlrpc-c\abyss.h"
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\abyss_info.h
+# End Source File
+# Begin Source File
+
+SOURCE="..\include\xmlrpc-c\abyss_winsock.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\include\xmlrpc-c\base.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\include\xmlrpc-c\base_int.h"
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\util\include\bool.h
+# End Source File
+# Begin Source File
+
+SOURCE="..\include\xmlrpc-c\c_util.h"
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\util\include\c_util.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\util\include\casprintf.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\channel.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\chanswitch.h
+# End Source File
+# Begin Source File
+
+SOURCE="..\include\xmlrpc-c\client.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\include\xmlrpc-c\client_global.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\include\xmlrpc-c\client_int.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\include\xmlrpc-c\config.h"
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\conn.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\date.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\file.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\util\include\girmath.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\handler.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\util\include\inline.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\util\include\linklist.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\util\include\mallocvar.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\double.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\method.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\util\include\pthreadx.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\parse_value.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\registry.h
+# End Source File
+# Begin Source File
+
+SOURCE="..\include\xmlrpc-c\server.h"
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\server.h
+# End Source File
+# Begin Source File
+
+SOURCE="..\include\xmlrpc-c\server_abyss.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\include\xmlrpc-c\server_cgi.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\include\xmlrpc-c\server_w32httpsys.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\include\xmlrpc-c\sleep_int.h"
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\socket.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\socket_win.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\util\include\stdargx.h
+# End Source File
+# Begin Source File
+
+SOURCE="..\include\xmlrpc-c\string_int.h"
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\system_method.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\thread.h
+# End Source File
+# Begin Source File
+
+SOURCE="..\include\xmlrpc-c\time_int.h"
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\token.h
+# End Source File
+# Begin Source File
+
+SOURCE="..\include\xmlrpc-c\transport.h"
+# End Source File
+# Begin Source File
+
+SOURCE=..\transport_config.h
+# End Source File
+# Begin Source File
+
+SOURCE="..\include\xmlrpc-c\transport_int.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\include\xmlrpc-c\util_int.h"
+# End Source File
+# Begin Source File
+
+SOURCE=..\xml_rpc_alloc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\expat\xmlparse\xmlparse.h
+# End Source File
+# Begin Source File
+
+SOURCE="..\include\xmlrpc-c\xmlparser.h"
+# End Source File
+# Begin Source File
+
+SOURCE=..\xmlrpc_config.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\curl_transport\xmlrpc_curl_transport.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\wininet_transport\xmlrpc_wininet_transport.h
+# End Source File
+# End Group
+# End Target
+# End Project
Modified: freeswitch/trunk/libs/xmlrpc-c/Windows/xmlrpc.dsw
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/Windows/xmlrpc.dsw (original)
+++ freeswitch/trunk/libs/xmlrpc-c/Windows/xmlrpc.dsw Fri May 23 16:56:24 2008
@@ -1,194 +1,242 @@
-Microsoft Developer Studio Workspace File, Format Version 6.00
-# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
-
-###############################################################################
-
-Project: "cpptest"=".\cpptest.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
- Begin Project Dependency
- Project_Dep_Name xmlrpc
- End Project Dependency
-}}}
-
-###############################################################################
-
-Project: "gennmtab"="..\lib\expat\gennmtab\gennmtab.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "query_meerkat"=".\query_meerkat.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
- Begin Project Dependency
- Project_Dep_Name xmlrpc
- End Project Dependency
-}}}
-
-###############################################################################
-
-Project: "rpctest"=".\rpctest.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
- Begin Project Dependency
- Project_Dep_Name xmlrpc
- End Project Dependency
-}}}
-
-###############################################################################
-
-Project: "xmlparse"="..\lib\expat\xmlparse\xmlparse.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
- Begin Project Dependency
- Project_Dep_Name xmltok
- End Project Dependency
-}}}
-
-###############################################################################
-
-Project: "xmlrpc"=".\xmlrpc.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
- Begin Project Dependency
- Project_Dep_Name xmlparse
- End Project Dependency
-}}}
-
-###############################################################################
-
-Project: "xmlrpc_sample_add_asynch_client"=".\xmlrpc_sample_add_asynch_client.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
- Begin Project Dependency
- Project_Dep_Name xmlrpc
- End Project Dependency
-}}}
-
-###############################################################################
-
-Project: "xmlrpc_sample_add_server"=".\xmlrpc_sample_add_server.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
- Begin Project Dependency
- Project_Dep_Name xmlrpc
- End Project Dependency
-}}}
-
-###############################################################################
-
-Project: "xmlrpc_sample_add_server_w32httpsys"=".\xmlrpc_sample_add_server_w32httpsys.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
- Begin Project Dependency
- Project_Dep_Name xmlrpc
- End Project Dependency
-}}}
-
-###############################################################################
-
-Project: "xmlrpc_sample_add_sync_client"=".\xmlrpc_sample_add_sync_client.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
- Begin Project Dependency
- Project_Dep_Name xmlrpc
- End Project Dependency
-}}}
-
-###############################################################################
-
-Project: "xmlrpc_sample_auth_client"=".\xmlrpc_sample_auth_client.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
- Begin Project Dependency
- Project_Dep_Name xmlrpc
- End Project Dependency
-}}}
-
-###############################################################################
-
-Project: "xmltok"="..\lib\expat\xmltok\xmltok.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
- Begin Project Dependency
- Project_Dep_Name gennmtab
- End Project Dependency
-}}}
-
-###############################################################################
-
-Global:
-
-Package=<5>
-{{{
-}}}
-
-Package=<3>
-{{{
-}}}
-
-###############################################################################
-
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "abyss"=".\abyss.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "cpptest"=".\cpptest.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name xmlrpc
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name xmlrpccpp
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name abyss
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "gennmtab"=".\gennmtab.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "rpctest"=".\rpctest.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name xmlrpc
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name abyss
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "xmlhttpsys"=".\xmlhttpsys.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "xmlparse"=".\xmlparse.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name xmltok
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "xmlrpc"=".\xmlrpc.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name xmlparse
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name abyss
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "xmlrpccpp"=".\xmlrpccpp.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name xmlparse
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name abyss
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name xmlrpc
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "xmlrpc_sample_add_asynch_client"=".\xmlrpc_sample_add_asynch_client.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name xmlrpc
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "xmlrpc_sample_add_server"=".\xmlrpc_sample_add_server.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name xmlrpc
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name abyss
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "xmlrpc_sample_add_server_w32httpsys"=".\xmlrpc_sample_add_server_w32httpsys.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name xmlhttpsys
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name xmlrpc
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "xmlrpc_sample_add_sync_client"=".\xmlrpc_sample_add_sync_client.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name xmlrpc
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "xmlrpc_sample_auth_client"=".\xmlrpc_sample_auth_client.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name xmlrpc
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "xmltok"=".\xmltok.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name gennmtab
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
Added: freeswitch/trunk/libs/xmlrpc-c/Windows/xmlrpc_cpp_proxy.dsp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/Windows/xmlrpc_cpp_proxy.dsp Fri May 23 16:56:24 2008
@@ -0,0 +1,132 @@
+# Microsoft Developer Studio Project File - Name="xmlrpc_cpp_proxy" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=xmlrpc_cpp_proxy - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "xmlrpc_cpp_proxy.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "xmlrpc_cpp_proxy.mak" CFG="xmlrpc_cpp_proxy - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "xmlrpc_cpp_proxy - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "xmlrpc_cpp_proxy - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "xmlrpc_cpp_proxy - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release\xmlrpc_cpp_proxy"
+# PROP Intermediate_Dir "Release\xmlrpc_cpp_proxy"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I ".." /I "../include" /I "../lib/util/include" /I "../.." /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "ABYSS_WIN32" /D "CURL_STATICLIB" /D "_CRT_SECURE_NO_WARNINGS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 ..\lib\xmlrpccpp.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Ws2_32.lib Wininet.lib /nologo /subsystem:console /machine:I386 /out:"..\bin\xmlrpc_cpp_proxy.exe"
+
+!ELSEIF "$(CFG)" == "xmlrpc_cpp_proxy - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug\xmlrpc_cpp_proxy"
+# PROP Intermediate_Dir "Debug\xmlrpc_cpp_proxy"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../.." /I ".." /I "../include" /I "../lib/util/include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "ABYSS_WIN32" /D "CURL_STATICLIB" /D "_CRT_SECURE_NO_WARNINGS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\xmlrpccppD.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Ws2_32.lib Wininet.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\bin\xmlrpc_cpp_proxyD.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "xmlrpc_cpp_proxy - Win32 Release"
+# Name "xmlrpc_cpp_proxy - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\tools\xmlrpc_cpp_proxy\proxyClass.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\tools\xmlrpc_cpp_proxy\systemProxy.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\tools\xmlrpc_cpp_proxy\xmlrpcMethod.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\tools\xmlrpc_cpp_proxy\xmlrpcType.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\tools\xmlrpc_cpp_proxy\xmlrpc_cpp_proxy.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\tools\xmlrpc_cpp_proxy\proxyClass.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\tools\xmlrpc_cpp_proxy\systemProxy.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\tools\xmlrpc_cpp_proxy\xmlrpcMethod.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\tools\xmlrpc_cpp_proxy\xmlrpcType.hpp
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
Added: freeswitch/trunk/libs/xmlrpc-c/Windows/xmlrpc_misc.dsp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/Windows/xmlrpc_misc.dsp Fri May 23 16:56:24 2008
@@ -0,0 +1,122 @@
+# Microsoft Developer Studio Project File - Name="xmlrpc_misc" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=xmlrpc_misc - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "xmlrpc_misc.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "xmlrpc_misc.mak" CFG="xmlrpc_misc - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "xmlrpc_misc - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "xmlrpc_misc - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "xmlrpc_misc - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir ".\Release"
+# PROP BASE Intermediate_Dir ".\Release"
+# PROP BASE Target_Dir "."
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release\xmlrpc_misc"
+# PROP Intermediate_Dir "Release\xmlrpc_misc"
+# PROP Target_Dir "."
+MTL=midl.exe
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I ".." /I "..\lib\util\include" /D "NDEBUG" /D "XML_NS" /D "WIN32" /D "_WINDOWS" /D "XML_DTD" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib\xmlrpc_misc.lib"
+
+!ELSEIF "$(CFG)" == "xmlrpc_misc - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir ".\Debug"
+# PROP BASE Intermediate_Dir ".\Debug"
+# PROP BASE Target_Dir "."
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug\xmlrpc_misc"
+# PROP Intermediate_Dir "Debug\xmlrpc_misc"
+# PROP Target_Dir "."
+MTL=midl.exe
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I ".." /I "..\lib\util\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "XML_DTD" /D "XML_NS" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib\xmlrpc_miscD.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "xmlrpc_misc - Win32 Release"
+# Name "xmlrpc_misc - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90"
+# Begin Source File
+
+SOURCE=..\lib\util\casprintf.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\util\cmdline_parser.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\util\cmdline_parser_cpp.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\util\getoptx.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\util\string_parser.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\util\stripcaseeq.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
Modified: freeswitch/trunk/libs/xmlrpc-c/Windows/xmlrpc_sample_add_asynch_client.dsp
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/Windows/xmlrpc_sample_add_asynch_client.dsp (original)
+++ freeswitch/trunk/libs/xmlrpc-c/Windows/xmlrpc_sample_add_asynch_client.dsp Fri May 23 16:56:24 2008
@@ -1,102 +1,102 @@
-# Microsoft Developer Studio Project File - Name="xmlrpc_sample_add_asynch_client" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=xmlrpc_sample_add_asynch_client - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "xmlrpc_sample_add_asynch_client.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "xmlrpc_sample_add_asynch_client.mak" CFG="xmlrpc_sample_add_asynch_client - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "xmlrpc_sample_add_asynch_client - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "xmlrpc_sample_add_asynch_client - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName "xmlrpc_sample_add_asynch_client"
-# PROP Scc_LocalPath ".."
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "xmlrpc_sample_add_asynch_client - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release\xmlrpc_sample_add_asynch_client"
-# PROP Intermediate_Dir "Release\xmlrpc_sample_add_asynch_client"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\\" /I "..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ..\lib\xmlrpc.lib WinInet.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"..\bin\xmlrpc_sample_add_asynch_client.exe"
-
-!ELSEIF "$(CFG)" == "xmlrpc_sample_add_asynch_client - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug\xmlrpc_sample_add_asynch_client"
-# PROP Intermediate_Dir "Debug\xmlrpc_sample_add_asynch_client"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\\" /I "..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 ..\lib\xmlrpcD.lib WinInet.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\bin\xmlrpc_sample_add_asynch_clientD.exe" /pdbtype:sept
-
-!ENDIF
-
-# Begin Target
-
-# Name "xmlrpc_sample_add_asynch_client - Win32 Release"
-# Name "xmlrpc_sample_add_asynch_client - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=..\examples\xmlrpc_asynch_client.c
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
+# Microsoft Developer Studio Project File - Name="xmlrpc_sample_add_asynch_client" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=xmlrpc_sample_add_asynch_client - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "xmlrpc_sample_add_asynch_client.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "xmlrpc_sample_add_asynch_client.mak" CFG="xmlrpc_sample_add_asynch_client - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "xmlrpc_sample_add_asynch_client - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "xmlrpc_sample_add_asynch_client - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "xmlrpc_sample_add_asynch_client - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release\xmlrpc_sample_add_asynch_client"
+# PROP Intermediate_Dir "Release\xmlrpc_sample_add_asynch_client"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I ".." /I "../include" /I "../lib/util/include" /I "../.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c /D "CURL_STATICLIB"
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 ..\lib\xmlrpc.lib WinInet.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"..\bin\xmlrpc_sample_add_asynch_client.exe"
+
+!ELSEIF "$(CFG)" == "xmlrpc_sample_add_asynch_client - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug\xmlrpc_sample_add_asynch_client"
+# PROP Intermediate_Dir "Debug\xmlrpc_sample_add_asynch_client"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I ".." /I "../include" /I "../lib/util/include" /I "../.." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c /D "CURL_STATICLIB"
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ..\lib\xmlrpcD.lib WinInet.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\bin\xmlrpc_sample_add_asynch_clientD.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "xmlrpc_sample_add_asynch_client - Win32 Release"
+# Name "xmlrpc_sample_add_asynch_client - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\examples\xmlrpc_asynch_client.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
Modified: freeswitch/trunk/libs/xmlrpc-c/Windows/xmlrpc_sample_add_server.dsp
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/Windows/xmlrpc_sample_add_server.dsp (original)
+++ freeswitch/trunk/libs/xmlrpc-c/Windows/xmlrpc_sample_add_server.dsp Fri May 23 16:56:24 2008
@@ -1,140 +1,103 @@
-# Microsoft Developer Studio Project File - Name="xmlrpc_sample_add_server" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=xmlrpc_sample_add_server - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "xmlrpc_sample_add_server.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "xmlrpc_sample_add_server.mak" CFG="xmlrpc_sample_add_server - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "xmlrpc_sample_add_server - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "xmlrpc_sample_add_server - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName "xmlrpc_sample_add_server"
-# PROP Scc_LocalPath ".."
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "xmlrpc_sample_add_server - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir ".\Release\xmlrpc_sample_add_server"
-# PROP Intermediate_Dir ".\Release\xmlrpc_sample_add_server"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\\" /I "..\include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "ABYSS_WIN32" /D "_THREAD" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib ..\lib\xmlrpc.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /out:"..\bin\xmlrpc_sample_add_server.exe"
-# SUBTRACT LINK32 /pdb:none
-
-!ELSEIF "$(CFG)" == "xmlrpc_sample_add_server - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir ".\Debug\xmlrpc_sample_add_server"
-# PROP Intermediate_Dir ".\Debug\xmlrpc_sample_add_server"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "..\\" /I "..\include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "ABYSS_WIN32" /D "_THREAD" /YX /FD /GZ /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib ..\lib\xmlrpcD.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\bin\xmlrpc_sample_add_serverD.exe" /pdbtype:sept
-# SUBTRACT LINK32 /pdb:none
-
-!ENDIF
-
-# Begin Target
-
-# Name "xmlrpc_sample_add_server - Win32 Release"
-# Name "xmlrpc_sample_add_server - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=..\lib\abyss\src\conf.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\lib\abyss\src\conn.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\lib\abyss\src\data.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\lib\abyss\src\file.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\lib\abyss\src\http.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\lib\abyss\src\server.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\lib\abyss\src\socket.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\lib\abyss\src\thread.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\lib\abyss\src\trace.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\examples\xmlrpc_sample_add_server.c
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
+# Microsoft Developer Studio Project File - Name="xmlrpc_sample_add_server" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=xmlrpc_sample_add_server - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "xmlrpc_sample_add_server.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "xmlrpc_sample_add_server.mak" CFG="xmlrpc_sample_add_server - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "xmlrpc_sample_add_server - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "xmlrpc_sample_add_server - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "xmlrpc_sample_add_server - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ".\Release\xmlrpc_sample_add_server"
+# PROP Intermediate_Dir ".\Release\xmlrpc_sample_add_server"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I ".." /I "../include" /I "../lib/util/include" /I "../.." /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "ABYSS_WIN32" /D "_THREAD" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib ..\lib\xmlrpc.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /out:"..\bin\xmlrpc_sample_add_server.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "xmlrpc_sample_add_server - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ".\Debug\xmlrpc_sample_add_server"
+# PROP Intermediate_Dir ".\Debug\xmlrpc_sample_add_server"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /GX /Zi /Od /I ".." /I "../include" /I "../lib/util/include" /I "../.." /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "ABYSS_WIN32" /D "_THREAD" /YX /FD /GZ /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib ..\lib\xmlrpcD.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\bin\xmlrpc_sample_add_serverD.exe" /pdbtype:sept
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF
+
+# Begin Target
+
+# Name "xmlrpc_sample_add_server - Win32 Release"
+# Name "xmlrpc_sample_add_server - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\examples\xmlrpc_sample_add_server.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
Modified: freeswitch/trunk/libs/xmlrpc-c/Windows/xmlrpc_sample_add_server_w32httpsys.dsp
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/Windows/xmlrpc_sample_add_server_w32httpsys.dsp (original)
+++ freeswitch/trunk/libs/xmlrpc-c/Windows/xmlrpc_sample_add_server_w32httpsys.dsp Fri May 23 16:56:24 2008
@@ -1,104 +1,102 @@
-# Microsoft Developer Studio Project File - Name="xmlrpc_sample_add_server_w32httpsys" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=xmlrpc_sample_add_server_w32httpsys - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "xmlrpc_sample_add_server_w32httpsys.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "xmlrpc_sample_add_server_w32httpsys.mak" CFG="xmlrpc_sample_add_server_w32httpsys - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "xmlrpc_sample_add_server_w32httpsys - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "xmlrpc_sample_add_server_w32httpsys - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName "xmlrpc_sample_add_server_w32httpsys"
-# PROP Scc_LocalPath ".."
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "xmlrpc_sample_add_server_w32httpsys - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir ".\Release\xmlrpc_sample_add_server_w32httpsys"
-# PROP Intermediate_Dir ".\Release\xmlrpc_sample_add_server_w32httpsys"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\\" /I "..\include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "ABYSS_WIN32" /D "_THREAD" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib ..\lib\xmlrpc.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /out:"..\bin\xmlrpc_sample_add_server_w32httpsys.exe"
-# SUBTRACT LINK32 /pdb:none
-
-!ELSEIF "$(CFG)" == "xmlrpc_sample_add_server_w32httpsys - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir ".\Debug\xmlrpc_sample_add_server_w32httpsys"
-# PROP Intermediate_Dir ".\Debug\xmlrpc_sample_add_server_w32httpsys"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "..\\" /I "..\include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "ABYSS_WIN32" /D "_THREAD" /YX /FD /GZ /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib ..\lib\xmlrpcD.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\bin\xmlrpc_sample_add_server_w32httpsysD.exe" /pdbtype:sept
-# SUBTRACT LINK32 /pdb:none
-
-!ENDIF
-
-# Begin Target
-
-# Name "xmlrpc_sample_add_server_w32httpsys - Win32 Release"
-# Name "xmlrpc_sample_add_server_w32httpsys - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=..\examples\xmlrpc_sample_add_server_w32httpsys.c
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
+# Microsoft Developer Studio Project File - Name="xmlrpc_sample_add_server_w32httpsys" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=xmlrpc_sample_add_server_w32httpsys - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "xmlrpc_sample_add_server_w32httpsys.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "xmlrpc_sample_add_server_w32httpsys.mak" CFG="xmlrpc_sample_add_server_w32httpsys - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "xmlrpc_sample_add_server_w32httpsys - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "xmlrpc_sample_add_server_w32httpsys - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "xmlrpc_sample_add_server_w32httpsys - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ".\Release\xmlrpc_sample_add_server_w32httpsys"
+# PROP Intermediate_Dir ".\Release\xmlrpc_sample_add_server_w32httpsys"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I ".." /I "../include" /I "../lib/util/include" /I "../.." /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "ABYSS_WIN32" /D "_THREAD" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib ..\lib\xmlrpc.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /out:"..\bin\xmlrpc_sample_add_server_w32httpsys.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "xmlrpc_sample_add_server_w32httpsys - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ".\Debug\xmlrpc_sample_add_server_w32httpsys"
+# PROP Intermediate_Dir ".\Debug\xmlrpc_sample_add_server_w32httpsys"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /GX /Zi /Od /I ".." /I "../include" /I "../lib/util/include" /I "../.." /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "ABYSS_WIN32" /D "_THREAD" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib ..\lib\xmlrpcD.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\bin\xmlrpc_sample_add_server_w32httpsysD.exe" /pdbtype:sept
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF
+
+# Begin Target
+
+# Name "xmlrpc_sample_add_server_w32httpsys - Win32 Release"
+# Name "xmlrpc_sample_add_server_w32httpsys - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\examples\xmlrpc_sample_add_server_w32httpsys.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
Modified: freeswitch/trunk/libs/xmlrpc-c/Windows/xmlrpc_sample_add_sync_client.dsp
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/Windows/xmlrpc_sample_add_sync_client.dsp (original)
+++ freeswitch/trunk/libs/xmlrpc-c/Windows/xmlrpc_sample_add_sync_client.dsp Fri May 23 16:56:24 2008
@@ -1,104 +1,103 @@
-# Microsoft Developer Studio Project File - Name="xmlrpc_sample_add_sync_client" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=xmlrpc_sample_add_sync_client - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "xmlrpc_sample_add_sync_client.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "xmlrpc_sample_add_sync_client.mak" CFG="xmlrpc_sample_add_sync_client - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "xmlrpc_sample_add_sync_client - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "xmlrpc_sample_add_sync_client - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName "xmlrpc_sample_add_sync_client"
-# PROP Scc_LocalPath ".."
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "xmlrpc_sample_add_sync_client - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir ".\Release\xmlrpc_sample_add_sync_client"
-# PROP Intermediate_Dir ".\Release\xmlrpc_sample_add_sync_client"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\\" /I "..\include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ..\lib\xmlrpc.lib kernel32.lib user32.lib gdi32.lib WinInet.lib /nologo /subsystem:console /machine:I386 /out:"..\bin\xmlrpc_sample_add_sync_client.exe"
-# SUBTRACT LINK32 /pdb:none
-
-!ELSEIF "$(CFG)" == "xmlrpc_sample_add_sync_client - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir ".\Debug\xmlrpc_sample_add_sync_client"
-# PROP Intermediate_Dir ".\Debug\xmlrpc_sample_add_sync_client"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\\" /I "..\include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 ..\lib\xmlrpcD.lib kernel32.lib user32.lib gdi32.lib WinInet.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\bin\xmlrpc_sample_add_sync_clientD.exe" /pdbtype:sept
-# SUBTRACT LINK32 /pdb:none
-
-!ENDIF
-
-# Begin Target
-
-# Name "xmlrpc_sample_add_sync_client - Win32 Release"
-# Name "xmlrpc_sample_add_sync_client - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=..\examples\xmlrpc_sample_add_client.c
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
+# Microsoft Developer Studio Project File - Name="xmlrpc_sample_add_sync_client" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=xmlrpc_sample_add_sync_client - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "xmlrpc_sample_add_sync_client.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "xmlrpc_sample_add_sync_client.mak" CFG="xmlrpc_sample_add_sync_client - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "xmlrpc_sample_add_sync_client - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "xmlrpc_sample_add_sync_client - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "xmlrpc_sample_add_sync_client - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ".\Release\xmlrpc_sample_add_sync_client"
+# PROP Intermediate_Dir ".\Release\xmlrpc_sample_add_sync_client"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I ".." /I "../include" /I "../lib/util/include" /I "../.." /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c /D "CURL_STATICLIB"
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 ..\lib\xmlrpc.lib kernel32.lib user32.lib gdi32.lib WinInet.lib /nologo /subsystem:console /machine:I386 /out:"..\bin\xmlrpc_sample_add_sync_client.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "xmlrpc_sample_add_sync_client - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ".\Debug\xmlrpc_sample_add_sync_client"
+# PROP Intermediate_Dir ".\Debug\xmlrpc_sample_add_sync_client"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I ".." /I "../include" /I "../lib/util/include" /I "../.." /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c /D "CURL_STATICLIB"
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\xmlrpcD.lib kernel32.lib user32.lib gdi32.lib WinInet.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\bin\xmlrpc_sample_add_sync_clientD.exe" /pdbtype:sept
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF
+
+# Begin Target
+
+# Name "xmlrpc_sample_add_sync_client - Win32 Release"
+# Name "xmlrpc_sample_add_sync_client - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\examples\xmlrpc_sample_add_client.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
+
Modified: freeswitch/trunk/libs/xmlrpc-c/Windows/xmlrpc_sample_auth_client.dsp
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/Windows/xmlrpc_sample_auth_client.dsp (original)
+++ freeswitch/trunk/libs/xmlrpc-c/Windows/xmlrpc_sample_auth_client.dsp Fri May 23 16:56:24 2008
@@ -1,104 +1,102 @@
-# Microsoft Developer Studio Project File - Name="xmlrpc_sample_auth_client" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=xmlrpc_sample_auth_client - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "xmlrpc_sample_auth_client.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "xmlrpc_sample_auth_client.mak" CFG="xmlrpc_sample_auth_client - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "xmlrpc_sample_auth_client - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "xmlrpc_sample_auth_client - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName "xmlrpc_sample_auth_client"
-# PROP Scc_LocalPath ".."
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "xmlrpc_sample_auth_client - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir ".\Release\xmlrpc_sample_auth_client"
-# PROP Intermediate_Dir ".\Release\xmlrpc_sample_auth_client"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\\" /I "..\include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ..\lib\xmlrpc.lib kernel32.lib user32.lib gdi32.lib WinInet.lib /nologo /subsystem:console /machine:I386 /out:"..\bin\xmlrpc_sample_auth_client.exe"
-# SUBTRACT LINK32 /pdb:none
-
-!ELSEIF "$(CFG)" == "xmlrpc_sample_auth_client - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir ".\Debug\xmlrpc_sample_auth_client"
-# PROP Intermediate_Dir ".\Debug\xmlrpc_sample_auth_client"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\\" /I "..\include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 ..\lib\xmlrpcD.lib kernel32.lib user32.lib gdi32.lib WinInet.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\bin\xmlrpc_sample_auth_clientD.exe" /pdbtype:sept
-# SUBTRACT LINK32 /pdb:none
-
-!ENDIF
-
-# Begin Target
-
-# Name "xmlrpc_sample_auth_client - Win32 Release"
-# Name "xmlrpc_sample_auth_client - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=..\examples\auth_client.c
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
+# Microsoft Developer Studio Project File - Name="xmlrpc_sample_auth_client" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=xmlrpc_sample_auth_client - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "xmlrpc_sample_auth_client.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "xmlrpc_sample_auth_client.mak" CFG="xmlrpc_sample_auth_client - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "xmlrpc_sample_auth_client - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "xmlrpc_sample_auth_client - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "xmlrpc_sample_auth_client - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ".\Release\xmlrpc_sample_auth_client"
+# PROP Intermediate_Dir ".\Release\xmlrpc_sample_auth_client"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I ".." /I "../include" /I "../lib/util/include" /I "../.." /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c /D "CURL_STATICLIB"
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 ..\lib\xmlrpc.lib kernel32.lib user32.lib gdi32.lib WinInet.lib /nologo /subsystem:console /machine:I386 /out:"..\bin\xmlrpc_sample_auth_client.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "xmlrpc_sample_auth_client - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ".\Debug\xmlrpc_sample_auth_client"
+# PROP Intermediate_Dir ".\Debug\xmlrpc_sample_auth_client"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I ".." /I "../include" /I "../lib/util/include" /I "../.." /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c /D "CURL_STATICLIB"
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\xmlrpcD.lib kernel32.lib user32.lib gdi32.lib WinInet.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\bin\xmlrpc_sample_auth_clientD.exe" /pdbtype:sept
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF
+
+# Begin Target
+
+# Name "xmlrpc_sample_auth_client - Win32 Release"
+# Name "xmlrpc_sample_auth_client - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\examples\auth_client.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
Modified: freeswitch/trunk/libs/xmlrpc-c/Windows/xmlrpc_win32_config.h
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/Windows/xmlrpc_win32_config.h (original)
+++ freeswitch/trunk/libs/xmlrpc-c/Windows/xmlrpc_win32_config.h Fri May 23 16:56:24 2008
@@ -1,130 +1,158 @@
-#pragma once
+/* Win32 version of xmlrpc_config.h.
-/* From xmlrpc_amconfig.h */
-
-/* Define to `unsigned' if <sys/types.h> doesn't define. */
-/* #undef size_t */
-
-/* Define if you have the setgroups function. */
-/* #undef HAVE_SETGROUPS */
-
-/* #undef HAVE_ASPRINTF */
-
-/* Define if you have the wcsncmp function. */
-#define HAVE_WCSNCMP 1
-
-/* Define if you have the <stdarg.h> header file. */
-#define HAVE_STDARG_H 1
-
-/* Define if you have the <sys/filio.h> header file. */
-/* #undef HAVE_SYS_FILIO_H */
-
-/* Define if you have the <sys/ioctl.h> header file. */
-/* #undef HAVE_SYS_IOCTL_H 1 */
-
-/* Define if you have the <wchar.h> header file. */
-#define HAVE_WCHAR_H 1
-
-/* Define if you have the socket library (-lsocket). */
-/* #undef HAVE_LIBSOCKET */
-
-/* Name of package */
-#define PACKAGE "xmlrpc-c"
-
-
-/* Win32 version of xmlrpc_config.h
+ For other platforms, this is generated automatically, but for Windows,
+ someone generates it manually. Nonetheless, we keep it looking as much
+ as possible like the automatically generated one to make it easier to
+ maintain (e.g. you can compare the two and see why something builds
+ differently for Windows than for some other platform).
+
+ The purpose of this file is to define stuff particular to the build
+ environment being used to build Xmlrpc-c. Xmlrpc-c source files can
+ #include this file and have build-environment-independent source code.
+
+ A major goal of this file is to reduce conditional compilation in
+ the other source files as much as possible. Even more, we want to avoid
+ having to generate source code particular to a build environment
+ except in this file.
+
+ This file is NOT meant to be used by any code outside of the
+ Xmlrpc-c source tree. There is a similar file that gets installed
+ as <xmlrpc-c/config.h> that performs the same function for Xmlrpc-c
+ interface header files that get compiled as part of a user's program.
Logical macros are 0 or 1 instead of the more traditional defined and
undefined. That's so we can distinguish when compiling code between
"false" and some problem with the code.
*/
-/* Define if va_list is actually an array. */
-#define VA_LIST_IS_ARRAY 0
-
-/* Define if we're using a copy of libwww with built-in SSL support. */
-#define HAVE_LIBWWW_SSL 0
+#ifndef XMLRPC_CONFIG_H_INCLUDED
+#define XMLRPC_CONFIG_H_INCLUDED
-/* Used to mark unused variables under GCC... */
-#define ATTR_UNUSED
+/* From xmlrpc_amconfig.h */
-/* Define this if your C library provides reasonably complete and correct Unicode wchar_t support. */
-#define HAVE_UNICODE_WCHAR 1
-
-#define DIRECTORY_SEPARATOR "\\"
+#define HAVE__STRICMP 1
+/* Name of package */
+#define PACKAGE "xmlrpc-c"
+/*----------------------------------*/
-
-/* Windows-specific includes. */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#if !defined (vsnprintf)
- #define vsnprintf _vsnprintf
-#endif
-#if !defined (snprintf)
- #define snprintf _snprintf
-#endif
-#if !defined (popen)
- #define popen _popen
+#ifndef HAVE_SETGROUPS
+#define HAVE_SETGROUPS 0
#endif
-
-
-#include <time.h>
-#include <WINSOCK.h>
-#include <direct.h> /* for _chdir() */
-
-/* We are linking against the multithreaded versions
- of the Microsoft runtimes - this makes gmtime
- equiv to gmtime_r in that Windows gmtime is threadsafe
-*/
-#if !defined (gmtime_r)
-static struct tm* gmtime_r(const time_t *timep, struct tm* result)
-{
- struct tm *local;
-
- local = gmtime(timep);
- memcpy(result,local,sizeof(struct tm));
- return result;
-}
-
+#ifndef HAVE_ASPRINTF
+#define HAVE_ASPRINTF 0
#endif
-
-#ifndef socklen_t
-typedef unsigned int socklen_t;
+#ifndef HAVE_SETENV
+#define HAVE_SETENV 0
#endif
-
-/* inttypes.h */
-#ifndef int8_t
-typedef signed char int8_t;
+#ifndef HAVE_PSELECT
+#define HAVE_PSELECT 0
#endif
-#ifndef uint8_t
-typedef unsigned char uint8_t;
+#ifndef HAVE_WCSNCMP
+#define HAVE_WCSNCMP 1
#endif
-#ifndef int16_t
-typedef signed short int16_t;
+#ifndef HAVE_GETTIMEOFDAY
+#define HAVE_GETTIMEOFDAY 0
#endif
-#ifndef uint16_t
-typedef unsigned short uint16_t;
+#ifndef HAVE_LOCALTIME_R
+#define HAVE_LOCALTIME_R 0
#endif
-#ifndef int32_t
-typedef signed int int32_t;
+#ifndef HAVE_GMTIME_R
+#define HAVE_GMTIME_R 0
#endif
-#ifndef uint32_t
-typedef unsigned int uint32_t;
+#ifndef HAVE_STRCASECMP
+#define HAVE_STRCASECMP 0
#endif
-#ifndef int64_t
-typedef __int64 int64_t;
+#ifndef HAVE_STRICMP
+#define HAVE_STRICMP 0
#endif
-#ifndef uint64_t
-typedef unsigned __int64 uint64_t;
+#ifndef HAVE__STRICMP
+#define HAVE__STRICMP 0
#endif
-#define __inline__ __inline
+#define HAVE_WCHAR_H 1
+#define HAVE_SYS_FILIO_H 0
+#define HAVE_SYS_IOCTL_H 0
+
+#define VA_LIST_IS_ARRAY 0
+
+#define HAVE_LIBWWW_SSL 0
+
+/* Used to mark an unused function parameter */
+#define ATTR_UNUSED
+
+#define DIRECTORY_SEPARATOR "\\"
+
+#define HAVE_UNICODE_WCHAR 1
+
+/* Xmlrpc-c code uses __inline__ to declare functions that should
+ be compiled as inline code. GNU C recognizes the __inline__ keyword.
+ Others recognize 'inline' or '__inline' or nothing at all to say
+ a function should be inlined.
+
+ We could make 'configure' simply do a trial compile to figure out
+ which one, but for now, this approximation is easier:
+*/
+#if (!defined(__GNUC__))
+ #if (!defined(__inline__))
+ #if (defined(__sgi) || defined(_AIX) || defined(_MSC_VER))
+ #define __inline__ __inline
+ #else
+ #define __inline__
+ #endif
+ #endif
+#endif
+
+/* MSVCRT means we're using the Microsoft Visual C++ runtime library */
+
+#ifdef _MSC_VER
+/* The compiler is Microsoft Visual C++. */
+ #define MSVCRT _MSC_VER
+#else
+ #define MSVCRT 0
+#endif
+
+#if MSVCRT
+ /* The MSVC runtime library _does_ have a 'struct timeval', but it is
+ part of the Winsock interface (along with select(), which is probably
+ its intended use), so isn't intended for use for general timekeeping.
+ */
+ #define HAVE_TIMEVAL 0
+ #define HAVE_TIMESPEC 0
+#else
+ #define HAVE_TIMEVAL 1
+ /* timespec is Posix.1b. If we need to work on a non-Posix.1b non-Windows
+ system, we'll have to figure out how to make Configure determine this.
+ */
+ #define HAVE_TIMESPEC 1
+#endif
+
+#if MSVCRT
+ #define XMLRPC_VSNPRINTF _vsnprintf
+#else
+ #define XMLRPC_VSNPRINTF vsnprintf
+#endif
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+/* Starting with MSVC 8, the runtime library defines various POSIX functions
+ such as strdup() whose names violate the ISO C standard (the standard
+ says the strXXX names are reserved for the standard), but warns you of
+ the standards violation. That warning is 4996, along with other warnings
+ that tell you you're using a function that Microsoft thinks you
+ shouldn't.
+
+ Well, POSIX is more important than that element of ISO C, so we disable
+ that warning.
+
+ FYI, msvcrt also defines _strdup(), etc, which doesn't violate the
+ naming standard. But since other environments don't define _strdup(),
+ we can't use it in portable code.
+*/
+#pragma warning(disable:4996)
+#endif
-#define HAVE_SETENV 1
-__inline BOOL setenv(const char* name, const char* value, int i)
-{
- return (SetEnvironmentVariable(name, value) != 0) ? TRUE : FALSE;
-}
+#define snprintf _snprintf
+#define popen _popen
+#define strtoll _strtoui64
+#define strtoull _strtoui64
+#endif
Added: freeswitch/trunk/libs/xmlrpc-c/Windows/xmlrpccpp.dsp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/Windows/xmlrpccpp.dsp Fri May 23 16:56:24 2008
@@ -0,0 +1,179 @@
+# Microsoft Developer Studio Project File - Name="xmlrpccpp" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=xmlrpccpp - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "xmlrpccpp.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "xmlrpccpp.mak" CFG="xmlrpccpp - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "xmlrpccpp - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "xmlrpccpp - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "xmlrpccpp - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release\xmlrpccpp"
+# PROP Intermediate_Dir "Release\xmlrpccpp"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+MTL=midl.exe
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GR /GX /O2 /I "../lib" /I "../lib/curl_transport" /I "../lib/util/include" /I "../include" /I ".." /I "../lib/expat/xmlparse" /I "../lib/abyss/src" /I "../lib/wininet_transport" /I "../.." /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "ABYSS_WIN32" /D "CURL_STATICLIB" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib\xmlrpccpp.lib"
+
+!ELSEIF "$(CFG)" == "xmlrpccpp - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug\xmlrpccpp"
+# PROP Intermediate_Dir "Debug\xmlrpccpp"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+MTL=midl.exe
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /GR /Gm /GX /ZI /Od /I "../lib" /I "../lib/curl_transport" /I "../lib/util/include" /I "../include" /I ".." /I "../lib/expat/xmlparse" /I "../lib/abyss/src" /I "../lib/wininet_transport" /I "../.." /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "ABYSS_WIN32" /D "CURL_STATICLIB" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib\xmlrpccppD.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "xmlrpccpp - Win32 Release"
+# Name "xmlrpccpp - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;cc"
+# Begin Source File
+
+SOURCE=..\src\cpp\base64.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\cpp\client.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\cpp\client_simple.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\cpp\curl.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\cpp\env_wrap.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\cpp\fault.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\cpp\girerr.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\cpp\girmem.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\cpp\libwww.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\cpp\outcome.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\cpp\packetsocket.cpp
+# PROP Exclude_From_Build 1
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\cpp\param_list.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\cpp\pstream.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\cpp\registry.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\cpp\server_abyss.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\cpp\server_pstream.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\cpp\value.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\cpp\wininet.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\cpp\xml.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\cpp\XmlRpcCpp.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\src\cpp\env_wrap.hpp
+# End Source File
+# End Group
+# End Target
+# End Project
Added: freeswitch/trunk/libs/xmlrpc-c/Windows/xmltok.dsp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/Windows/xmltok.dsp Fri May 23 16:56:24 2008
@@ -0,0 +1,138 @@
+# Microsoft Developer Studio Project File - Name="xmltok" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=xmltok - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "xmltok.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "xmltok.mak" CFG="xmltok - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "xmltok - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "xmltok - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "xmltok - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir ".\Release"
+# PROP BASE Intermediate_Dir ".\Release"
+# PROP BASE Target_Dir "."
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release\xmltok"
+# PROP Intermediate_Dir "Release\xmltok"
+# PROP Target_Dir "."
+MTL=midl.exe
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I ".." /D "NDEBUG" /D "XML_NS" /D "WIN32" /D "_WINDOWS" /D "XML_DTD" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib\xmltok.lib"
+
+!ELSEIF "$(CFG)" == "xmltok - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir ".\Debug"
+# PROP BASE Intermediate_Dir ".\Debug"
+# PROP BASE Target_Dir "."
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug\xmltok"
+# PROP Intermediate_Dir "Debug\xmltok"
+# PROP Target_Dir "."
+MTL=midl.exe
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I ".." /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "XML_DTD" /D "XML_NS" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib\xmltokD.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "xmltok - Win32 Release"
+# Name "xmltok - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90"
+# Begin Source File
+
+SOURCE=..\lib\expat\xmltok\xmlrole.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\expat\xmltok\xmltok.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
+# Begin Source File
+
+SOURCE=..\lib\expat\xmltok\asciitab.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\expat\xmltok\iasciitab.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\expat\xmltok\latin1tab.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\expat\xmltok\nametab.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\expat\xmltok\utf8tab.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\expat\xmltok\xmldef.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\expat\xmltok\xmlrole.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\expat\xmltok\xmltok.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
Added: freeswitch/trunk/libs/xmlrpc-c/common.mk
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/common.mk Fri May 23 16:56:24 2008
@@ -0,0 +1,611 @@
+# This file contains rules and variable settings for the convenience
+# of every other make file in the package.
+
+# No make file is required to use this file, but it usually saves a lot
+# of duplication.
+
+# The following make variables are meaningful as input to this file:
+#
+# SRCDIR: Name of directory which is the top of the Xmlrpc-c source tree.
+# BLDDIR: Name of directory which is the top of the Xmlrpc-c build tree.
+
+include $(SRCDIR)/Makefile.version
+
+# .DELETE_ON_ERROR is a special predefined Make target that says to delete
+# the target if a command in the rule for it fails. That's important,
+# because we don't want a half-made target sitting around looking like it's
+# fully made.
+.DELETE_ON_ERROR:
+
+GCC_WARNINGS = -Wall -Wundef -Wimplicit -W -Winline -Wundef
+ # We need -Wwrite-strings after we fix all the missing consts
+
+GCC_C_WARNINGS = $(GCC_WARNINGS) \
+ -Wmissing-declarations -Wstrict-prototypes -Wmissing-prototypes
+
+GCC_CXX_WARNINGS = $(GCC_WARNINGS) -Woverloaded-virtual -Wsynth
+
+# The NDEBUG macro says not to build code that assumes there are no bugs.
+# This makes the code go faster. The main thing it does is tell the C library
+# to make assert() a no-op as opposed to generating code to check the
+# assertion and crash the program if it isn't really true. You can add
+# -UNDEBUG (in any of various ways) to override this.
+#
+CFLAGS_COMMON = -DNDEBUG
+CXXFLAGS_COMMON = -DNDEBUG
+
+ifeq ($(C_COMPILER_GNU),yes)
+ CFLAGS_COMMON += $(GCC_C_WARNINGS) -fno-common -g -O3
+endif
+
+ifeq ($(CXX_COMPILER_GNU),yes)
+ CXXFLAGS_COMMON += $(GCC_CXX_WARNINGS) -g
+endif
+
+DISTDIR = $(BLDDIR)/$(PACKAGE)-$(VERSION)/$(SUBDIR)
+
+# MIN is the minor version number for shared libraries.
+# MAJ is the major version number, but is set separately by
+# individual make files so that the major number of one library can change
+# from one release to another while the major number of another does not.
+MIN = $(XMLRPC_MINOR_RELEASE)
+
+# CURDIR was introduced in GNU Make 3.77.
+ifeq ($(CURDIR)x,x)
+ CURDIR := $(shell /bin/pwd)
+endif
+
+##############################################################################
+# STATIC LINK LIBRARY RULES #
+##############################################################################
+
+
+# To use this rule, the including make file must set a target_specific
+# variable LIBOBJECTS (and declare dependencies that include LIBOBJECTS).
+# Example:
+# FOO_OBJECTS = foo1.o foo2.o
+# libfoo.a: LIBOBJECTS = $(FOO_OBJECTS)
+# libfoo.a: $(FOO_OBJECTS)
+# TARGET_LIBRARY_NAMES = libfoo
+
+TARGET_STATIC_LIBRARIES = \
+ $(TARGET_LIBRARY_NAMES:%=%.a) $(TARGET_LIB_NAMES_PP:%=%.a)
+$(TARGET_STATIC_LIBRARIES):
+ -rm -f $@
+ $(AR) cru $@ $(LIBOBJECTS)
+ $(RANLIB) $@
+
+
+##############################################################################
+# SHARED LIBRARY RULES, VARIABLES #
+##############################################################################
+
+ifeq ($(SHARED_LIB_TYPE),unix)
+ include $(SRCDIR)/unix-common.make
+ endif
+
+ifeq ($(SHARED_LIB_TYPE),irix)
+ include $(SRCDIR)/irix-common.make
+ endif
+
+ifeq ($(SHARED_LIB_TYPE),dll)
+ include $(SRCDIR)/dll-common.make
+ endif
+
+ifeq ($(SHARED_LIB_TYPE),dylib)
+ include $(SRCDIR)/dylib-common.make
+ endif
+
+ifeq ($(SHARED_LIB_TYPE),NONE)
+ install-shared-libraries:
+ endif
+
+# To use this rule, the including make file must set a target-specific
+# variable LIBOBJECTS (and declare dependencies that include LIBOBJECTS).
+# Analogous to static library rule above.
+
+# Optionally, including make file can set LIBDEP (probably
+# target-specific) to the -L and -l options necessary to declare the
+# libraries the target uses at run time. (This information gets built
+# into the shared library so that the runtime library loader will load
+# the specified libraries when asked to load the target library).
+
+ifeq ($(MUST_BUILD_SHLIB),Y)
+ TARGET_SHARED_LIBRARIES = $(call shlibfn, $(TARGET_LIBRARY_NAMES))
+ TARGET_SHARED_LIBS_PP = $(call shlibfn, $(TARGET_LIB_NAMES_PP))
+ ifeq ($(MUST_BUILD_SHLIBLE),Y)
+ TARGET_SHARED_LE_LIBS = \
+ $(call shliblefn, $(TARGET_LIBRARY_NAMES) $(TARGET_LIB_NAMES_PP))
+ else
+ TARGET_SHARED_LE_LIBS =
+ endif
+else
+ TARGET_SHARED_LIBRARIES =
+ TARGET_SHARED_LIBS_PP =
+ TARGET_SHARED_LE_LIBS =
+endif
+
+#------ the actual rules ----------------------------------------------------
+$(TARGET_SHARED_LIBRARIES) dummyshlib:
+ $(CCLD) $(LDFLAGS_SHLIB) $(LIBDEP) -o $@ $(LIBOBJECTS) $(LADD)
+
+$(TARGET_SHARED_LIBS_PP) dummyshlibpp:
+ $(CXXLD) $(LDFLAGS_SHLIB) $(LIBDEP) -o $@ $(LIBOBJECTS) $(LADD)
+#----------------------------------------------------------------------------
+
+LIBXMLRPC_UTIL_DIR = $(BLDDIR)/lib/libutil
+
+ifneq ($(OMIT_LIBXMLRPC_UTIL_RULE),Y)
+LIBXMLRPC_UTIL = \
+ $(call shliblefn, $(LIBXMLRPC_UTIL_DIR)/libxmlrpc_util)
+LIBXMLRPC_UTIL_A = $(LIBXMLRPC_UTIL_DIR)/libxmlrpc_util.a
+endif
+
+ifneq ($(OMIT_XMLRPC_LIB_RULE),Y)
+
+LIBXMLRPC = \
+ $(call shliblefn, $(BLDDIR)/src/libxmlrpc)
+LIBXMLRPC_CLIENT = \
+ $(call shliblefn, $(BLDDIR)/src/libxmlrpc_client)
+LIBXMLRPC_SERVER = \
+ $(call shliblefn, $(BLDDIR)/src/libxmlrpc_server)
+LIBXMLRPC_SERVER_ABYSS = \
+ $(call shliblefn, $(BLDDIR)/src/libxmlrpc_server_abyss)
+LIBXMLRPC_SERVER_CGI = \
+ $(call shliblefn, $(BLDDIR)/src/libxmlrpc_server_cgi)
+
+LIBXMLRPC_A = $(BLDDIR)/src/libxmlrpc.a
+LIBXMLRPC_CLIENT_A = $(BLDDIR)/src/libxmlrpc_client.a
+LIBXMLRPC_SERVER_A = $(BLDDIR)/src/libxmlrpc_server.a
+LIBXMLRPC_SERVER_ABYSS_A = $(BLDDIR)/src/libxmlrpc_server_abyss.a
+LIBXMLRPC_SERVER_CGI_A = $(BLDDIR)/src/libxmlrpc_server_cgi.a
+
+endif
+
+LIBXMLRPC_XMLTOK_DIR = $(BLDDIR)/lib/expat/xmltok
+
+ifneq ($(OMIT_XMLTOK_LIB_RULE),Y)
+LIBXMLRPC_XMLTOK = \
+ $(call shliblefn, $(LIBXMLRPC_XMLTOK_DIR)/libxmlrpc_xmltok)
+LIBXMLRPC_XMLTOK_A = $(LIBXMLRPC_XMLTOK_DIR)/libxmlrpc_xmltok.a
+endif
+
+LIBXMLRPC_XMLPARSE_DIR = $(BLDDIR)/lib/expat/xmlparse
+
+ifneq ($(OMIT_XMLPARSE_LIB_RULE),Y)
+LIBXMLRPC_XMLPARSE = \
+ $(call shliblefn, $(LIBXMLRPC_XMLPARSE_DIR)/libxmlrpc_xmlparse)
+LIBXMLRPC_XMLPARSE_A = $(LIBXMLRPC_XMLPARSE_DIR)/libxmlrpc_xmlparse.a
+endif
+
+LIBXMLRPC_ABYSS_DIR = $(BLDDIR)/lib/abyss/src
+
+ifneq ($(OMIT_ABYSS_LIB_RULE),Y)
+LIBXMLRPC_ABYSS = \
+ $(call shliblefn, $(LIBXMLRPC_ABYSS_DIR)/libxmlrpc_abyss)
+LIBXMLRPC_ABYSS_A = $(LIBXMLRPC_ABYSS_DIR)/libxmlrpc_abyss.a
+endif
+
+ifneq ($(OMIT_CPP_LIB_RULES),Y)
+LIBXMLRPC_CPP = \
+ $(call shliblefn, $(BLDDIR)/src/cpp/libxmlrpc_cpp)
+LIBXMLRPC_CPP_A = $(BLDDIR)/src/cpp/libxmlrpc_cpp.a
+LIBXMLRPCPP = \
+ $(call shliblefn, $(BLDDIR)/src/cpp/libxmlrpc++)
+LIBXMLRPCPP_A = $(BLDDIR)/src/cpp/libxmlrpc++.a
+LIBXMLRPC_PACKETSOCKET = \
+ $(call shliblefn, $(BLDDIR)/src/cpp/libxmlrpc_packetsocket)
+LIBXMLRPC_PACKETSOCKET_A = $(BLDDIR)/src/cpp/libxmlrpc_packetsocket.a
+LIBXMLRPC_CLIENTPP = \
+ $(call shliblefn, $(BLDDIR)/src/cpp/libxmlrpc_client++)
+LIBXMLRPC_CLIENTPP_A = $(BLDDIR)/src/cpp/libxmlrpc_client++.a
+LIBXMLRPC_SERVERPP = \
+ $(call shliblefn, $(BLDDIR)/src/cpp/libxmlrpc_server++)
+LIBXMLRPC_SERVERPP_A = $(BLDDIR)/src/cpp/libxmlrpc_server++.a
+LIBXMLRPC_SERVER_ABYSSPP = \
+ $(call shliblefn, $(BLDDIR)/src/cpp/libxmlrpc_server_abyss++)
+LIBXMLRPC_SERVER_ABYSSPP_A = $(BLDDIR)/src/cpp/libxmlrpc_server_abyss++.a
+LIBXMLRPC_SERVER_PSTREAMPP = \
+ $(call shliblefn, $(BLDDIR)/src/cpp/libxmlrpc_server_pstream++)
+LIBXMLRPC_SERVER_PSTREAMPP_A = $(BLDDIR)/src/cpp/libxmlrpc_server_pstream++.a
+endif
+
+# LIBXMLRPC_XML is the list of Xmlrpc-c libraries we need to parse
+# XML. If we're using an external library to parse XML, this is null.
+# LDLIBS_XML is the corresponding -L/-l options
+
+ifneq ($(ENABLE_LIBXML2_BACKEND),yes)
+ # We're using the internal Expat XML parser
+ LIBXMLRPC_XML = $(LIBXMLRPC_XMLPARSE) $(LIBXMLRPC_XMLTOK)
+ LDLIBS_XML = \
+ -L$(BLDDIR)/lib/expat/xmlparse -lxmlrpc_xmlparse \
+ -L$(BLDDIR)/lib/expat/xmltok -lxmlrpc_xmltok
+else
+ LDLIBS_XML = $(shell xml2-config --libs)
+endif
+
+
+##############################################################################
+# RULES TO BUILD OBJECT FILES TO LINK INTO LIBRARIES #
+##############################################################################
+
+# The including make file sets TARGET_MODS to a list of all modules that
+# might go into a library. Its a list of the bare module names. The
+# including make file also sets INCLUDES, in a target-dependent manner,
+# to the string of -I options needed for each target. Example:
+
+# TARGET_MODS = foo bar
+#
+# foo.o foo.osh: INCLUDES = -Iinclude -I/usr/include/foostuff
+# bar.o bar.osh: INCLUDES = -Iinclude -I/usr/include/barstuff
+#
+# include Makefile.common
+#
+# The above generates rules to build foo.o, bar.o, foo.osh, and bar.osh
+#
+# For C++ source files, use TARGET_MODS_PP instead.
+
+# CFLAGS and CXXFLAGS are designed to be overridden on the make command
+# line. We pile all the options except -I into these variables so the
+# user can override them all if he wants.
+
+$(TARGET_MODS:%=%.o):%.o:%.c
+ $(CC) -c -o $@ $(INCLUDES) $(CFLAGS) $<
+
+$(TARGET_MODS:%=%.osh): CFLAGS_COMMON += $(CFLAGS_SHLIB)
+
+$(TARGET_MODS:%=%.osh):%.osh:%.c
+ $(CC) -c -o $@ $(INCLUDES) $(CFLAGS) $(CFLAGS_SHLIB) $<
+
+$(TARGET_MODS_PP:%=%.o):%.o:%.cpp
+ $(CXX) -c -o $@ $(INCLUDES) $(CXXFLAGS) $<
+
+$(TARGET_MODS_PP:%=%.osh): CXXFLAGS_COMMON += $(CFLAGS_SHLIB)
+
+$(TARGET_MODS_PP:%=%.osh):%.osh:%.cpp
+ $(CXX) -c -o $@ $(INCLUDES) $(CXXFLAGS) $<
+
+
+##############################################################################
+# MISC BUILD RULES #
+##############################################################################
+
+# We use the srcdir symbolic link simply to make the make
+# rules easier to read in the make output. We could use the $(SRCDIR)
+# variable, but that makes the compile and link commands
+# a mile long. Note that Make sometime figures that a directory which
+# is a dependency is newer than the symbolic link pointing to it and wants
+# to rebuild the symbolic link. So we don't make $(SRCDIR) a
+# dependency of 'srcdir'.
+
+# We should do the same for 'blddir'. We did once before, then undid
+# it in an erroneous effort to enable parallel make. It's a little harder
+# with blddir; when we did it before, we had to use the non-symlink
+# version in a few places.
+
+srcdir:
+ $(LN_S) $(SRCDIR) $@
+blddir:
+ $(LN_S) $(BLDDIR) $@
+
+##############################################################################
+# RECURSIVE SUBDIRECTORY BUILD RULES #
+##############################################################################
+
+.PHONY: $(SUBDIRS:%=%/all)
+$(SUBDIRS:%=%/all): %/all: $(CURDIR)/%
+ $(MAKE) -C $(dir $@) -f $(SRCDIR)/$(SUBDIR)/$(dir $@)Makefile \
+ $(notdir $@)
+
+.PHONY: $(SUBDIRS:%=%/install)
+$(SUBDIRS:%=%/install): %/install: $(CURDIR)/%
+ $(MAKE) -C $(dir $@) -f $(SRCDIR)/$(SUBDIR)/$(dir $@)Makefile \
+ $(notdir $@)
+
+.PHONY: $(SUBDIRS:%=%/clean)
+$(SUBDIRS:%=%/clean): %/clean: $(CURDIR)/%
+ $(MAKE) -C $(dir $@) -f $(SRCDIR)/$(SUBDIR)/$(dir $@)Makefile \
+ $(notdir $@)
+
+.PHONY: $(SUBDIRS:%=%/distclean)
+$(SUBDIRS:%=%/distclean): %/distclean: $(CURDIR)/%
+ $(MAKE) -C $(dir $@) -f $(SRCDIR)/$(SUBDIR)/$(dir $@)Makefile \
+ $(notdir $@)
+
+.PHONY: $(SUBDIRS:%=%/check)
+$(SUBDIRS:%=%/check): %/check: $(CURDIR)/%
+ $(MAKE) -C $(dir $@) -f $(SRCDIR)/$(SUBDIR)/$(dir $@)Makefile \
+ $(notdir $@)
+
+.PHONY: $(SUBDIRS:%=%/distdir)
+$(SUBDIRS:%=%/distdir): %/distdir: $(CURDIR)/%
+ $(MAKE) -C $(dir $@) -f $(SRCDIR)/$(SUBDIR)/$(dir $@)Makefile \
+ $(notdir $@)
+
+.PHONY: $(SUBDIRS:%=%/dep)
+$(SUBDIRS:%=%/dep): %/dep: $(CURDIR)/%
+ $(MAKE) -C $(dir $@) -f $(SRCDIR)/$(SUBDIR)/$(dir $@)Makefile \
+ $(notdir $@)
+
+
+##############################################################################
+# CROSS-COMPONENT BUILD RULES #
+##############################################################################
+
+ifneq ($(OMIT_WININET_TRANSPORT_RULE),Y)
+$(BLDDIR)/lib/wininet_transport/xmlrpc_wininet_transport.o \
+$(BLDDIR)/lib/wininet_transport/xmlrpc_wininet_transport.osh \
+: FORCE
+ $(MAKE) -C $(dir $@) -f $(SRCDIR)/lib/wininet_transport/Makefile \
+ $(notdir $@)
+endif
+
+ifneq ($(OMIT_CURL_TRANSPORT_RULE),Y)
+$(BLDDIR)/lib/curl_transport/xmlrpc_curl_transport.o \
+$(BLDDIR)/lib/curl_transport/xmlrpc_curl_transport.osh \
+: FORCE
+ $(MAKE) -C $(dir $@) -f $(SRCDIR)/lib/curl_transport/Makefile \
+ $(notdir $@)
+endif
+
+ifneq ($(OMIT_LIBWWW_TRANSPORT_RULE),Y)
+$(BLDDIR)/lib/libwww_transport/xmlrpc_libwww_transport.o \
+$(BLDDIR)/lib/libwww_transport/xmlrpc_libwww_transport.osh \
+: FORCE
+ $(MAKE) -C $(dir $@) -f $(SRCDIR)/lib/libwww_transport/Makefile \
+ $(notdir $@)
+endif
+
+$(LIBXMLRPC) \
+$(LIBXMLRPC_CLIENT) \
+$(LIBXMLRPC_SERVER) \
+$(LIBXMLRPC_SERVER_ABYSS) \
+$(LIBXMLRPC_SERVER_CGI) \
+$(LIBXMLRPC_A) \
+$(LIBXMLRPC_CLIENT_A) \
+$(LIBXMLRPC_SERVER_A) \
+$(LIBXMLRPC_SERVER_ABYSS_A) \
+$(LIBXMLRPC_SERVER_CGI_A): FORCE
+ $(MAKE) -C $(dir $@) -f $(SRCDIR)/src/Makefile \
+ $(notdir $@)
+
+$(LIBXMLRPC_UTIL) $(LIBXMLRPC_UTIL_A) : FORCE
+ $(MAKE) -C $(dir $@) -f $(SRCDIR)/lib/libutil/Makefile \
+ $(notdir $@)
+
+$(LIBXMLRPC_XMLPARSE) $(LIBXMLRPC_XMLPARSE_A) : FORCE
+ $(MAKE) -C $(dir $@) -f $(SRCDIR)/lib/expat/xmlparse/Makefile \
+ $(notdir $@)
+
+$(LIBXMLRPC_XMLTOK) $(LIBXMLRPC_XMLTOK_A) : FORCE
+ $(MAKE) -C $(dir $@) -f $(SRCDIR)/lib/expat/xmltok/Makefile \
+ $(notdir $@)
+
+$(LIBXMLRPC_ABYSS) $(LIBXMLRPC_ABYSS_A): FORCE
+ $(MAKE) -C $(dir $@) -f $(SRCDIR)/lib/abyss/src/Makefile \
+ $(notdir $@)
+
+$(LIBXMLRPCPP) $(LIBXMLRPCPP_A) \
+$(LIBXMLRPC_PACKETSOCKET) $(LIBXMLRPC_PACKETSOCKET_A) \
+$(LIBXMLRPC_CLIENTPP) $(LIBXMLRPC_CLIENTPP_A) \
+$(LIBXMLRPC_SERVERPP) $(LIBXMLRPC_SERVERPP_A) \
+$(LIBXMLRPC_SERVER_ABYSSPP) $(LIBXMLRPC_SERVER_ABYSSPP_A) \
+$(LIBXMLRPC_SERVER_PSTREAMPP) $(LIBXMLRPC_SERVER_PSTREAMPP_A) \
+$(LIBXMLRPC_CPP) $(LIBXMLRPC_CPP_A) : FORCE
+ $(MAKE) -C $(dir $@) -f $(SRCDIR)/src/cpp/Makefile \
+ $(notdir $@)
+
+# For the following utilities, we don't bother with a library -- we
+# just explicitly link the object file we need. This is to save
+# complexity. If the list gets too big, we may need a library just to
+# keep link commands short.
+
+UTIL_DIR = $(BLDDIR)/lib/util
+
+UTILS = \
+ casprintf.o \
+ cmdline_parser.o \
+ cmdline_parser_cpp.o \
+ getoptx.o \
+ stripcaseeq.o \
+ string_parser.o \
+
+ifneq ($(OMIT_UTILS_RULE),Y)
+$(UTILS:%=$(UTIL_DIR)/%): FORCE
+ $(MAKE) -C $(dir $@) -f $(SRCDIR)/lib/util/Makefile \
+ $(notdir $@)
+endif
+
+CASPRINTF = $(UTIL_DIR)/casprintf.o
+
+
+# About version.h: This is a built header file, which means it is a supreme
+# pain in the ass. The biggest problem is that when we automatically make
+# dependencies (Makefile.depend), it doesn't exist yet. This means Gcc
+# generates a dependency on it being in the local directory. Therefore,
+# we generate it in the local directory, as a symbolic link, wherever it
+# is needed. But the original is always in the top level directory,
+# generated by a rule in that directory's make file. Problem 2 is that
+# the top directory's make file includes Makefile.common, so the rules
+# below conflict with it. That's what OMIT_VERSION_H is for.
+
+ifneq ($(OMIT_VERSION_H),Y)
+
+$(BLDDIR)/version.h:
+ $(MAKE) -C $(dir $@) -f $(SRCDIR)/GNUmakefile $(notdir $@)
+
+version.h: $(BLDDIR)/version.h
+ $(LN_S) $< $@
+
+endif
+
+ifneq ($(OMIT_CONFIG_H_RULE),Y)
+$(BLDDIR)/include/xmlrpc-c/config.h:
+ $(MAKE) -C $(BLDDIR)/include -f $(SRCDIR)/include/Makefile \
+ xmlrpc-c/config.h
+endif
+
+ifneq ($(OMIT_TRANSPORT_CONFIG_H),Y)
+$(BLDDIR)/transport_config.h:
+ $(MAKE) -C $(dir $@) -f $(SRCDIR)/GNUmakefile $(notdir $@)
+endif
+
+ifneq ($(OMIT_XMLRPC_C_CONFIG_TEST),Y)
+$(BLDDIR)/xmlrpc-c-config.test:
+ $(MAKE) -C $(dir $@) -f $(SRCDIR)/GNUmakefile $(notdir $@)
+endif
+
+$(TARGET_MODS:%=%.o) $(TARGET_MODS:%=%.osh): \
+ $(BLDDIR)/include/xmlrpc-c/config.h
+
+# With a separate build directory, you have to make the directory itself
+# before you can make anything in it. Here's the rule to do that.
+$(SUBDIRS:%=$(CURDIR)/%):
+ mkdir $@
+
+
+##############################################################################
+# INSTALL RULES #
+# (except shared libraries) #
+##############################################################################
+
+MKINSTALLDIRS = $(SHELL) $(SRCDIR)/mkinstalldirs
+
+.PHONY: install-common install-ltlibraries install-headers install-bin
+install-common: \
+ install-ltlibraries install-static-libraries install-shared-libraries \
+ install-headers install-bin
+
+INSTALL_LIB_CMD = $(INSTALL_DATA) $$p $(DESTDIR)$(LIBINST_DIR)/$$p
+RANLIB_CMD = $(RANLIB) $(DESTDIR)$(LIBINST_DIR)/$$p
+
+install-static-libraries: $(STATIC_LIBRARIES_TO_INSTALL)
+ $(MKINSTALLDIRS) $(DESTDIR)$(LIBINST_DIR)
+ @list='$(STATIC_LIBRARIES_TO_INSTALL)'; for p in $$list; do \
+ if test -f $$p; then \
+ echo " $(INSTALL_LIB_CMD)"; \
+ $(INSTALL_LIB_CMD); \
+ else :; fi; \
+ done
+ @$(POST_INSTALL)
+ @list='$(STATIC_LIBRARIES_TO_INSTALL)'; for p in $$list; do \
+ if test -f $$p; then \
+ echo " $(RANLIB_CMD)"; \
+ $(RANLIB_CMD); \
+ else :; fi; \
+ done
+
+HEADERDESTDIR = $(DESTDIR)$(HEADERINST_DIR)
+INSTALL_HDR_CMD = $(INSTALL_DATA) $$d$$p $(HEADERDESTDIR)/$$p
+
+install-headers: $(HEADERS_TO_INSTALL)
+ $(MKINSTALLDIRS) $(HEADERDESTDIR)
+ $(MKINSTALLDIRS) $(HEADERDESTDIR)/xmlrpc-c
+ @list='$(HEADERS_TO_INSTALL)'; for p in $$list; do \
+ if test -f "$$p"; then d= ; else d="$(SRCDIR)/$(SUBDIR)/"; fi; \
+ echo " $(INSTALL_HDR_CMD)"; \
+ $(INSTALL_HDR_CMD); \
+ done
+
+
+INSTALL_PROGRAM_CMD = $(INSTALL_PROGRAM) $$p $(DESTDIR)$(PROGRAMINST_DIR)/$$p
+
+install-bin: $(PROGRAMS_TO_INSTALL) $(DESTDIR)$(PROGRAMINST_DIR)
+ @list='$(PROGRAMS_TO_INSTALL)'; \
+ for p in $$list; do \
+ echo "$(INSTALL_PROGRAM_CMD)"; \
+ $(INSTALL_PROGRAM_CMD); \
+ done
+
+$(DESTDIR)$(PROGRAMINST_DIR):
+ $(MKINSTALLDIRS) $@
+
+
+##############################################################################
+# MISCELLANEOUS RULES #
+##############################################################################
+
+.PHONY: clean-common
+clean-common:
+ rm -f *.o *.osh *.a *.s *.i *.la *.lo
+ rm -f *.$(SHLIB_SUFFIX) *.$(SHLIB_SUFFIX).*
+ rm -rf .libs
+ifneq ($(OMIT_VERSION_H),Y)
+ rm -f version.h
+endif
+
+.PHONY: distclean-common
+distclean-common:
+# Makefile.depend is generated by 'make dep' and contains only dependencies
+# that make parts get _rebuilt_ when parts upon which they depend change.
+# It does not contain dependencies that are necessary to cause a part to
+# get built in the first place. E.g. if foo.c uses bar.h and bar.h gets built
+# by a make rule, you must put the dependency of foo.c on bar.h somewhere
+# besides Makefile.depend.
+#
+# Because of this, a user doesn't need Makefile.depend, because he
+# doesn't modify source files. A developer, on the other hand, must make his
+# own Makefile.depend, because 'make dep' creates Makefile.depend with
+# absolute pathnames, specific to the developer's system.
+#
+# So we obliterate Makefile.depend here. The build will automatically
+# create an empty Makefile.depend when it is needed for the user. The
+# developer must do 'make dep' if he wants to edit and rebuild.
+#
+# Other projects have the build automatically build a true
+# Makefile.depend, suitable for a developer. We have found that to be
+# an utter disaster -- it's way too complicated and prone to failure,
+# especially with built .h files. Better not to burden the user, who
+# gains nothing from it, with that.
+#
+ rm -f Makefile.depend
+ rm -f srcdir blddir
+
+.PHONY: distdir-common
+distdir-common:
+ @for file in $(DISTFILES); do \
+ d=$(SRCDIR); \
+ if test -d $$d/$$file; then \
+ cp -pr $$d/$$file $(DISTDIR)/$$file; \
+ else \
+ test -f $(DISTDIR)/$$file \
+ || ln $$d/$$file $(DISTDIR)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(DISTDIR)/$$file || :; \
+ fi; \
+ done
+
+DEP_SOURCES = $(wildcard *.c *.cpp)
+
+# This is a filter to turn "foo.o:" rules into "foo.o foo.lo foo.osh:"
+# to make dependencies for all the various forms of object file out of
+# a file made by a depedency generator that knows only about .o.
+
+DEPEND_MASSAGER = perl -walnpe's{^(.*)\.o:}{$$1.o $$1.lo $$1.osh:}'
+
+
+
+.PHONY: dep-common
+dep-common: FORCE
+ifneq ($(DEP_SOURCES)x,x)
+ -$(CC) -MM -MG -I. $(INCLUDES) $(DEP_SOURCES) | \
+ $(DEPEND_MASSAGER) \
+ >Makefile.depend
+endif
+
+Makefile.depend:
+ cat /dev/null >$@
+
+# The automatic dependency generation is a pain in the butt and
+# totally unnecessary for people just installing the distributed code,
+# so to avoid needless failures in the field and a complex build, the
+# 'distclean' target simply makes Makefile.depend an empty file. A
+# developer may do 'make dep' to create a Makefile.depend full of real
+# dependencies.
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
+
+
+# Use the FORCE target as a dependency to force a target to get remade
+FORCE:
Added: freeswitch/trunk/libs/xmlrpc-c/config.mk.in
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/config.mk.in Fri May 23 16:56:24 2008
@@ -0,0 +1,336 @@
+# config.mk is generated by 'configure' using config.mk.in
+# as a template and information that 'configure' gathers from the build
+# system and from user options.
+
+# config.mk should someday replace most of the other files that
+# 'configure' generates, thus simplifying development and customization.
+# config.mk is intended to contain information specific to the
+# particular build environment or user build choices.
+
+# Furthermore, most of the logic in 'configure', and thus 'configure.in',
+# should go into the make files to simplify the build. config.mk
+# should just pass raw configure variables through to the make file.
+
+# Tokens of the form @TOKEN@ in the template file get replaced by
+# 'configure' with the values of variables of the same name within
+# 'configure', because of a AC_SUBST(TOKEN) statement in the
+# 'configure.in' from which 'configure' was built.
+
+# Here are the options the user chose on 'configure':
+
+ENABLE_ABYSS_SERVER = @ENABLE_ABYSS_SERVER@
+ENABLE_ABYSS_THREADS = @ENABLE_ABYSS_THREADS@
+ENABLE_CPLUSPLUS = @ENABLE_CPLUSPLUS@
+ENABLE_CGI_SERVER = @ENABLE_CGI_SERVER@
+ENABLE_LIBXML2_BACKEND = @ENABLE_LIBXML2_BACKEND@
+
+MUST_BUILD_WININET_CLIENT = @MUST_BUILD_WININET_CLIENT@
+MUST_BUILD_CURL_CLIENT = @MUST_BUILD_CURL_CLIENT@
+MUST_BUILD_LIBWWW_CLIENT = @MUST_BUILD_LIBWWW_CLIENT@
+LSOCKET = @LSOCKET@
+WININET_LDADD = @WININET_LDADD@
+WININET_RPATH = @WININET_RPATH@
+WININET_WL_RPATH = @WININET_WL_RPATH@
+CURL_LDADD = @CURL_LDADD@
+CURL_RPATH = @CURL_RPATH@
+CURL_WL_RPATH = @CURL_WL_RPATH@
+LIBWWW_LDADD = @LIBWWW_LDADD@
+LIBWWW_RPATH = @LIBWWW_RPATH@
+LIBWWW_WL_RPATH = @LIBWWW_WL_RPATH@
+FEATURE_LIST = @FEATURE_LIST@
+ABS_SRCDIR = @abs_srcdir@
+PREFIX = @prefix@
+
+
+HAVE_WCHAR_H_DEFINE = @HAVE_WCHAR_H_DEFINE@
+
+# Stuff 'configure' figured out about our build platform:
+
+SHELL = @SHELL@
+CC = @CC@
+CXX = @CXX@
+CCLD = $(CC)
+CXXLD = $(CXX)
+AR = ar
+RANLIB = ranlib
+LN_S = ln -s
+INSTALL = $(SRCDIR)/install-sh
+
+C_COMPILER_GNU = @C_COMPILER_GNU@
+CXX_COMPILER_GNU = @CXX_COMPILER_GNU@
+
+# Stuff 'configure' figured out via AC_CANONICAL_HOST macro in configure.in
+# and config.guess program and 'configure' command options:
+
+# HOST_OS names the operating system on which Xmlrpc-c is to run.
+# E.g. "linux-gnu".
+HOST_OS = @host_os@
+
+###############################################################################
+
+MUST_BUILD_CLIENT = no
+ifeq ($(MUST_BUILD_WININET_CLIENT),yes)
+ MUST_BUILD_CLIENT = yes
+endif
+ifeq ($(MUST_BUILD_CURL_CLIENT),yes)
+ MUST_BUILD_CLIENT = yes
+endif
+ifeq ($(MUST_BUILD_LIBWWW_CLIENT),yes)
+ MUST_BUILD_CLIENT = yes
+endif
+
+
+##############################################################################
+# SHARED LIBRARY STUFF
+##############################################################################
+
+# Shared libraries are very difficult, because how you build and use
+# them varies greatly from one platform to the next.
+
+# First, we break down shared library schemes into a few major types,
+# and indicate the type by SHARED_LIB_TYPE.
+
+# We also have a bunch of other make variables that reflect the different
+# ways we have to build on and for different platforms:
+
+# CFLAGS_SHLIB is a set of flags needed to compile a module which will
+# become part of a shared library.
+
+# On older systems, you have to make shared libraries out of position
+# independent code, so you need -fpic or -fPIC here. (The rule is: if
+# -fpic works, use it. If it bombs, go to -fPIC). On newer systems,
+# it isn't necessary, but can save real memory at the expense of
+# execution speed. Without position independent code, the library
+# loader may have to patch addresses into the executable text. On an
+# older system, this would cause a program crash because the loader
+# would be writing into read-only shared memory. But on newer
+# systems, the system silently creates a private mapping of the page
+# or segment being modified (the "copy on write" phenomenon). So it
+# needs its own private real page frame.
+
+# We have seen -fPIC required on IA64 and AMD64 machines (GNU
+# compiler/linker). Build-time linking fails without it. I don't
+# know why -- history seems to be repeating itself. 2005.02.23.
+
+# SHLIB_CLIB is the link option to include the C library in a shared library,
+# normally "-lc". On typical systems, this serves no purpose. On some,
+# though, it causes information about which C library to use to be recorded
+# in the shared library and thus choose the correct library among several or
+# avoid using an incompatible one. But on some systems, the link fails.
+# On 2002.09.30, "John H. DuBois III" <spcecdt at armory.com> reports that on
+# SCO OpenServer, he gets the following error message with -lc:
+#
+# -lc; relocations referenced ; from file(s) /usr/ccs/lib/libc.so(random.o);
+# fatal error: relocations remain against allocatable but non-writable
+# section: ; .text
+#
+# On Bryan's system, with gcc 2.95.3 and glibc 2.2.2, -lc causes
+# throws (from anywhere in a program that links the shared library)
+# not to work. I have no idea how.
+
+# LDFLAGS_SHLIB is the linker (Ld) flags needed to generate a shared
+# library from object files. It may use $(SONAME) as the soname for
+# the shared library being created (assuming sonames exist).
+#
+# This make file defines these functions that the including make file
+# can use:
+#
+# $(call shlibfn, LIBNAMELIST): file names of shared libraries
+# whose base names are LIBNAMELIST. E.g. if LIBNAMELIST is
+# "libfoo libbar", function returns "libfoo.so.3.1 libbar.so.3.1"
+#
+# $(call shliblefn, LIBNAMELIST): same as shlibfn, but for the file you
+# use at link-edit time. E.g. libfoo.so .
+
+# NEED_RPATH says on this platform, when you link-edit an executable you
+# need to have -R linker options to tell where to look, at run time,
+# for the shared libraries that the program uses. The linker puts that
+# information into the executable.
+
+# NEED_WL_RPATH is like NEED_RPATH, but it's a compiler option for when
+# you have the compiler call the linker. So E.g. "-Wl,-rpath,/my/runtime",
+# which tells the compiler to pass the option "-rpath /my/runtime" to
+# the linker.
+
+# Defaults:
+NEED_WL_RPATH=no
+NEED_RPATH=no
+
+# We build shared libraries only for platforms for which we've figured
+# out how. For the rest, we have this default:
+SHARED_LIB_TYPE = NONE
+MUST_BUILD_SHLIB = N
+MUST_BUILD_SHLIBLE = N
+shlibfn = $(1:%=%.shlibdummy)
+shliblefn = $(1:%=%.shlibledummy)
+
+ifeq ($(HOST_OS),linux-gnu)
+ # Assume linker is GNU Compiler (gcc)
+ SHARED_LIB_TYPE = unix
+ MUST_BUILD_SHLIB = Y
+ MUST_BUILD_SHLIBLE = Y
+ SHLIB_SUFFIX = so
+ shlibfn = $(1:%=%.$(SHLIB_SUFFIX).$(MAJ).$(MIN))
+ shliblefn = $(1:%=%.$(SHLIB_SUFFIX))
+# SHLIB_CLIB = -lc
+ LDFLAGS_SHLIB = -shared -Wl,-soname,$(SONAME) $(SHLIB_CLIB)
+ CFLAGS_SHLIB=-fPIC
+endif
+
+ifeq ($(findstring solaris,$(HOST_OS)),solaris)
+ SHARED_LIB_TYPE = unix
+ MUST_BUILD_SHLIB = Y
+ MUST_BUILD_SHLIBLE = Y
+ SHLIB_SUFFIX = so
+ shlibfn = $(1:%=%.$(SHLIB_SUFFIX).$(MAJ).$(MIN))
+ shliblefn = $(1:%=%.$(SHLIB_SUFFIX))
+ # Solaris compiler (Sun C 5.5) can't take multiple ld options as
+ # -Wl,-a,-b . Ld sees -a,-b in that case.
+ LDFLAGS_SHLIB = -Wl,-Bdynamic -Wl,-G -Wl,-h -Wl,$(SONAME)
+ CFLAGS_SHLIB = -Kpic
+endif
+
+ifeq ($(HOST_OS),aix)
+ SHARED_LIB_TYPE = unix
+ MUST_BUILD_SHLIB = Y
+ MUST_BUILD_SHLIBLE = Y
+ SHLIB_SUFFIX = a
+ shlibfn = $(1:%=%.$(SHLIB_SUFFIX).$(MAJ).$(MIN))
+ shliblefn = $(1:%=%.$(SHLIB_SUFFIX))
+ LDFLAGS_SHLIB = -qmkshrobj
+endif
+
+ifeq ($(HOST_OS),hpux)
+ SHARED_LIB_TYPE = unix
+ MUST_BUILD_SHLIB = Y
+ MUST_BUILD_SHLIBLE = Y
+ SHLIB_SUFFIX = sl
+ shlibfn = $(1:%=%.$(SHLIB_SUFFIX).$(MAJ).$(MIN))
+ shliblefn = $(1:%=%.$(SHLIB_SUFFIX))
+ LDFLAGS_SHLIB: -shared -fPIC
+endif
+
+ifeq ($(HOST_OS),osf)
+ SHARED_LIB_TYPE = unix
+ MUST_BUILD_SHLIB = Y
+ MUST_BUILD_SHLIBLE = Y
+ SHLIB_SUFFIX = so
+ shlibfn = $(1:%=%.$(SHLIB_SUFFIX).$(MAJ).$(MIN))
+ shliblefn = $(1:%=%.$(SHLIB_SUFFIX))
+ LDFLAGS_SHLIB = -shared -expect_unresolved
+endif
+
+ifeq ($(findstring netbsd,$(HOST_OS)),netbsd)
+ SHARED_LIB_TYPE = unix
+ SHLIB_SUFFIX = so
+ MUST_BUILD_SHLIB = Y
+ MUST_BUILD_SHLIBLE = Y
+ shlibfn = $(1:%=%.$(SHLIB_SUFFIX).$(MAJ).$(MIN))
+ shliblefn = $(1:%=%.$(SHLIB_SUFFIX))
+ CFLAGS_SHLIB = -fpic
+ LDFLAGS_SHLIB = -shared -Wl,-soname,$(SONAME) $(SHLIB_CLIB)
+ NEED_WL_RPATH=yes
+endif
+
+ifeq ($(HOST_OS),dragonfly)
+ SHARED_LIB_TYPE = unix
+ MUST_BUILD_SHLIB = Y
+ MUST_BUILD_SHLIBLE = Y
+ SHLIB_SUFFIX = so
+ shlibfn = $(1:%=%.$(SHLIB_SUFFIX).$(MAJ).$(MIN))
+ shliblefn = $(1:%=%.$(SHLIB_SUFFIX))
+ CFLAGS_SHLIB = -fpic
+ LDFLAGS_SHLIB = -shared -Wl,-soname,$(SONAME) $(SHLIB_CLIB)
+endif
+
+ifeq ($(HOST_OS),beos)
+ SHARED_LIB_TYPE = unix
+ MUST_BUILD_SHLIB = Y
+ MUST_BUILD_SHLIBLE = Y
+ SHLIB_SUFFIX = so
+ shlibfn = $(1:%=%.$(SHLIB_SUFFIX).$(MAJ).$(MIN))
+ shliblefn = $(1:%=%.$(SHLIB_SUFFIX))
+ LDFLAGS_SHLIB = -nostart
+endif
+
+ifeq ($(patsubst darwin%, darwin, $(HOST_OS)), darwin)
+ # (I once saw a system that generated 'darwin8.10.1').
+ SHARED_LIB_TYPE = dylib
+ MUST_BUILD_SHLIB = Y
+ MUST_BUILD_SHLIBLE = Y
+ SHLIB_SUFFIX = dylib
+ shlibfn = $(1:%=%.$(MAJ).$(MIN).$(SHLIB_SUFFIX))
+ shliblefn = $(1:%=%.$(SHLIB_SUFFIX))
+ LDFLAGS_SHLIB = -shared -Wl,-soname,$(SONAME) $(SHLIB_CLIB)
+endif
+
+ifeq ($(HOST_OS),irix)
+ SHARED_LIB_TYPE = irix
+ MUST_BUILD_SHLIB = Y
+ MUST_BUILD_SHLIBLE = Y
+ SHLIB_SUFFIX = so
+ shlibfn = $(1:%=%.$(SHLIB_SUFFIX).$(MAJ))
+ shliblefn = $(1:%=%.$(SHLIB_SUFFIX))
+
+ VERSIONPERLPROG = \
+ print "sgi$(MAJ)." . join(":sgi$(MAJ) . ", (0..$(MIN))) . "\n"
+ LDFLAGS_SHLIB = -shared -n32 -soname $(SONAME) \
+ -set_version $(shell perl -e '$(VERSIONPERLPROG)') -lc
+endif
+
+ifeq ($(HOST_OS),cygwin)
+ SHARED_LIB_TYPE = dll
+ MUST_BUILD_SHLIB = Y
+ MUST_BUILD_SHLIBLE = N
+ SHLIB_SUFFIX = dll
+ shlibfn = $(1:lib%=$(SHLIB_PREFIX)%.$(SHLIB_SUFFIX).$(MAJ).$(MIN))
+ shliblefn = $(1:%=%.shlibledummy)
+ LDFLAGS_SHLIB = -shared -Wl,-soname,$(SONAME) $(SHLIB_CLIB)
+endif
+
+##############################################################################
+# MISCELLANEOUS
+##############################################################################
+
+# BUILDTOOL_CC is the compiler to use to generate build tools, which we
+# will then run to build product. The typical reason this would be
+# different from CC is that you're cross-compiling: the product will run
+# in Environment A, but you're building in Environment B, so you must
+# build the build toos for Environment B.
+
+# The cross compiling user can update Makefile.config or override
+# BUILDTOOL_CC on a make command.
+
+BUILDTOOL_CC = $(CC)
+BUILDTOOL_CCLD = $(CCLD)
+
+# Here are the commands 'make install' uses to install various kinds of files:
+
+INSTALL_PROGRAM = $(INSTALL) -c -m 755
+INSTALL_SHLIB = $(INSTALL) -c -m 755
+INSTALL_DATA = $(INSTALL) -c -m 644
+INSTALL_SCRIPT = $(INSTALL) -c -m 755
+
+# Here are the locations at which 'make install' puts files:
+
+# PREFIX is designed to be overridden at make time if the user decides
+# he doesn't like the default specified at 'configure' time.
+
+LIBINST_DIR = $(PREFIX)/lib
+HEADERINST_DIR = $(PREFIX)/include
+PROGRAMINST_DIR = $(PREFIX)/bin
+
+# DESTDIR is designed to be overridden at make time in order to relocate
+# the entire install into a subdirectory.
+DESTDIR =
+
+# VPATH probably doesn't belong in this file, but it's a convenient
+# place to set it once. VPATH is a special Make variable that tells
+# Make where to look for dependencies. E.g. if a make file says bar.c
+# is a dependency of bar.o and VPATH is ".:/usr/src/mypkg", Make will
+# look for bar.c first in the current directory (.) (as it would with
+# no VPATH), then in /usr/src/mypkg. The purpose of this is to allow
+# you to build in a fresh build directory, while your source stays in
+# the read-only directory /usr/src/mypkg .
+
+VPATH := .:$(SRCDIR)/$(SUBDIR)
Modified: freeswitch/trunk/libs/xmlrpc-c/configure.in
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/configure.in (original)
+++ freeswitch/trunk/libs/xmlrpc-c/configure.in Fri May 23 16:56:24 2008
@@ -1,30 +1,21 @@
dnl Process this file with autoconf to produce a configure script.
AC_INIT(include/xmlrpc-c/base.h)
-AC_CONFIG_HEADERS(xmlrpc_amconfig.h)
+AM_CONFIG_HEADER(xmlrpc_amconfig.h)
dnl =======================================================================
dnl Define PACKAGE, VERSION, @PACKAGE@, @VERSION@
dnl =======================================================================
-dnl Increment the package version for each release.
-AM_INIT_AUTOMAKE(xmlrpc-c, 1.03.13)
-
-dnl This version number needs to be changed in several *different* tricky
-dnl ways for each release. Please read the libtool documentation very
-dnl closely before touching this or making a release!
-VERSION_INFO="-version-info 7:0:4"
-AC_SUBST(VERSION_INFO)
-
-dnl Get our host type.
+dnl "x.xx" is supposed to be a version number, but is meaningless here.
+dnl The real version number is in Makefile.version.
+AM_INIT_AUTOMAKE(xmlrpc-c, x.xx)
+
+dnl Define @build@, @build_cpu@, @build_vendor@, @build_os,
+dnl @host, @host_cpu@, @host_vender, and @host_os@ substitutions.
+dnl "host" means the target system -- the one for which we are building.
+dnl "build" means the system that will do the building.
AC_CANONICAL_HOST
-XMLRPC_HOST_TYPE=$host
-AC_SUBST(XMLRPC_HOST_TYPE)
-
-dnl We need this to compensate for an incompatibility between autoconf
-dnl and our libtool. autoconf generates an invalid ltconfig command
-dnl otherwise.
-test -z "$target" && target=NONE
dnl =======================================================================
dnl Decide What To Build
@@ -95,11 +86,6 @@
AC_SUBST(MUST_BUILD_LIBWWW_CLIENT)
-if test "$MUST_BUILD_WININET_CLIENT $MUST_BUILD_CURL_CLIENT $MUST_BUILD_LIBWWW_CLIENT" = "no no no"; then
- AC_MSG_NOTICE([We are not building any client XML transport, therefore we will not build the client library at all.])
-fi
-
-
dnl Set up the appropriate Makefile substitutions.
LIBXMLRPC_CLIENT_LA=libxmlrpc_client.la
@@ -203,34 +189,6 @@
AC_SUBST(XMLRPCCPP_H)
AC_SUBST(XML_RPC_API2CPP_SUBDIR)
-dnl =======================================================================
-dnl Decide what to do about Unicode.
-dnl =======================================================================
-
-dnl Check to see if we should build our Unicode stuff.
-AC_MSG_CHECKING(whether to build Unicode support)
-AC_ARG_ENABLE(unicode,
- [ --disable-unicode Don't build Unicode and wchar_t capability], ,
-enable_unicode=yes)
-AC_MSG_RESULT($enable_unicode)
-
-dnl Do all the work...
-if test x"$enable_unicode" != xno; then
- FEATURE_LIST="unicode $FEATURE_LIST"
- HAVE_UNICODE_WCHAR_DEFINE=1
-
- dnl Unicode function needed by test suites.
- AC_CHECK_FUNCS(wcsncmp)
-
- AC_CHECK_HEADERS(wchar.h, , [
- AC_MSG_ERROR(wchar.h is required to build this library)
- ])
-
-else
- HAVE_UNICODE_WCHAR_DEFINE=0
-fi
-
-AC_SUBST(HAVE_UNICODE_WCHAR_DEFINE)
AC_SUBST(FEATURE_LIST)
@@ -240,8 +198,9 @@
dnl =======================================================================
AC_PROG_CC
-AC_PROG_CXX
-AC_PROG_INSTALL
+if test x"$enable_cplusplus" != xno; then
+ AC_PROG_CXX
+fi
dnl =======================================================================
@@ -255,6 +214,18 @@
# require too much testing.)
AC_CHECK_FUNC(socket, , AC_CHECK_LIB(socket, socket))
+# Above sets LIBS, which is not all that useful because we don't want
+# to include every library in every link. It also sets
+# ac_cv_lib_socket_socket, which we use to pass more specific information
+# to the configuration files.
+
+if test x"$ac_cv_lib_socket_socket" = xyes; then
+ LSOCKET=-lsocket
+else
+ LSOCKET=
+fi
+AC_SUBST(LSOCKET)
+
# For some reason, we don't seem to need this on Solaris. If you do
# need it, go ahead and try it.
# AC_CHECK_FUNC(gethostent, , AC_CHECK_LIB(nsl, gethostent))
@@ -266,13 +237,48 @@
AC_STDC_HEADERS
+dnl We don't use AM_CONFIG_HEADER to define HAVE_WCHAR_H, etc. because
+dnl the following is more straightforward and easier to understand,
+dnl especially for a newcomer. Furthermore, AM_CONFIG_HEADER represents
+dnl false as undefined, whereas our scheme represents it as 0. undefined
+dnl is a poor choice because it often means just that you neglected to
+dnl choose a value for some reason.
+
+dnl defines ac_cv_header_wchar_h, etc:
+AC_CHECK_HEADERS(wchar.h)
+
+if test x"$ac_cv_header_wchar_h" = xyes; then
+ HAVE_WCHAR_H_DEFINE=1
+else
+ HAVE_WCHAR_H_DEFINE=0
+fi
+AC_SUBST(HAVE_WCHAR_H_DEFINE)
+
+# Needed by Abyss on Solaris:
+
+AC_CHECK_HEADERS(sys/filio.h)
+if test x"$ac_cv_header_sys_filio_h" = xyes; then
+ HAVE_SYS_FILIO_H_DEFINE=1
+else
+ HAVE_SYS_FILIO_H_DEFINE=0
+fi
+AC_SUBST(HAVE_SYS_FILIO_H_DEFINE)
+
+# Needed by Abyss on Solaris:
+
+AC_CHECK_HEADERS(sys/ioctl.h)
+if test x"$ac_cv_header_sys_ioctl_h" = xyes; then
+ HAVE_SYS_IOCTL_H_DEFINE=1
+else
+ HAVE_SYS_IOCTL_H_DEFINE=0
+fi
+AC_SUBST(HAVE_SYS_IOCTL_H_DEFINE)
+
+
AC_CHECK_HEADERS(stdarg.h, , [
AC_MSG_ERROR(stdarg.h is required to build this library)
])
-# I/O headers, needed by Abyss on Solaris.
-AC_CHECK_HEADERS(sys/filio.h sys/ioctl.h)
-
dnl =======================================================================
dnl Checks for typedefs, structures, and compiler characteristics.
@@ -296,13 +302,12 @@
fi
AC_SUBST(VA_LIST_IS_ARRAY_DEFINE)
-dnl See if the compiler supports __attribute__ gracefully.
-AC_MSG_CHECKING(whether compiler supports __attribute__)
+AC_MSG_CHECKING(whether compiler has __attribute__)
AC_TRY_COMPILE(, [int x __attribute__((__unused__));],
-compiler_supports_attribute=yes,
-compiler_supports_attribute=no)
-AC_MSG_RESULT($compiler_supports_attribute)
-if test x"$compiler_supports_attribute" = xyes; then
+compiler_has_attribute=yes,
+compiler_has_attribute=no)
+AC_MSG_RESULT($compiler_has_attribute)
+if test x"$compiler_has_attribute" = xyes; then
ATTR_UNUSED="__attribute__((__unused__))"
else
ATTR_UNUSED=
@@ -318,13 +323,28 @@
AC_MSG_ERROR(your C library does not provide vsnprintf)
])
-dnl CygWin looks like Unix, but doesn't provide setgroups.
+dnl Unicode function needed by test suites.
+AC_CHECK_FUNCS(wcsncmp)
+
+dnl CygWin doesn't provide setgroups.
AC_CHECK_FUNCS(setgroups)
AC_CHECK_FUNCS(asprintf)
AC_CHECK_FUNCS(setenv)
+dnl uclib doesn't have pselect
+AC_CHECK_FUNCS(pselect)
+
+dnl Windows doesn't have gettimeofday, localtime_r, or gmtime_r
+AC_CHECK_FUNCS(gettimeofday)
+AC_CHECK_FUNCS(localtime_r)
+AC_CHECK_FUNCS(gmtime_r)
+
+dnl Windows doesn't have strcasecmp;
+AC_CHECK_FUNCS(strcasecmp)
+AC_CHECK_FUNCS(stricmp)
+AC_CHECK_FUNCS(_stricmp)
dnl =======================================================================
dnl Checks for operating system features.
@@ -339,8 +359,6 @@
dnl =======================================================================
dnl ABYSS Configuration
dnl =======================================================================
-dnl Abyss doesn't pay any attention to xmlrpc_config.h, so we need to
-dnl pass it some flags on the command-line.
AC_MSG_CHECKING(whether to use Abyss pthread function)
AC_ARG_ENABLE(abyss-threads,
@@ -353,9 +371,7 @@
if test x"$enable_abyss_threads" != xno; then
CFLAGS="$CFLAGS -D_THREAD"
- LIBABYSS_LDADD="-lpthread"
fi
-AC_SUBST(LIBABYSS_LDADD)
dnl =======================================================================
@@ -435,7 +451,7 @@
dnl Finding w3c-libwww
dnl =======================================================================
dnl Once upon a time, we used a patched copy of libwww that needed to
-dnl co-exist with the system copy of libwww. We have some vestigal support
+dnl co-exist with the system copy of libwww. We have some vestigal function
dnl for keeping track of libwww's rpath, although this is no longer really
dnl necessary.
@@ -540,7 +556,7 @@
dnl Oh, such massive brain damage! Because there may be another copy
dnl of curl in the default dynamic loader search path, we need to
- dnl adjust the search patch manually. Just gag me with a backquote, OK?
+ dnl adjust the search path manually. Just gag me with a backquote, OK?
AC_MSG_CHECKING(for curl library directory)
dnl Yawn. We're using the regular boring version.
CURL_LIBDIR="`$CURL_CONFIG --prefix`/lib"
@@ -581,39 +597,15 @@
enable_libxml2_backend=no)
AC_MSG_CHECKING(whether to build the libxml2 backend)
AC_MSG_RESULT($enable_libxml2_backend)
-ENABLE_LIBXML2_BACKEND=$enable_libxml2_backend
-AC_SUBST(ENABLE_LIBXML2_BACKEND)
-
-dnl If we're using the libxml2 backend, look for pkg-config
-if test x"$enable_libxml2_backend" != xno; then
- AC_MSG_CHECKING(for pkg-config)
- AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
- if test x$PKG_CONFIG = xno; then
- AC_MSG_ERROR([*** pkg-config not found. See http://www.freedesktop.org/software/pkgconfig/])
- fi
-
-dnl Set up the appropriate Makefile substitutions
- LIBXML2_CFLAGS=`pkg-config --cflags libxml-2.0`
- AC_SUBST(LIBXML2_CFLAGS)
- CFLAGS="$CFLAGS $LIBXML2_CFLAGS"
-
- LIBXML2_LIBS=`pkg-config --libs libxml-2.0`
- AC_SUBST(LIBXML2_LIBS)
- EXTRA_XML_LIBS="$LIBXML2_LIBS"
-else
- EXTRA_XML_LIBS="-lxmlrpc_xmlparse -lxmlrpc_xmltok"
+if test $enable_libxml2_backend = yes; then
+ AC_CHECK_PROG(have_xml2_config, xml2-config, yes, no)
+ if test $have_xml2_config = no; then
+ AC_MSG_ERROR([You specified --enable-libxml2_backend, but don't appear to have libxml2 installed (no working xml2-config in your command search path), so we cannot not build for libxml2])
+ fi
fi
-
-AC_SUBST(EXTRA_XML_LIBS)
-
-AC_MSG_CHECKING(whether to test with Electric Fence)
-AC_ARG_ENABLE(efence,
- [ --enable-efence Enable malloc/free debugging with Bruce Perens\'
- Electric Fence library (test suites only).])
-AC_MSG_RESULT($enable_efence)
-ENABLE_EFENCE=$enable_efence
-AC_SUBST(ENABLE_EFENCE)
+ENABLE_LIBXML2_BACKEND=$enable_libxml2_backend
+AC_SUBST(ENABLE_LIBXML2_BACKEND)
dnl =======================================================================
dnl Compiler information
@@ -634,57 +626,30 @@
AC_SUBST(BUILDDIR)
+dnl =======================================================================
+dnl Output our results.
+dnl =======================================================================
-AC_DEFUN([AX_COMPILER_VENDOR],
-[
-AC_CACHE_CHECK([for _AC_LANG compiler vendor], ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor,
- [ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor=unknown
- # note: don't check for gcc first since some other compilers define __GNUC__
- for ventest in intel:__ICC,__ECC,__INTEL_COMPILER ibm:__xlc__,__xlC__,__IBMC__,__IBMCPP__ gnu:__GNUC__ sun:__SUNPRO_C,__SUNPRO_CC hp:__HP_cc,__HP_aCC dec:__DECC,__DECCXX,__DECC_VER,__DECCXX_VER borland:__BORLANDC__,__TURBOC__ comeau:__COMO__ cray:_CRAYC kai:__KCC lcc:__LCC__ metrowerks:__MWERKS__ sgi:__sgi,sgi microsoft:_MSC_VER watcom:__WATCOMC__ portland:__PGI; do
- vencpp="defined("`echo $ventest | cut -d: -f2 | sed 's/,/) || defined(/g'`")"
- AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[
-#if !($vencpp)
- thisisanerror;
-#endif
-])], [ax_cv_]_AC_LANG_ABBREV[_compiler_vendor=`echo $ventest | cut -d: -f1`; break])
- done
- ])
-])
+dnl Note that AM_CONFIG_HEADER at the top of this file outputs another
+dnl result: xmlrpc_amconfig.h .
-AX_COMPILER_VENDOR
+AC_OUTPUT( \
+ Makefile.srcdir \
+ config.mk \
+ xmlrpc_config.h \
+ )
-# Enable 64 bit build
-AC_ARG_ENABLE(64,
-[AC_HELP_STRING([--enable-64],[build with 64 bit support])],[enable_64="$enable_64"],[enable_64="no"])
-if test "x${ax_cv_c_compiler_vendor}" = "xsun" ; then
- if test "${enable_64}" = "yes"; then
- COMPILER_CFLAGS=-m64
- COMPILER_CXXFLAGS=-m64
- fi
+if test ! -f GNUmakefile; then
+ ln -s "${srcdir}/GNUmakefile" .
+fi
+if test ! -f Makefile; then
+ ln -s "${srcdir}/Makefile" .
fi
-AC_SUBST(COMPILER_CFLAGS)
-AC_SUBST(COMPILER_CXXFLAGS)
-
-dnl =======================================================================
-dnl Libtool
-dnl =======================================================================
-AM_PROG_LIBTOOL
+if test "$MUST_BUILD_WININET_CLIENT $MUST_BUILD_CURL_CLIENT $MUST_BUILD_LIBWWW_CLIENT" = "no no no"; then
+ AC_MSG_NOTICE([\n\n==>We are not building any client XML transport (see earlier messages explaining why), therefore WE WILL NOT BUILD THE CLIENT LIBRARY.])
+fi
-dnl =======================================================================
-dnl Output our results.
-dnl =======================================================================
-AC_OUTPUT(xmlrpc-c-config \
- xmlrpc-c-config.test \
- Makefile.config \
- xmlrpc_config.h \
- lib/expat/Makefile \
- lib/expat/xmlparse/Makefile \
- lib/expat/xmlwf/Makefile \
- lib/expat/sample/Makefile \
- )
-chmod +x xmlrpc-c-config
-chmod +x xmlrpc-c-config.test
Added: freeswitch/trunk/libs/xmlrpc-c/dll-common.make
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/dll-common.make Fri May 23 16:56:24 2008
@@ -0,0 +1,22 @@
+# -*-makefile-*- <-- an Emacs control
+
+# See unix-common.make for an explanation of this file. This file is
+# analogous to unix-common.make, but is for a Windows system
+
+SONAME = $@
+IMPLIB = $(@:%:%.dll.a)
+
+SHLIB_CMD = $(CCLD) $(LDFLAGS_SHLIB) -o $@ $^ $(LADD)
+
+.PHONY: $(SHLIB_INSTALL_TARGETS)
+.PHONY: install-shared-libraries
+
+SHLIB_INSTALL_TARGETS = $(SHARED_LIBS_TO_INSTALL:%=%/install)
+
+#SHLIB_INSTALL_TARGETS is like "libfoo/install libbar/install"
+
+install-shared-libraries: $(SHLIB_INSTALL_TARGETS)
+
+$(SHLIB_INSTALL_TARGETS):lib%/install:$(SHLIB_PREFIX)%.$(SHLIB_SUFFIX).$(MAJ).$(MIN)
+# $< is a library file name, e.g. cygfoo.so.3.1 .
+ $(INSTALL_SHLIB) $< $(DESTDIR)$(LIBINST_DIR)/$<
Modified: freeswitch/trunk/libs/xmlrpc-c/doc/COPYING
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/doc/COPYING (original)
+++ freeswitch/trunk/libs/xmlrpc-c/doc/COPYING Fri May 23 16:56:24 2008
@@ -2,7 +2,7 @@
(and do other things with it which are controlled by copyright law)
under a few simple conditions.
-Each source files describes the copyright license for that particular
+Each source file describes the copyright license for that particular
file. This file summarizes the licenses for your convenience.
All the code written specifically for Xmlrpc-c, which is most
Modified: freeswitch/trunk/libs/xmlrpc-c/doc/HISTORY
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/doc/HISTORY (original)
+++ freeswitch/trunk/libs/xmlrpc-c/doc/HISTORY Fri May 23 16:56:24 2008
@@ -1,5 +1,5 @@
-(There is a detailed release-by-release change history after the
-following overview).
+For a release-by-release change history, see
+<http://xmlrpc-c.sourceforge.net/change.html>.
XML-RPC For C/C++ was created by Eric Kidd in 2000, when XML-RPC was
new and vital. Its development was funded in significant part by
@@ -22,7 +22,7 @@
consequently became rather stable and interest in Xmlrpc-c levelled
off.
-This dark age of Xmlrpc-c lasted until November 2004, when Bryan Henderson
+This dark age of Xmlrpc-c lasted until October 2004, when Bryan Henderson
set out to find an RPC mechanism to use in one of his projects. Bryan
found XML-RPC and then Xmlrpc-c. He decided that the two were almost right
for his needs, but he needed some small extensions.
@@ -59,395 +59,3 @@
each of his releases consisted of a single source code tarball, and
that tarball was not signed. Bryan removed some redundant sources of
information from the package and the web site.
-
-
-DETAILED RELEASE HISTORY:
-
-
-(BJH means Bryan Henderson <bryanh at giraffe-data.com>)
-(SAB means Steven A. Bone <sbone at pobox.com>)
-
-1.03.14 - 06.04.15
-
- *BJH: Fix int/size_t mismatch in xmlrpc_server_abyss.c (manifests on 64
- bit systems).
-
-1.03.13 - 06.04.05
-
- *BJH: Fix build on system with no wchar_t.
-
- *BJH: Abyss XML-RPC server accepts (ignores) parameters after
- "text/xml" in Content-type header from client.
-
-1.03.12 - 06.03.20
-
- *BJH: Fix build of transport_config.h
-
- *BJH: Remove tantalizing but broken RPM spec file.
-
- *BJH: Remove casprintf.o from link of 'xmlrpc', 'xmlrpc_transport', because
- it conflicts with the version in libxmlrpc_client.
-
- *BJH: Change order of libraries in linking 'xml-rpc-api2cpp' to fix
- undefined reference error.
-
-1.03.11 - 06.01.25
-
- *Mike Goddard: in Xmlrpc-c-config, allow libwww-client as synonym
- for client, for backward compatibility.
-
- *Daniel Dlab: Correct INTERNET_FLAG_IGNORE_CERT_DATE_INVALID to
- ERROR_INTERNET_SEC_CERT_DATE_INVALID in Wininet transport.
-
- *BJH: Fix memory leak in C++ client result value - one leak per RPC.
-
- *BJH: Fix memory leak in C++ client - one leak per RPC.
-
- *BJH: Fix signature in xmlrpc_sample_add_server C++ example program.
-
- *BJH: Fix memory leak in xmlrpc_server_abyss_set_handler().
-
- *BJH: Fix memory leak in server method registry -- one leak for each
- RPC.
-
- *BJH: Fix memory leak in wide character constructor functions.
-
-1.03.10 - December 18, 2005
-
- *BJH: Change default minimum on paramList::getDouble() from DBL_MIN
- to -DBL_MAX.
-
-1.03.09 - December 7, 2005
-
- * BJH: Fix size_t/int type mismatch in xmlrpc_server_abyss.c.
-
- * BJH: meerkat-app-list example program: remove NUL character from
- time period parameter.
-
-1.03.08 - November 23, 2005
-
- * BJH: Fix use of uninitialized 'name' member in Abyss ServerCreate().
-
- * BJH: Install client_simple.hpp interface header file.
-
- * BJH: Fix bogus NULL default value for string argument in
- serverAbyss constructor. Use null string instead
-
- * BJH: Remove 'cpptest' from default make.
-
- * Mike West:
- Don't include tools/xmlrpc and tools/xmlrpc_transport
- in the build if client library configured out.
-
-1.03.07 - October 22, 2005
-
- * BJH: Remove curl_global_cleanup() so that multiple simultaneous
- Curl client XML transports per process are essentially
- possible and they don't interfere with other process use of
- Curl.
-
- * BJH: Serialize access to synchronous Curl session in Curl client
- XML transport (to avoid crashes with multiple threads).
-
- * BJH: When installing legacy header symlinks, remove old names first.
-
-1.03.06 - October 6, 2005
-
- * BJH: Fix use of pthread_mutex_t in girmem.hpp so it can be used in
- a Windows program.
-
- * BJH: Don't include xml-rpc-api2cpp in the build with --disable-cpp.
-
- * BJH: Fix bug in tools build, where it tries to link libxml2 instead
- of expat.
-
- * BJH: Add missing xmlrpc_config.h so lib/abyss/src/socket.h will
- compile on Solaris.
-
-1.03.05 - September 24, 2005
-
- * BJH: Change int to long in XMLRPC_STRUCTSIZE to correct 64 bit
- compile error.
-
- * BJH: Add virtual destructor for client to quiet compiler warning.
-
- * BJH: Don't try to build Abyss example programs if Abyss libraries not
- built.
-
- * BJH: Include <sys/filio.h> if it exists (i.e. Solaris).
-
- * BJH: Include <stdlib.h> instead of <malloc.h>, which doesn't exist
- in some environments.
-
-1.03.04 - September 9, 2005
-
- * BJH: Make Abyss work with short writes to sockets. Thanks
- Alistair John Strachan <s0348365 at sms.ed.ac.uk>.
-
- * BJH: Remove unused SSPRINTF definition that won't compile on AIX
- because it has variable arguments.
-
- * BJH: Fix Curl transport bug: arbitrary values for SSL verify options.
-
-1.03.03 - August 4, 2005
-
- * SAB: Fix for Windows what broke between 1.02 and 1.03.
-
- * SAB: Fix incorrect result of xmlrpc_read_string_w() (wrong-size memcpy()).
-
- * BJH: Fix various things that don't compile on AIX.
-
- * BJH: Fix bug: doesn't install libxmlrpc_abyss.
-
- * BJH: Fix missing -l options in xmlrpc-c-config --client
-
-1.03.02 - July 20, 2005
-
- * BJH: Fix for bug in which Abyss doesn't build with either thread or
- fork capability. (Add -D_UNIX and -D_THREAD compile options).
-
-1.03.01 - July 9, 2005
-
- * BJH: Fix for libxml2, no curl builds. make clean cleans test directory
-
-1.03 - June 26, 2005
-
- * BJH: new C++ libraries designed for pure C++ applications
- (Application never sees the underlying C structures or reference
- counts).
-
- * BJH: Make Curl do cookies (session only) and persistent connections.
- This is only for calls through the synchronous interface, and the
- synchronous interface is no longer thread safe -- you can have only
- one thread making calls through it.
-
- * BJH: Add Curl SSL_NO_VERIFYPEER, SSL_NO_VERIFYHOST control.
-
- * BJH: Add User-Agent to Curl transport, Xmlrpc program.
-
- * BJH: libwww transport does not do the weird handling of the "auth"
- cookie. It used to have a global cookie (one cookie shared by all
- servers) called "auth", which it maintained in an environment
- variable.
-
- * BJH: interface header files renamed from xmlrpc_xxx to xmlrpc-c/xxx
- (old names installed a symbolic links for backward compatibility).
-
- * BJH: libxmlrpc_server_abyss: Add ability to set the /RPC2 handler
- without also setting default handler, and to set handlers for files
- other than /RPC2.
-
- * BJH: libxmlrpc_server_abyss: Eliminate global variable for registry
- handle.
-
- * BJH: Abyss: allow user's request handlers to have context
- (Add URIHandler2 type).
-
- * BJH: Add xmlrpc_datetime_new_sec(), xmlrpc_read_datetime_sec().
-
- * BJH: Builds on AIX - new __inline definition, uint32_t instead of uint32,
- et al.
-
- * BJH: Don't build client library if not building any client XML
- transport.
-
- * BJH: Fix bug: xmlrpc_serialize_base64_data() doesn't free working
- storage.
-
- * BJH: Fix mysterious disablement of forking Abyss (ServerRunForked()).
-
- * BJH: Fix bug: 'make install' doesn't install libxmlrpc_xmltok.
-
- * BJH: Renamed CGI stuff, add non-builtin-registry style of CGI server.
-
- * BJH: Break up 'rpctest', rename to 'test'.
-
-1.02 - April 4, 2005
-
- * SAB: Win32 http.sys server: Add new project and sample as
- an alternative to Abyss on current Win32 platforms. Does
- basic authentication and SSL. Requires recent Platform SDK to
- build.
-
- * BJH: Add xmlrpc_int_new(), xmlrpc_read_int(), etc.,
- xmlrpc_decompose_value()
-
- * BJH: Add nil (<nil/>, XMLRPC_TYPE_NIL) capability.
-
- * SAB: WinInet Transport: Add Ignore Invalid SSL certs option.
-
- * BJH: Add 'network_interface' option to Curl transport.
-
- * BJH: Add basic authentication to 'xmlrpc' program.
-
- * BJH: Add 'xmlrpc_transport' tool.
-
- * SAB: Improve use of libCurl in Win32. Add documentation
- and alter some project and configuration files.
-
- * BJH: Add transport-specific options.
-
- * BJH: Use GNUmakefile to catch non-GNU make
-
- * BJH: Fix usage message in xmlrpc-c-config.
-
- * BJH: Curl transport: check for failure of Winsock startup.
-
- * BJH: Fix memory leak in Curl - not freeing curlTransaction.
-
- * SAB: WinInet Transport: Fix bad authentication header.
-
-
-1.01 - January 8, 2005
-
- * SAB: Windows works again; new build strategy.
-
- * BJH: Abyss: Add ConnCreate2() with foreground capability.
-
- * BJH: Abyss: Add ServerRunOnce2() with foreground capability.
-
- * BJH: Abyss: Fix ServerRunOnce().
-
- * BJH: Add xmlrpc_server_abyss().
-
- * BJH: Abyss pthreads is default
-
- * BJH: Clean up client transport multiplexor
-
- * BJH: Separate out server registry stuff into new libxml_server.
-
- * BJH: Examples/Makefile uses new xmlrpc-c-config.test so as to be a
- better example.
-
- * BJH: Fail when structure format specifier does not end in
- "*" instead of just asserting that it does.
-
- * BJH: Fail when structure format specifier is not closed by "}"
- instead of just asserting that it is.
-
- * BJH: Add xmlrpc_array_read_item().
-
-1.00 - October 25, 2004
- * New modular client XML transport structure. Curl and Wininet transports
- (in addition to existing libwww).
- * Bryan Henderson: create Makefile.config; make examples/ directory use
- static make file.
- * Bryan Henderson: replace Makefile.am with already built Makefile.in.
- * Peter Astrand: make it compile with Gcc 3.1.1.
- * Joe Shaw: Can use libxml2 instead of libexpat.
- * Bernhard Herzog: const fixes
- * Stephen Blackheath: ./configure support for building Abyss
- with pthreads.
- * Jeff Dubrule: Removed C++ comments from expat.
- * Patrick Boykin: Facility to copy xmlrpc_server_info structs.
-
-0.9.10 - Eric Kidd <eric.kidd at pobox.com> - 30 June 2001
-
- * Man pages!
- * Debian packages!
-
- * Jeff Stewart: NT CGI fixes.
- * Andy Maloney: Win32 xmlrpc_win32_config.h fixes.
- * Mike Bytnar: Solaris build fixes. Thanks!
-
- * No more 'CVS' directories lurking in the dist tarball.
- * Disabled rpath stuff so we comply with Debian policy.
- * wchar_t code can now be disabled.
- * New interop server.
- * Parts of an interop client.
- * Lots of interop fixes.
- * Other stuff.
-
-0.9.9 - Eric Kidd <eric.kidd at pobox.com> - 03 April 2001
-
- * xml-rpc-api2cpp now generates usable proxy classes.
- * Luke Howard: Default method capability.
- * Abstract XML parser API (but you'll need to edit makefiles to use it).
- * Implemented a configurable size limit for XML data off the network.
-
- * Ability to build and parse XML-RPC values using wchar_t strings.
- * Basic UTF-8 handling: Refuse to process invalid UTF-8 from network,
- print warnings when sending invalid UTF-8 *to* network.
- * Highly robust UTF-8 validator, decoder, encoder.
-
- * Modularized the build system--build only what you need.
- * Integrated Electric Fence into build system (optional).
-
- * Fixed all recent, reproducible bugs in CVS. These were generally
- Windows build bugs.
- * Andy Maloney: Build fixes for Windows.
- * Mike Bytnar: Build fixes for Solaris.
- * RedHat 7 warning fixes.
-
-0.9.8 - Eric Kidd <eric.kidd at pobox.com> - 19 February 2001
-
- * J. Alan Eldridge, Rosimildo daSIlva: Build fixes.
- * Send 'encoding="UTF-8"' in XML prologue.
-
-0.9.7 - Eric Kidd <eric.kidd at pobox.com> - 14 February 2001
-
- * SECURITY: Configurable nesting limits (see advisory 1) to prevent
- denial-of-service attacks and stack overflow.
- * Win32 build fixes from Alex Olugbile.
- * Function name fix from Luke Howard.
-
-0.9.6w - Eric Kidd <eric.kidd at pobox.com> - 02 February 2001
-
- * Merged Win32 VC/C++ changes from Alex and Ian.
- * Merged Win32 Cygwin changes from Rosimildo daSilva
-
-0.9.6 - Eric Kidd <eric.kidd at pobox.com> - 30 January 2001
-
- * Fixed lots of gcc warnings.
- * Added a new 'xmlrpc_server_info' class, which allows you to
- set options on a per-server basis.
- * HTTP Basic authentication.
- * Added internal implementation of system.multicall, lots of brutal test
- cases, and stubs for other system.* commands.
- * Added APIs for accessing CGI and Abyss method registries.
- * Implemented system.listMethods, system.methodHelp, system.methodSignature.
- * Fixed stupid bug in parsing of "(ss*)"-style array descriptions
- where there were no extra elements.
- * Added highly experimental hacked copy of mod_gzip into the
- tools/turbocharger directory. This version does gzip *and* deflate!
- * Added xml-rpc-api2txt, since XML-RPC doesn't have any IDL language.
- * Merged in Ilya Goldberg's libwww/SSL setup code.
-
-0.9.5 - Eric Kidd <eric.kidd at pobox.com> - 20 January 2001
-
- * Bug fix: Make sure CGI-based servers send correct content-length.
-
-0.9.4 - Eric Kidd <eric.kidd at pobox.com> - 18 January 2001
-
- * Services for CGI-based servers.
-
-0.9.3 - Eric Kidd <eric.kidd at pobox.com> - 14 January 2001
-
- * Works with Libwww 5.2.8, even when linked against expat.
- * Added xmlrpc_value_type and XmlRpcValue::getType functions.
- * Miscellaneous API tweaks to discourage writing of incorrect programs.
- Should not affect any correct programs.
-
-0.9.2 - Eric Kidd <eric.kidd at pobox.com> - 12 January 2001
-
- * Improved error messages.
- * Refuse to link against libwww if it was built with expat.
-
-0.9.1 - Eric Kidd <eric.kidd at pobox.com> - 9 January 2001
-
- * Integrated Rick Blair's fix to speed up libwww client.
- * Added informative URLs to Meerkat example programs.
- * Hid the implementation details of xmlrpc_value, just to keep
- people honest. (No more dangerous allocation on the stack!)
- * Minor C++ code cleanup after buying modern C++ books.
- * Documentation improvements.
-
-Some other contributions of unknown date:
-
- Adrian Likins made lots of good, real-world suggestions for improvement.
-
- Ian MacLean made patches from Alex's Windows port.
-
- Brian Quinlan of the Active State company made lots of cool patches,
- including preliminary wchar_t capability.
-
Added: freeswitch/trunk/libs/xmlrpc-c/doc/INSTALL
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/doc/INSTALL Fri May 23 16:56:24 2008
@@ -0,0 +1,148 @@
+These are instructions for building Xmlrpc-c from source and installing
+it on a system.
+
+See the README file for information on prerequisites (things you need to
+have installed before you can build).
+
+
+Essentially, it's just the conventional
+
+ $ ./configure
+ $ make
+ $ make install
+
+To build handy tools such as the 'xmlrpc' command line XML-RPC client:
+
+ $ cd tools
+ $ make
+ $ make install
+
+You can also do
+
+ $ make check
+
+to run a battery of tests before you install. But note that it's as common
+for the tests to fail because the tests are broken as because the product
+is broken, so consider the results carefully.
+
+To see it work, build and run a simple server like this:
+
+ $ cd examples
+ $ make
+ $ ./xmlrpc_sample_add_server 8080
+
+That runs forever, serving clients as they arrive. Now, from another
+shell, run a client that does an RPC to this server:
+
+ $ ./xmlrpc_sample_add_client
+
+Also try other example servers and clients, described in examples/README.
+
+
+You may want to pass a '--prefix' argument to 'configure'. See
+'./configure --help' for details.
+
+You may also want to disable client XML transports that you won't be
+using. In particular, the Libwww transport can be inconvenient, because
+it typically uses about 20 shared libraries. Any XML-RPC client
+program that uses Xmlrpc-c, whether or not the program uses any of the
+libwww facilities, must attach all those libraries, and that can take
+a significant amount of time.
+
+See './configure --help' for the options that disable certain transports.
+
+
+SEPARATE BUILD TREE
+-------------------
+
+While it's traditional to build a Unix package by adding object files
+to the same tree with the source files, it's actually much cleaner to
+keep your source tree exactly as you got it and put the built files in
+a separate directory, called the build tree.
+
+To do this, just create an empty directory and run 'configure' in it,
+then 'make':
+
+ mkdir xmlrpcbuild
+ cd xmlrpcbuild
+ /usr/src/xmlrpc-c/configure
+ ...
+ make
+
+But if you plan to work on Xmlrpc-c source code, you'll probably find
+it more convenient to build the traditional way, with a single tree
+for source and build.
+
+In the source tree, you can type 'make' in any directory to do the
+default make for that directory, or make FILENAME to make the file of
+that name there. In the separate build tree, there are special
+facilities to allow you to do a simple make from the _top level
+directory_, but if you want to make a subcomponent or individual part,
+you have to have a -f option and set SRCDIR and BLDDIR on your 'make'
+command.
+
+
+COMMON PROBLEMS
+---------------
+
+Improper -config files
+----------------------
+
+The most common problem building Xmlrpc-c is one of improperly installed
+prerequisite libraries, namely Libwww and Curl. These libraries are
+designed to be installed along with a -config program (libwww-config
+and curl-config) that tells builders of dependent packages (such as
+Xmlrpc-c) how to use them. When the -config program is wrong, you get
+Xmlrpc-c build failures with messages about undefined references.
+
+The exact nature of the problems with -config programs can be quite
+involved, especially since there is no guarantee that a -config
+program can do what's required of it in every situation. But I'll
+explain the basic problem. For simplicity, I'll talk specifically
+about Curl, but the principles apply to any library that has a -config
+program.
+
+The point of curl-config is to describe how Curl is installed on your
+particular system. You have choices of where to install the various parts
+and what prerequisites to build into them, and curl-config is how you
+communicate those choices to the Xmlrpc-c make files.
+
+Curl's builder automatically creates a curl-config program for you,
+but you should not think of it as part of Curl. It's really a
+configuration file -- something that tells how your particular system
+is put together. The Curl builder is not smart enough to know exactly
+what to put in curl-config; it just builds one that works for most
+people. The local system administrator is actually responsible for
+the contents of curl-config.
+
+One rather complex way in which the curl-config that the Curl builder
+builds can be wrong is that it often indicates that to link to the
+Curl library, you need a "-L /usr/lib" option (or something like that
+-- an option that adds to the linker's search path a directory that is
+already in it). This is usually unnecessary because the directory is
+already in the search path, and often breaks things because it puts
+the directory too early in the search path. If your curl-config says to
+link with -L /usr/lib, you should normally edit it to remove that.
+
+As an example of how -L /usr/lib breaks things, here is a problem that
+is often reported: The user has Xmlrpc-c installed on his system, but
+wants to build a new one to replace it, or to use for a particular
+project instead of the system version. But the build of the new
+version fails with undefined references to symbol "xmlrpc_foo".
+xmlrpc_foo is a new symbol - it was added to Xmlrpc-c in a recent
+release. The version of Xmlrpc-c installed on the system is too old
+to have it. The make file obviously specifies the path to the current
+libraries that the user just built in the link library search order,
+but the link is picking up the old system version instead. Why?
+Because the link options say to search /usr/lib _before_ the local
+build directory. And it does that because curl-config erroneously
+says that you need a -L /usr/lib link option to find the Curl library.
+
+
+WINDOWS
+-------
+
+All of the above is essentially for Unix-type operating systems. To
+build and use Xmlrpc-c on Windows, see the file
+Windows/ReadMeWin32.txt.
+
Modified: freeswitch/trunk/libs/xmlrpc-c/doc/TODO
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/doc/TODO (original)
+++ freeswitch/trunk/libs/xmlrpc-c/doc/TODO Fri May 23 16:56:24 2008
@@ -7,16 +7,8 @@
FUNCTIONAL CHANGES
------------------
-Make xmlrpc_server_abyss() catch a SIGTERM and terminate cleanly.
-
-Make a system.shutdown XML-RPC method to send SIGTERM to its server.
-Don't know what kind of security.
-
-Provide an interface for Abyss servers where the user accepts the TCP
-connection and passes to Xmlrpc-c the open socket. This would be
-useful for inetd servers, among others.
-
-Document the xmlrpc-c/server_abyss.hpp interface.
+Put details in the manual for the xmlrpc-c/server_abyss.hpp interface:
+libxmlrpc_server_abyss++.html.
Implement pluggable XML transports on the server side like on the
client side.
@@ -24,9 +16,6 @@
Create a non-XML non-HTTP efficient transport, client and server.
The tools/binmode-rpc-kit/ directory might be useful. Consider XDR.
-Make clients and servers reentrant (this requires getting or making
-reentrant HTTP libraries).
-
Change the argument order of asynchronous response callbacks to be
more consistent with the xmlrpc_client_call_asynch function. Also
take a look at the server method callback.
@@ -37,9 +26,8 @@
This will break binary and source API compatibility in a very minor
way.
-Make a Perl interface to Xmlrpc-c libraries. This would be better than the
-existing Perl RPC::XML modules because the latter are Perl all the way down
-to the sockets and are thus very slow.
+Expand the Perl interface to Xmlrpc-c libraries to do server functions.
+Maybe match some other features of RPC::XML.
Don't use xmlrpc_value for things that aren't part of an XML-RPC call or
response. It's confusing. In particular, we use an xmlrpc_value
@@ -49,12 +37,16 @@
Don't use XML-RPC fault codes internally. It's confusing. Plus, there's
no need for fault codes at all. Just use the string descriptions.
+Add a function to deregister a method from a method registry.
+
+Add a "registry" type that works via a filesystem directory. There is
+a .so file for each method with its code, and probably a configuration
+file. Make it dynamically updatable.
+
IMPLEMENTATION CHANGES
----------------------
-Replace dynamically created make files with static ones based on GNU make.
-
Use function pointers to access cleanup code in xmlrpc_DECREF?
Or even better: Should we create some kind of class-like system to declare
Added: freeswitch/trunk/libs/xmlrpc-c/dylib-common.make
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/dylib-common.make Fri May 23 16:56:24 2008
@@ -0,0 +1,37 @@
+# -*-makefile-*- <-- an Emacs control
+
+# See unix-common.make for an explanation of this file. This file is
+# analogous to unix-common.make, but is for an Irix system.
+
+SONAME = $(@:%.$(MIN)=%)
+
+SHLIB_CMD = $(CCLD) $(LDFLAGS_SHLIB) -o $@ $^ $(LADD)
+
+SHLIBPP_CMD = $(CXXLD) $(LDFLAGS_SHLIB) -o $@ $^ $(LADD)
+
+SHLIB_LE_TARGETS = $(call shliblefn, $(SHARED_LIBS_TO_BUILD))
+
+$(SHLIB_LE_TARGETS):%.$(SHLIB_SUFFIX):%.$(MAJ).$(MIN).$(SHLIB_SUFFIX)
+ rm -f $@
+ $(LN_S) $< $@
+
+
+.PHONY: $(SHLIB_INSTALL_TARGETS)
+.PHONY: install-shared-libraries
+
+SHLIB_INSTALL_TARGETS = $(SHARED_LIBS_TO_INSTALL:%=%/install)
+
+#SHLIB_INSTALL_TARGETS is like "libfoo/install libbar/install"
+
+install-shared-libraries: $(SHLIB_INSTALL_TARGETS)
+
+$(SHLIB_INSTALL_TARGETS):%/install:%.$(MAJ).$(MIN).$(SHLIB_SUFFIX)
+# $< is a library file name, e.g. libfoo.so.3.1 .
+ $(INSTALL_SHLIB) $< $(DESTDIR)$(LIBINST_DIR)/$<
+ cd $(DESTDIR)$(LIBINST_DIR); \
+ rm -f $(<:%.$(MIN).$(SHLIB_SUFFIX)=%.$(SHLIB_SUFFIX)); \
+ $(LN_S) $< $(<:%.$(MIN).$(SHLIB_SUFFIX)=%.$(SHLIB_SUFFIX))
+ cd $(DESTDIR)$(LIBINST_DIR); \
+ rm -f $(<:%.$(MAJ).$(MIN).$(SHLIB_SUFFIX)=%.$(SHLIB_SUFFIX)); \
+ $(LN_S) $(<:%.$(MIN).$(SHLIB_SUFFIX)=%.$(SHLIB_SUFFIX)) \
+ $(<:%.$(MAJ).$(MIN).$(SHLIB_SUFFIX)=%.$(SHLIB_SUFFIX))
Modified: freeswitch/trunk/libs/xmlrpc-c/examples/Makefile
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/examples/Makefile (original)
+++ freeswitch/trunk/libs/xmlrpc-c/examples/Makefile Fri May 23 16:56:24 2008
@@ -5,14 +5,15 @@
# these programs depend.
-ifeq ($(SRCDIR)x,x)
+ifeq ($(SRCDIR),)
SRCDIR = $(CURDIR)/..
-BUILDDIR = $(SRCDIR)
+BLDDIR = $(SRCDIR)
endif
+SUBDIR = examples
-default: all
+include $(BLDDIR)/config.mk
-include $(BUILDDIR)/Makefile.config
+default: all
CFLAGS = $(CFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD)
LDFLAGS = $(LADD)
@@ -20,19 +21,25 @@
# If this were a real application, working from an installed copy of
# Xmlrpc-c, XMLRPC_C_CONFIG would just be 'xmlrpc-c-config'. It would be
# found in the user's PATH.
-XMLRPC_C_CONFIG = $(BUILDDIR)/xmlrpc-c-config.test
+XMLRPC_C_CONFIG = $(BLDDIR)/xmlrpc-c-config.test
CLIENTPROGS = \
auth_client \
- query-meerkat \
synch_client \
xmlrpc_sample_add_client \
xmlrpc_asynch_client \
+ifeq ($(MUST_BUILD_CURL_CLIENT),yes)
+ CLIENTPROGS += interrupted_client
+endif
+
SERVERPROGS_CGI = \
xmlrpc_sample_add_server.cgi
SERVERPROGS_ABYSS = \
+ interrupted_server \
+ xmlrpc_inetd_server \
+ xmlrpc_socket_server \
xmlrpc_loop_server \
xmlrpc_sample_add_server \
xmlrpc_server_validatee \
@@ -54,7 +61,7 @@
PROGS += $(SERVERPROGS_CGI)
endif
-INCLUDES = $(shell $(XMLRPC_C_CONFIG) client abyss-server --cflags)
+INCLUDES = -I. $(shell $(XMLRPC_C_CONFIG) client abyss-server --cflags)
LDADD_CLIENT = \
$(shell $(XMLRPC_C_CONFIG) client --ldadd)
@@ -75,8 +82,12 @@
endif
.PHONY: cpp/all
-cpp/all:
- $(MAKE) -C $(dir $@) $(notdir $@)
+cpp/all: $(BLDDIR)/examples/cpp
+ $(MAKE) -C cpp -f $(SRCDIR)/examples/cpp/Makefile all
+
+# When building in separate tree, directory won't exist yet
+$(BLDDIR)/examples/cpp:
+ mkdir $@
$(CLIENTPROGS):%:%.o
$(CCLD) -o $@ $(LDFLAGS) $^ $(LDADD_CLIENT)
@@ -90,17 +101,25 @@
gen_sample_add_xml:%:%.o
$(CCLD) -o $@ $(LDFLAGS) $^ $(LDADD_BASE)
-%.o:%.c
+OBJECTS = $(patsubst %,%.o,$(patsubst %.cgi,%_cgi,$(PROGS)))
+
+$(OBJECTS):%.o:%.c
$(CC) -c $(INCLUDES) $(CFLAGS) $<
-*.c: config.h xmlrpc_amconfig.h
+# config.h and xmlrpc_amconfig.h just describe the build environment.
+# We use them so that the example programs will build in users'
+# various environments. If you're copying these examples, you can
+# just remove these headers from the programs and hardcode whatever is
+# right for your build environment.
+
+$(OBJECTS): config.h xmlrpc_amconfig.h
config.h:
- $(LN_S) $(BUILDDIR)/xmlrpc_config.h $@
+ $(LN_S) $(BLDDIR)/xmlrpc_config.h $@
xmlrpc_amconfig.h:
- $(LN_S) $(BUILDDIR)/$@ .
+ $(LN_S) $(BLDDIR)/$@ .
-include $(SRCDIR)/Makefile.common
+include $(SRCDIR)/common.mk
.PHONY: clean
clean: clean-common
Modified: freeswitch/trunk/libs/xmlrpc-c/examples/auth_client.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/examples/auth_client.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/examples/auth_client.c Fri May 23 16:56:24 2008
@@ -20,22 +20,26 @@
#define VERSION "1.0"
#define SERVER_URL "http://localhost:8080/RPC2"
-static void die_if_fault_occurred (xmlrpc_env *env)
-{
- if (env->fault_occurred) {
+
+
+static void
+die_if_fault_occurred(xmlrpc_env * const envP) {
+ if (envP->fault_occurred) {
fprintf(stderr, "XML-RPC Fault: %s (%d)\n",
- env->fault_string, env->fault_code);
+ envP->fault_string, envP->fault_code);
exit(1);
}
}
+
+
int
main(int const argc,
const char ** const argv ATTR_UNUSED) {
xmlrpc_env env;
- xmlrpc_server_info * server;
- xmlrpc_value * result;
+ xmlrpc_server_info * serverP;
+ xmlrpc_value * resultP;
xmlrpc_int sum;
if (argc-1 > 0) {
@@ -48,29 +52,29 @@
xmlrpc_env_init(&env);
/* Make a new object to represent our XML-RPC server. */
- server = xmlrpc_server_info_new(&env, SERVER_URL);
+ serverP = xmlrpc_server_info_new(&env, SERVER_URL);
die_if_fault_occurred(&env);
/* Set up our authentication information. */
- xmlrpc_server_info_set_basic_auth(&env, server, "jrandom", "secret");
+ xmlrpc_server_info_set_basic_auth(&env, serverP, "jrandom", "secret");
die_if_fault_occurred(&env);
- result =
+ resultP =
xmlrpc_client_call_server(
- &env, server, "sample.add", "(ii)",
+ &env, serverP, "sample.add", "(ii)",
(xmlrpc_int32) 5, (xmlrpc_int32) 7);
die_if_fault_occurred(&env);
/* Dispose of our server object. */
- xmlrpc_server_info_free(server);
+ xmlrpc_server_info_free(serverP);
/* Get the authentication information and print it out. */
- xmlrpc_read_int(&env, result, &sum);
+ xmlrpc_read_int(&env, resultP, &sum);
die_if_fault_occurred(&env);
- printf("The sum is %d\n", sum);
+ printf("The sum is %d\n", sum);
/* Dispose of our result value. */
- xmlrpc_DECREF(result);
+ xmlrpc_DECREF(resultP);
/* Shut down our XML-RPC client library. */
xmlrpc_env_clean(&env);
Modified: freeswitch/trunk/libs/xmlrpc-c/examples/cpp/Makefile
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/examples/cpp/Makefile (original)
+++ freeswitch/trunk/libs/xmlrpc-c/examples/cpp/Makefile Fri May 23 16:56:24 2008
@@ -5,14 +5,15 @@
# these programs depend.
-ifeq ($(SRCDIR)x,x)
+ifeq ($(SRCDIR),)
SRCDIR = $(CURDIR)/../..
-BUILDDIR = $(SRCDIR)
+BLDDIR = $(SRCDIR)
endif
+SUBDIR=examples/cpp
-default: all
+include $(BLDDIR)/config.mk
-include $(BUILDDIR)/Makefile.config
+default: all
CXXFLAGS = $(CXXFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD)
LDFLAGS = $(LADD)
@@ -20,18 +21,18 @@
# If this were a real application, working from an installed copy of
# Xmlrpc-c, XMLRPC_C_CONFIG would just be 'xmlrpc-c-config'. It would be
# found in the user's PATH.
-XMLRPC_C_CONFIG = $(BUILDDIR)/xmlrpc-c-config.test
+XMLRPC_C_CONFIG = $(BLDDIR)/xmlrpc-c-config.test
SERVERPROGS_ABYSS = \
+ xmlrpc_inetd_server \
+ xmlrpc_loop_server \
xmlrpc_sample_add_server \
-LEGACY_CLIENTPROGS = \
- meerkat-app-list
-
CLIENTPROGS = \
xmlrpc_sample_add_client \
sample_add_client_complex \
+ asynch_client \
# Build up PROGS:
PROGS =
@@ -41,10 +42,16 @@
endif
ifeq ($(MUST_BUILD_CLIENT),yes)
- PROGS += $(CLIENTPROGS) $(LEGACY_CLIENTPROGS)
+ PROGS += $(CLIENTPROGS)
endif
-INCLUDES = $(shell $(XMLRPC_C_CONFIG) c++2 client abyss-server --cflags)
+PROGS += pstream_inetd_server
+
+ifeq ($(MUST_BUILD_CLIENT),yes)
+ PROGS += pstream_client
+endif
+
+INCLUDES = -I. $(shell $(XMLRPC_C_CONFIG) c++2 client abyss-server --cflags)
LDADD_SERVER_ABYSS = \
$(shell $(XMLRPC_C_CONFIG) c++2 abyss-server --ldadd)
@@ -55,31 +62,42 @@
LDADD_BASE = \
$(shell $(XMLRPC_C_CONFIG) c++2 --ldadd)
-LDADD_LEGACY_CLIENT = \
- $(shell $(XMLRPC_C_CONFIG) c++ client --ldadd)
-
all: $(PROGS)
$(SERVERPROGS_ABYSS):%:%.o
$(CXXLD) -o $@ $(LDFLAGS) $^ $(LDADD_SERVER_ABYSS)
-$(LEGACY_CLIENTPROGS):%:%.o
- $(CXXLD) -o $@ $(LDFLAGS) $^ $(LDADD_LEGACY_CLIENT)
-
$(CLIENTPROGS):%:%.o
$(CXXLD) -o $@ $(LDFLAGS) $^ $(LDADD_CLIENT)
-%.o:%.cpp
+
+LDADD_PSTREAM_CLIENT = \
+ $(shell $(XMLRPC_C_CONFIG) c++2 client --ldadd)
+
+pstream_client:%:%.o
+ $(CXXLD) -o $@ $(LDFLAGS) $^ $(LDADD_PSTREAM_CLIENT)
+
+LDADD_PSTREAM_SERVER = \
+ $(shell $(XMLRPC_C_CONFIG) c++2 pstream-server --ldadd)
+
+pstream_inetd_server:%:%.o
+ $(CXXLD) -o $@ $(LDFLAGS) $^ $(LDADD_PSTREAM_SERVER)
+
+OBJECTS = $(PROGS:%=%.o)
+
+$(OBJECTS):%.o:%.cpp
$(CXX) -c $(INCLUDES) $(CXXFLAGS) $<
-*.c: config.h xmlrpc_amconfig.h
+# See example/Makefile for an explanation of config.h and xmlrpc_amconfig.h
+
+$(OBJECTS): config.h xmlrpc_amconfig.h
config.h:
- $(LN_S) $(BUILDDIR)/xmlrpc_config.h $@
+ $(LN_S) $(BLDDIR)/xmlrpc_config.h $@
xmlrpc_amconfig.h:
- $(LN_S) $(BUILDDIR)/$@ .
+ $(LN_S) $(BLDDIR)/$@ .
-include $(SRCDIR)/Makefile.common
+include $(SRCDIR)/common.mk
.PHONY: clean
clean: clean-common
Added: freeswitch/trunk/libs/xmlrpc-c/examples/cpp/asynch_client.cpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/examples/cpp/asynch_client.cpp Fri May 23 16:56:24 2008
@@ -0,0 +1,75 @@
+/*=============================================================================
+ asynch_client.cpp
+===============================================================================
+ This is an example of an XML-RPC client that uses XML-RPC for C/C++
+ (Xmlrpc-c).
+
+ In particular, it does multiple RPCs asynchronously, running
+ simultaneously.
+=============================================================================*/
+
+#include <cassert>
+#include <cstdlib>
+#include <string>
+#include <iostream>
+#include <xmlrpc-c/girerr.hpp>
+#include <xmlrpc-c/base.hpp>
+#include <xmlrpc-c/client.hpp>
+
+using namespace std;
+
+int
+main(int argc, char **) {
+
+ if (argc-1 > 0) {
+ cerr << "This program has no arguments" << endl;
+ exit(1);
+ }
+
+ try {
+ xmlrpc_c::clientXmlTransport_curl myTransport;
+
+ xmlrpc_c::client_xml myClient(&myTransport);
+
+ string const methodName("sample.add");
+
+ xmlrpc_c::paramList sampleAddParms1;
+ sampleAddParms1.add(xmlrpc_c::value_int(3));
+ sampleAddParms1.add(xmlrpc_c::value_int(1));
+
+ xmlrpc_c::rpcPtr rpc1P(methodName, sampleAddParms1);
+
+ xmlrpc_c::paramList sampleAddParms2;
+ sampleAddParms2.add(xmlrpc_c::value_int(5));
+ sampleAddParms2.add(xmlrpc_c::value_int(7));
+
+ xmlrpc_c::rpcPtr rpc2P(methodName, sampleAddParms2);
+
+ string const serverUrl("http://localhost:8080/RPC2");
+
+ xmlrpc_c::carriageParm_curl0 myCarriageParm(serverUrl);
+
+ rpc1P->start(&myClient, &myCarriageParm);
+ rpc2P->start(&myClient, &myCarriageParm);
+
+ cout << "Two RPCs started. Waiting for them to finish." << endl;
+
+ myClient.finishAsync(xmlrpc_c::timeout()); // infinite timeout
+
+ assert(rpc1P->isFinished());
+ assert(rpc2P->isFinished());
+
+ int const sum1(xmlrpc_c::value_int(rpc1P->getResult()));
+ int const sum2(xmlrpc_c::value_int(rpc2P->getResult()));
+
+ cout << "Result of RPC 1 (sum of 3 and 1): " << sum1 << endl;
+ cout << "Result of RPC 2 (sum of 5 and 7): " << sum2 << endl;
+
+ } catch (exception const& e) {
+ cerr << "Client threw error: " << e.what() << endl;
+ } catch (...) {
+ cerr << "Client threw unexpected error." << endl;
+ }
+
+ return 0;
+}
Added: freeswitch/trunk/libs/xmlrpc-c/examples/cpp/pstream_client.cpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/examples/cpp/pstream_client.cpp Fri May 23 16:56:24 2008
@@ -0,0 +1,84 @@
+/*=============================================================================
+ pstream_client.cpp
+===============================================================================
+ This is an example of a client that uses XML-RPC for C/C++
+ (Xmlrpc-c).
+
+ In particular, it uses the simple "packet stream" XML transport mechanism
+ instead of HTTP as specified by XML-RPC (so this is not an XML-RPC
+ client).
+
+ You have to supply as Standard Input a stream (TCP) socket whose other
+ end is hooked up to the RPC server. The 'socket_exec' program is a
+ good way to arrange that.
+
+ The sample program pstream_server.cpp is compatible with this client.
+
+ Example:
+
+ $ socketexec -connect -remote_host=localhost -remote_port=8080 \
+ ./pstream_client
+=============================================================================*/
+
+#include <cassert>
+#include <cstdlib>
+#include <string>
+#include <iostream>
+#include <unistd.h>
+#include <sys/signal.h>
+#include <xmlrpc-c/girerr.hpp>
+#include <xmlrpc-c/base.hpp>
+#include <xmlrpc-c/client.hpp>
+#include <xmlrpc-c/client_transport.hpp>
+
+
+using namespace std;
+
+int
+main(int argc, char **) {
+
+ if (argc-1 > 0) {
+ cerr << "This program has no arguments" << endl;
+ exit(1);
+ }
+
+ // It's a good idea to disable SIGPIPE signals; if server closes his end
+ // of the pipe/socket, we'd rather see a failure to send a call than
+ // get killed by the OS.
+ signal(SIGPIPE, SIG_IGN);
+
+ try {
+ xmlrpc_c::clientXmlTransport_pstream myTransport(
+ xmlrpc_c::clientXmlTransport_pstream::constrOpt()
+ .fd(STDIN_FILENO));
+
+ xmlrpc_c::client_xml myClient(&myTransport);
+
+ string const methodName("sample.add");
+
+ xmlrpc_c::paramList sampleAddParms;
+ sampleAddParms.add(xmlrpc_c::value_int(5));
+ sampleAddParms.add(xmlrpc_c::value_int(7));
+
+ xmlrpc_c::rpcPtr myRpcP(methodName, sampleAddParms);
+
+ xmlrpc_c::carriageParm_pstream myCarriageParm;
+ // Empty; transport doesn't need any information
+
+ myRpcP->call(&myClient, &myCarriageParm);
+
+ assert(myRpcP->isFinished());
+
+ int const sum(xmlrpc_c::value_int(myRpcP->getResult()));
+ // Assume the method returned an integer; throws error if not
+
+ cout << "Result of RPC (sum of 5 and 7): " << sum << endl;
+
+ } catch (exception const& e) {
+ cerr << "Client threw error: " << e.what() << endl;
+ } catch (...) {
+ cerr << "Client threw unexpected error." << endl;
+ }
+
+ return 0;
+}
Added: freeswitch/trunk/libs/xmlrpc-c/examples/cpp/pstream_inetd_server.cpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/examples/cpp/pstream_inetd_server.cpp Fri May 23 16:56:24 2008
@@ -0,0 +1,90 @@
+/* A simple standalone RPC server based on an Xmlrpc-c packet socket.
+
+ This program expects the invoker to provide an established connection
+ to a client as Standard Input (E.g. Inetd can do this). It processes
+ RPCs from that connection until the client closes the connection.
+
+ This is not an XML-RPC server, because it uses a simple packet socket
+ instead of HTTP. See xmlrpc_sample_add_server.cpp for an example of
+ an XML-RPC server.
+
+ The advantage of this example over XML-RPC is that it has a connection
+ concept. The client can be connected indefinitely and the server gets
+ notified when the client terminates, even if it gets aborted by its OS.
+
+ Here's an example of running this:
+
+ $ socketexec -accept -local_port=8080 ./pstream_inetd_server
+*/
+
+#ifndef WIN32
+#include <unistd.h>
+#endif
+#include <cassert>
+#include <iostream>
+#include <sys/signal.h>
+
+#include <xmlrpc-c/base.hpp>
+#include <xmlrpc-c/registry.hpp>
+#include <xmlrpc-c/server_pstream.hpp>
+
+using namespace std;
+
+
+class sampleAddMethod : public xmlrpc_c::method {
+public:
+ sampleAddMethod() {
+ // signature and help strings are documentation -- the client
+ // can query this information with a system.methodSignature and
+ // system.methodHelp RPC.
+ this->_signature = "i:ii"; // method's arguments are two integers
+ this->_help = "This method adds two integers together";
+ }
+ void
+ execute(xmlrpc_c::paramList const& paramList,
+ xmlrpc_c::value * const retvalP) {
+
+ int const addend(paramList.getInt(0));
+ int const adder(paramList.getInt(1));
+
+ paramList.verifyEnd(2);
+
+ *retvalP = xmlrpc_c::value_int(addend + adder);
+ }
+};
+
+
+
+int
+main(int const,
+ const char ** const) {
+
+ // It's a good idea to disable SIGPIPE signals; if client closes his end
+ // of the pipe/socket, we'd rather see a failure to send a response than
+ // get killed by the OS.
+ signal(SIGPIPE, SIG_IGN);
+
+ try {
+ xmlrpc_c::registry myRegistry;
+
+ xmlrpc_c::methodPtr const sampleAddMethodP(new sampleAddMethod);
+
+ myRegistry.addMethod("sample.add", sampleAddMethodP);
+
+ xmlrpc_c::serverPstreamConn server(
+ xmlrpc_c::serverPstreamConn::constrOpt()
+ .socketFd(STDIN_FILENO)
+ .registryP(&myRegistry));
+
+ for (bool clientHasDisconnected = false; !clientHasDisconnected;)
+ server.runOnce(&clientHasDisconnected);
+ // This reads one packet (containing an XML-RPC call message)
+ // from Standard Input, executes the indicated RPC, and writes
+ // one packet containing the XML-RPC response message to
+ // Standard Input.
+
+ } catch (exception const& e) {
+ cerr << "Something threw an error: " << e.what() << endl;
+ }
+ return 0;
+}
Modified: freeswitch/trunk/libs/xmlrpc-c/examples/cpp/sample_add_client_complex.cpp
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/examples/cpp/sample_add_client_complex.cpp (original)
+++ freeswitch/trunk/libs/xmlrpc-c/examples/cpp/sample_add_client_complex.cpp Fri May 23 16:56:24 2008
@@ -14,12 +14,13 @@
facility. It is for demonstration purposes.
=============================================================================*/
+#include <cassert>
+#include <cstdlib>
#include <string>
#include <iostream>
#include <xmlrpc-c/girerr.hpp>
#include <xmlrpc-c/base.hpp>
#include <xmlrpc-c/client.hpp>
-#include <cassert>
using namespace std;
@@ -32,7 +33,11 @@
}
try {
- xmlrpc_c::clientXmlTransport_curl myTransport;
+ xmlrpc_c::clientXmlTransport_curl myTransport(
+ xmlrpc_c::clientXmlTransport_curl::constrOpt()
+ .no_ssl_verifyhost(true)
+ .user_agent("sample_add/1.0"));
+
xmlrpc_c::client_xml myClient(&myTransport);
string const methodName("sample.add");
@@ -47,8 +52,6 @@
xmlrpc_c::carriageParm_curl0 myCarriageParm(serverUrl);
- xmlrpc_c::value result;
-
myRpcP->call(&myClient, &myCarriageParm);
assert(myRpcP->isFinished());
@@ -58,8 +61,8 @@
cout << "Result of RPC (sum of 5 and 7): " << sum << endl;
- } catch (girerr::error const error) {
- cerr << "Client threw error: " << error.what() << endl;
+ } catch (exception const& e) {
+ cerr << "Client threw error: " << e.what() << endl;
} catch (...) {
cerr << "Client threw unexpected error." << endl;
}
Added: freeswitch/trunk/libs/xmlrpc-c/examples/cpp/xmlrpc_inetd_server.cpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/examples/cpp/xmlrpc_inetd_server.cpp Fri May 23 16:56:24 2008
@@ -0,0 +1,62 @@
+/* A simple XML-RPC server that runs under Inetd. I.e. it lets the invoking
+ program handle all the connection switching and simply processes one
+ RPC on the provided connection (Standard Input) and exits.
+*/
+
+#ifndef WIN32
+#include <unistd.h>
+#endif
+#include <cassert>
+
+#include <xmlrpc-c/base.hpp>
+#include <xmlrpc-c/registry.hpp>
+#include <xmlrpc-c/server_abyss.hpp>
+
+using namespace std;
+
+class sampleAddMethod : public xmlrpc_c::method {
+public:
+ sampleAddMethod() {
+ // signature and help strings are documentation -- the client
+ // can query this information with a system.methodSignature and
+ // system.methodHelp RPC.
+ this->_signature = "i:ii"; // method's arguments are two integers
+ this->_help = "This method adds two integers together";
+ }
+ void
+ execute(xmlrpc_c::paramList const& paramList,
+ xmlrpc_c::value * const retvalP) {
+
+ int const addend(paramList.getInt(0));
+ int const adder(paramList.getInt(1));
+
+ paramList.verifyEnd(2);
+
+ *retvalP = xmlrpc_c::value_int(addend + adder);
+ }
+};
+
+
+
+int
+main(int const,
+ const char ** const) {
+
+ xmlrpc_c::registry myRegistry;
+
+ xmlrpc_c::methodPtr const sampleAddMethodP(new sampleAddMethod);
+
+ myRegistry.addMethod("sample.add", sampleAddMethodP);
+
+ xmlrpc_c::serverAbyss myAbyssServer(
+ myRegistry,
+ 8080, // TCP port on which to listen
+ "/tmp/xmlrpc_log" // Log file
+ );
+
+ myAbyssServer.runConn(STDIN_FILENO);
+ /* This reads the HTTP POST request from Standard Input and
+ executes the indicated RPC.
+ */
+ return 0;
+}
Added: freeswitch/trunk/libs/xmlrpc-c/examples/cpp/xmlrpc_loop_server.cpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/examples/cpp/xmlrpc_loop_server.cpp Fri May 23 16:56:24 2008
@@ -0,0 +1,72 @@
+/* A simple standalone XML-RPC server based on Abyss that contains a
+ simple one-thread request processing loop.
+
+ xmlrpc_sample_add_server.cpp is a server that does the same thing, but
+ does it by running a full Abyss daemon in the background, so it has
+ less control over how the requests are served.
+*/
+
+#include <cassert>
+#include <iostream>
+
+#include <xmlrpc-c/base.hpp>
+#include <xmlrpc-c/registry.hpp>
+#include <xmlrpc-c/server_abyss.hpp>
+
+using namespace std;
+
+class sampleAddMethod : public xmlrpc_c::method {
+public:
+ sampleAddMethod() {
+ // signature and help strings are documentation -- the client
+ // can query this information with a system.methodSignature and
+ // system.methodHelp RPC.
+ this->_signature = "i:ii"; // method's arguments, result are integers
+ this->_help = "This method adds two integers together";
+ }
+ void
+ execute(xmlrpc_c::paramList const& paramList,
+ xmlrpc_c::value * const retvalP) {
+
+ int const addend(paramList.getInt(0));
+ int const adder(paramList.getInt(1));
+
+ paramList.verifyEnd(2);
+
+ *retvalP = xmlrpc_c::value_int(addend + adder);
+ }
+};
+
+
+
+int
+main(int const,
+ const char ** const) {
+
+ try {
+ xmlrpc_c::registry myRegistry;
+
+ xmlrpc_c::methodPtr const sampleAddMethodP(new sampleAddMethod);
+
+ myRegistry.addMethod("sample.add", sampleAddMethodP);
+
+ xmlrpc_c::serverAbyss myAbyssServer(
+ xmlrpc_c::serverAbyss::constrOpt()
+ .registryP(&myRegistry)
+ .portNumber(8080)
+ .logFileName("/tmp/xmlrpc_log"));
+
+ while (true) {
+ cout << "Waiting for next RPC..." << endl;
+
+ myAbyssServer.runOnce();
+ /* This waits for the next connection, accepts it, reads the
+ HTTP POST request, executes the indicated RPC, and closes
+ the connection.
+ */
+ }
+ } catch (exception const& e) {
+ cerr << "Something failed. " << e.what() << endl;
+ }
+ return 0;
+}
Modified: freeswitch/trunk/libs/xmlrpc-c/examples/cpp/xmlrpc_sample_add_client.cpp
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/examples/cpp/xmlrpc_sample_add_client.cpp (original)
+++ freeswitch/trunk/libs/xmlrpc-c/examples/cpp/xmlrpc_sample_add_client.cpp Fri May 23 16:56:24 2008
@@ -1,3 +1,4 @@
+#include <cstdlib>
#include <string>
#include <iostream>
#include <xmlrpc-c/girerr.hpp>
@@ -28,8 +29,8 @@
cout << "Result of RPC (sum of 5 and 7): " << sum << endl;
- } catch (girerr::error const error) {
- cerr << "Client threw error: " << error.what() << endl;
+ } catch (exception const& e) {
+ cerr << "Client threw error: " << e.what() << endl;
} catch (...) {
cerr << "Client threw unexpected error." << endl;
}
Modified: freeswitch/trunk/libs/xmlrpc-c/examples/cpp/xmlrpc_sample_add_server.cpp
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/examples/cpp/xmlrpc_sample_add_server.cpp (original)
+++ freeswitch/trunk/libs/xmlrpc-c/examples/cpp/xmlrpc_sample_add_server.cpp Fri May 23 16:56:24 2008
@@ -1,4 +1,11 @@
#include <cassert>
+#include <stdexcept>
+#include <iostream>
+#ifdef WIN32
+# include <windows.h>
+#else
+# include <unistd.h>
+#endif
#include <xmlrpc-c/base.hpp>
#include <xmlrpc-c/registry.hpp>
@@ -6,6 +13,13 @@
using namespace std;
+#ifdef WIN32
+ #define SLEEP(seconds) SleepEx(seconds * 1000);
+#else
+ #define SLEEP(seconds) sleep(seconds);
+#endif
+
+
class sampleAddMethod : public xmlrpc_c::method {
public:
sampleAddMethod() {
@@ -26,6 +40,11 @@
paramList.verifyEnd(2);
*retvalP = xmlrpc_c::value_int(addend + adder);
+
+ // Sometimes, make it look hard (so client can see what it's like
+ // to do an RPC that takes a while).
+ if (adder == 1)
+ SLEEP(2);
}
};
@@ -35,21 +54,24 @@
main(int const,
const char ** const) {
- xmlrpc_c::registry myRegistry;
-
- xmlrpc_c::methodPtr const sampleAddMethodP(new sampleAddMethod);
-
- myRegistry.addMethod("sample.add", sampleAddMethodP);
+ try {
+ xmlrpc_c::registry myRegistry;
- xmlrpc_c::serverAbyss myAbyssServer(
- myRegistry,
- 8080, // TCP port on which to listen
- "/tmp/xmlrpc_log" // Log file
- );
-
- myAbyssServer.run();
- // xmlrpc_c::serverAbyss.run() never returns
- assert(false);
+ xmlrpc_c::methodPtr const sampleAddMethodP(new sampleAddMethod);
+ myRegistry.addMethod("sample.add", sampleAddMethodP);
+
+ xmlrpc_c::serverAbyss myAbyssServer(
+ myRegistry,
+ 8080, // TCP port on which to listen
+ "/tmp/xmlrpc_log" // Log file
+ );
+
+ myAbyssServer.run();
+ // xmlrpc_c::serverAbyss.run() never returns
+ assert(false);
+ } catch (exception const& e) {
+ cerr << "Something failed. " << e.what() << endl;
+ }
return 0;
}
Modified: freeswitch/trunk/libs/xmlrpc-c/examples/gen_sample_add_xml.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/examples/gen_sample_add_xml.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/examples/gen_sample_add_xml.c Fri May 23 16:56:24 2008
@@ -16,10 +16,10 @@
#include "config.h"
static void
-die_if_fault_occurred (xmlrpc_env *env) {
- if (env->fault_occurred) {
+die_if_fault_occurred(xmlrpc_env * const envP) {
+ if (envP->fault_occurred) {
fprintf(stderr, "XML-RPC Fault: %s (%d)\n",
- env->fault_string, env->fault_code);
+ envP->fault_string, envP->fault_code);
exit(1);
}
}
Added: freeswitch/trunk/libs/xmlrpc-c/examples/interrupted_client.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/examples/interrupted_client.c Fri May 23 16:56:24 2008
@@ -0,0 +1,164 @@
+/* Same as xmlrpc_sample_add_client.c, except the call is interruptible,
+ both by timeout and by control-C.
+*/
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <signal.h>
+
+#include <xmlrpc-c/base.h>
+#include <xmlrpc-c/client.h>
+
+#include "config.h" /* information about this build environment */
+
+static int interrupt;
+ /* This is a flag telling libxmlrpc_client to abort whatever it's
+ doing. It's global because we set it with a signal handler.
+ */
+
+static void
+die_if_fault_occurred (xmlrpc_env * const envP) {
+ if (envP->fault_occurred) {
+ fprintf(stderr, "XML-RPC Fault: %s (%d)\n",
+ envP->fault_string, envP->fault_code);
+ exit(1);
+ }
+}
+
+
+
+static void
+interruptRpc(int const signalClass) {
+
+ switch (signalClass) {
+ case SIGINT:
+ printf("SIGINT signal received.\n");
+ break;
+ case SIGALRM:
+ printf("SIGALRM signal received.\n");
+ break;
+ default:
+ printf("Internal error: signal of class %u caught even though "
+ "we didn't set up a handler for that class\n", signalClass);
+ };
+
+ interrupt = 1;
+}
+
+
+
+static void
+setupSignalHandlers(void) {
+
+ struct sigaction mysigaction;
+
+ sigemptyset(&mysigaction.sa_mask);
+ mysigaction.sa_flags = 0;
+
+ /* Usually, this signal indicates the user pressed Ctl-C */
+ mysigaction.sa_handler = interruptRpc;
+ sigaction(SIGINT, &mysigaction, NULL);
+ /* This signal indicates a timed alarm you requested happened */
+ sigaction(SIGALRM, &mysigaction, NULL);
+}
+
+
+
+static void
+addInterruptibly(xmlrpc_client * const clientP,
+ const char * const serverUrl,
+ int const addend,
+ int const adder) {
+
+ const char * const methodName = "sample.add";
+
+ xmlrpc_env env;
+ xmlrpc_value * resultP;
+ xmlrpc_int32 sum;
+
+ xmlrpc_env_init(&env);
+
+ printf("Making XMLRPC call to server url '%s' method '%s' "
+ "to request the sum "
+ "of %d and %d...\n", serverUrl, methodName, addend, adder);
+
+ interrupt = 0; /* Global variable */
+
+ alarm(2); /* Interrupt the call if it hasn't finished 2 seconds from now */
+
+ /* Make the remote procedure call */
+
+ xmlrpc_client_call2f(&env, clientP, serverUrl, methodName, &resultP,
+ "(ii)", (xmlrpc_int32) addend, (xmlrpc_int32) adder);
+ die_if_fault_occurred(&env);
+
+ alarm(0); /* Cancel alarm, if it hasn't happened yet */
+
+ /* Get our sum and print it out. */
+ xmlrpc_read_int(&env, resultP, &sum);
+ die_if_fault_occurred(&env);
+ printf("The sum is %d\n", sum);
+
+ /* Dispose of our result value. */
+ xmlrpc_DECREF(resultP);
+
+ xmlrpc_env_clean(&env);
+}
+
+
+
+int
+main(int const argc,
+ const char ** const argv ATTR_UNUSED) {
+
+ const char * const serverUrl = "http://localhost:8080/RPC2";
+
+ xmlrpc_env env;
+ struct xmlrpc_clientparms clientParms;
+ xmlrpc_client * clientP;
+
+ if (argc-1 > 0) {
+ fprintf(stderr, "This program has no arguments\n");
+ exit(1);
+ }
+
+ setupSignalHandlers();
+
+ /* Initialize our error-handling environment. */
+ xmlrpc_env_init(&env);
+
+ /* Required before any use of Xmlrpc-c client library: */
+ xmlrpc_client_setup_global_const(&env);
+ die_if_fault_occurred(&env);
+
+ clientParms.transport = "curl";
+
+ /* Create a client object */
+ xmlrpc_client_create(&env, 0, NULL, NULL,
+ &clientParms, XMLRPC_CPSIZE(transport),
+ &clientP);
+
+ die_if_fault_occurred(&env);
+
+ xmlrpc_client_set_interrupt(clientP, &interrupt);
+
+ /* If our server is running 'xmlrpc_sample_add_server' normally, the
+ RPC will finish almost instantly. UNLESS the adder is 1, in which
+ case said server is programmed to take 3 seconds to do the
+ computation, thus allowing us to demonstrate a timeout or CTL-C.
+ */
+
+ addInterruptibly(clientP, serverUrl, 5, 7);
+ /* Should finish instantly */
+
+ addInterruptibly(clientP, serverUrl, 5, 1);
+ /* Should time out after 2 seconds */
+
+ xmlrpc_env_clean(&env);
+ xmlrpc_client_destroy(clientP);
+ xmlrpc_client_teardown_global_const();
+
+ return 0;
+}
+
Added: freeswitch/trunk/libs/xmlrpc-c/examples/interrupted_server.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/examples/interrupted_server.c Fri May 23 16:56:24 2008
@@ -0,0 +1,161 @@
+/* A simple standalone XML-RPC server based on Abyss.
+
+ You can terminate this server in controlled fashion with a SIGTERM
+ signal.
+
+ xmlrpc_sample_add_server.c is a server that does the same thing with
+ simpler code, but it is not interruptible with SIGTERM.
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <signal.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <xmlrpc-c/base.h>
+#include <xmlrpc-c/abyss.h>
+#include <xmlrpc-c/server.h>
+#include <xmlrpc-c/server_abyss.h>
+
+#include "config.h" /* information about this build environment */
+
+
+static void
+dieIfFailed(const char * const description,
+ xmlrpc_env const env) {
+
+ if (env.fault_occurred) {
+ fprintf(stderr, "%s failed. %s\n", description, env.fault_string);
+ exit(1);
+ }
+}
+
+
+
+static xmlrpc_server_abyss_t * serverToTerminateP;
+
+static void
+sigtermHandler(int const signalClass ATTR_UNUSED) {
+
+ xmlrpc_env env;
+
+ xmlrpc_env_init(&env);
+
+ xmlrpc_server_abyss_terminate(&env, serverToTerminateP);
+
+ dieIfFailed("xmlrpc_server_abyss_terminate", env);
+
+ xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+setupSigtermHandler(xmlrpc_server_abyss_t * const serverP) {
+
+ struct sigaction mysigaction;
+
+ serverToTerminateP = serverP;
+
+ sigemptyset(&mysigaction.sa_mask);
+ mysigaction.sa_flags = 0;
+ mysigaction.sa_handler = sigtermHandler;
+ sigaction(SIGTERM, &mysigaction, NULL);
+}
+
+
+
+static void
+restoreSigtermHandler(void){
+
+ struct sigaction mysigaction;
+
+ sigemptyset(&mysigaction.sa_mask);
+ mysigaction.sa_flags = 0;
+ mysigaction.sa_handler = SIG_DFL;
+ sigaction(SIGTERM, &mysigaction, NULL);
+}
+
+
+
+static xmlrpc_value *
+sample_add(xmlrpc_env * const envP,
+ xmlrpc_value * const paramArrayP,
+ void * const serverInfo ATTR_UNUSED,
+ void * const channelInfo ATTR_UNUSED) {
+
+ xmlrpc_int x, y, z;
+
+ /* Parse our argument array. */
+ xmlrpc_decompose_value(envP, paramArrayP, "(ii)", &x, &y);
+ if (envP->fault_occurred)
+ return NULL;
+
+ /* Add our two numbers. */
+ z = x + y;
+
+ /* Return our result. */
+ return xmlrpc_build_value(envP, "i", z);
+}
+
+
+
+int
+main(int const argc,
+ const char ** const argv) {
+
+ xmlrpc_server_abyss_parms serverparm;
+ xmlrpc_server_abyss_t * serverP;
+ xmlrpc_registry * registryP;
+ xmlrpc_env env;
+ xmlrpc_server_abyss_sig * oldHandlersP;
+
+ if (argc-1 != 1) {
+ fprintf(stderr, "You must specify 1 argument: The TCP port number "
+ "on which to listen for XML-RPC calls. "
+ "You specified %d.\n", argc-1);
+ exit(1);
+ }
+
+ xmlrpc_env_init(&env);
+
+ xmlrpc_server_abyss_global_init(&env);
+ dieIfFailed("xmlrpc_server_abyss_global_init", env);
+
+ registryP = xmlrpc_registry_new(&env);
+ dieIfFailed("xmlrpc_registry_new", env);
+
+ xmlrpc_registry_add_method2(
+ &env, registryP, "sample.add", &sample_add, NULL, NULL, NULL);
+ dieIfFailed("xmlrpc_registry_add_method2", env);
+
+ serverparm.config_file_name = NULL;
+ serverparm.registryP = registryP;
+ serverparm.port_number = atoi(argv[1]);
+
+ xmlrpc_server_abyss_create(&env, &serverparm, XMLRPC_APSIZE(port_number),
+ &serverP);
+ dieIfFailed("xmlrpc_server_abyss_create", env);
+
+ xmlrpc_server_abyss_setup_sig(&env, serverP, &oldHandlersP);
+ dieIfFailed("xmlrpc_server_abyss_setup_sig", env);
+
+ setupSigtermHandler(serverP);
+
+ printf("Running XML-RPC server...\n");
+
+ xmlrpc_server_abyss_run_server(&env, serverP);
+ dieIfFailed("xmlrpc_server_abyss_run_server", env);
+
+ printf("Server has terminated\n");
+
+ restoreSigtermHandler();
+ xmlrpc_server_abyss_restore_sig(oldHandlersP);
+ xmlrpc_server_abyss_destroy(serverP);
+ xmlrpc_registry_free(registryP);
+ xmlrpc_server_abyss_global_term();
+ xmlrpc_env_clean(&env);
+
+ return 0;
+}
Modified: freeswitch/trunk/libs/xmlrpc-c/examples/synch_client.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/examples/synch_client.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/examples/synch_client.c Fri May 23 16:56:24 2008
@@ -11,11 +11,11 @@
#define NAME "XML-RPC C Test Client synch_client"
#define VERSION "1.0"
-static void die_if_fault_occurred (xmlrpc_env *env)
-{
- if (env->fault_occurred) {
+static void
+die_if_fault_occurred(xmlrpc_env * const envP) {
+ if (envP->fault_occurred) {
fprintf(stderr, "XML-RPC Fault: %s (%d)\n",
- env->fault_string, env->fault_code);
+ envP->fault_string, envP->fault_code);
exit(1);
}
}
@@ -28,7 +28,7 @@
xmlrpc_env env;
xmlrpc_value * resultP;
- const char * state_name;
+ const char * stateName;
if (argc-1 > 0) {
fprintf(stderr, "No arguments");
@@ -48,10 +48,10 @@
die_if_fault_occurred(&env);
/* Get our state name and print it out. */
- xmlrpc_read_string(&env, resultP, &state_name);
+ xmlrpc_read_string(&env, resultP, &stateName);
die_if_fault_occurred(&env);
- printf("%s\n", state_name);
- free((char*)state_name);
+ printf("%s\n", stateName);
+ free((char*)stateName);
/* Dispose of our result value. */
xmlrpc_DECREF(resultP);
Modified: freeswitch/trunk/libs/xmlrpc-c/examples/xmlrpc_asynch_client.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/examples/xmlrpc_asynch_client.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/examples/xmlrpc_asynch_client.c Fri May 23 16:56:24 2008
@@ -3,6 +3,10 @@
simpler synchronous client xmlprc_sample_add_client.c, except that
it adds 3 different pairs of numbers with the summation RPCs going on
simultaneously.
+
+ Use this with xmlrpc_sample_add_server. Note that that server
+ intentionally takes extra time to add 1 to anything, so you can see
+ our 5+1 RPC finish after our 5+0 and 5+2 RPCs.
*/
#include <stdlib.h>
@@ -17,10 +21,10 @@
#define VERSION "1.0"
static void
-die_if_fault_occurred (xmlrpc_env *env) {
- if (env->fault_occurred) {
+die_if_fault_occurred(xmlrpc_env * const envP) {
+ if (envP->fault_occurred) {
fprintf(stderr, "Something failed. %s (XML-RPC fault code %d)\n",
- env->fault_string, env->fault_code);
+ envP->fault_string, envP->fault_code);
exit(1);
}
}
@@ -28,13 +32,13 @@
static void
-handle_sample_add_response(const char * const server_url,
- const char * const method_name,
- xmlrpc_value * const param_array,
+handle_sample_add_response(const char * const serverUrl,
+ const char * const methodName,
+ xmlrpc_value * const paramArrayP,
void * const user_data ATTR_UNUSED,
xmlrpc_env * const faultP,
xmlrpc_value * const resultP) {
-
+
xmlrpc_env env;
xmlrpc_int addend, adder;
@@ -44,14 +48,14 @@
/* Our first four arguments provide helpful context. Let's grab the
addends from our parameter array.
*/
- xmlrpc_decompose_value(&env, param_array, "(ii)", &addend, &adder);
+ xmlrpc_decompose_value(&env, paramArrayP, "(ii)", &addend, &adder);
die_if_fault_occurred(&env);
printf("RPC with method '%s' at URL '%s' to add %d and %d "
- "has completed\n", method_name, server_url, addend, adder);
+ "has completed\n", methodName, serverUrl, addend, adder);
if (faultP->fault_occurred)
- printf("The RPC failed. %s", faultP->fault_string);
+ printf("The RPC failed. %s\n", faultP->fault_string);
else {
xmlrpc_int sum;
@@ -68,10 +72,11 @@
main(int const argc,
const char ** const argv ATTR_UNUSED) {
- char * const url = "http://localhost:8080/RPC2";
- char * const methodName = "sample.add";
+ const char * const serverUrl = "http://localhost:8080/RPC2";
+ const char * const methodName = "sample.add";
xmlrpc_env env;
+ xmlrpc_client * clientP;
xmlrpc_int adder;
if (argc-1 > 0) {
@@ -82,17 +87,21 @@
/* Initialize our error environment variable */
xmlrpc_env_init(&env);
- /* Create the Xmlrpc-c client object */
- xmlrpc_client_init2(&env, XMLRPC_CLIENT_NO_FLAGS, NAME, VERSION, NULL, 0);
+ /* Required before any use of Xmlrpc-c client library: */
+ xmlrpc_client_setup_global_const(&env);
+ die_if_fault_occurred(&env);
+
+ xmlrpc_client_create(&env, XMLRPC_CLIENT_NO_FLAGS, NAME, VERSION, NULL, 0,
+ &clientP);
die_if_fault_occurred(&env);
for (adder = 0; adder < 3; ++adder) {
printf("Making XMLRPC call to server url '%s' method '%s' "
"to request the sum "
- "of 5 and %d...\n", url, methodName, adder);
+ "of 5 and %d...\n", serverUrl, methodName, adder);
/* request the remote procedure call */
- xmlrpc_client_call_asynch(url, methodName,
+ xmlrpc_client_start_rpcf(&env, clientP, serverUrl, methodName,
handle_sample_add_response, NULL,
"(ii)", (xmlrpc_int32) 5, adder);
die_if_fault_occurred(&env);
@@ -100,13 +109,15 @@
printf("RPCs all requested. Waiting for & handling responses...\n");
- /* The following is what calls handle_sample_add_response() (3 times) */
- xmlrpc_client_event_loop_finish_asynch();
+ /* Wait for all RPCs to be done. With some transports, this is also
+ what causes them to go.
+ */
+ xmlrpc_client_event_loop_finish(clientP);
printf("All RPCs finished.\n");
- /* Destroy the Xmlrpc-c client object */
- xmlrpc_client_cleanup();
+ xmlrpc_client_destroy(clientP);
+ xmlrpc_client_teardown_global_const();
return 0;
}
Added: freeswitch/trunk/libs/xmlrpc-c/examples/xmlrpc_inetd_server.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/examples/xmlrpc_inetd_server.c Fri May 23 16:56:24 2008
@@ -0,0 +1,121 @@
+/* A simple standalone XML-RPC server based on Abyss that processes a
+ single RPC from an existing TCP connection on Standard Input.
+
+ A typical example of where this would be useful is with an Inetd
+ "super server."
+
+ xmlrpc_sample_add_server.c is a server that does the same thing,
+ but you give it a TCP port number and it listens for TCP connecitons
+ and processes RPCs ad infinitum. xmlrpc_socket_server.c is halfway
+ in between those -- you give it an already bound and listening
+ socket, and it lists for TCP connections and processes RPCs ad
+ infinitum.
+
+ Here is an easy way to test this program:
+
+ socketexec --accept --local_port=8080 --stdin -- ./xmlrpc_inetd_server
+
+ Now run the client program 'xmlrpc_sample_add_client'. Socketexec
+ will accept the connection that the client program requests and pass it
+ to this program on Standard Input. This program will perform the RPC,
+ respond to the client, then exit.
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <signal.h>
+#ifndef WIN32
+#include <unistd.h>
+#endif
+
+#include <xmlrpc-c/base.h>
+#include <xmlrpc-c/abyss.h>
+#include <xmlrpc-c/server.h>
+#include <xmlrpc-c/server_abyss.h>
+
+#include "config.h" /* information about this build environment */
+
+
+static void
+setupSignalHandlers(void) {
+
+ /* In UNIX, when you try to write to a socket that has been closed
+ from the other end, your write fails, but you also get a SIGPIPE
+ signal. That signal will kill you before you even have a chance
+ to see the write fail unless you catch, block, or ignore it.
+ If a client should connect to us and then disconnect before we've
+ sent our response, we see this socket-closed behavior. We
+ obviously don't want to die just because a client didn't complete
+ an RPC, so we ignore SIGPIPE.
+ */
+#ifndef WIN32
+ struct sigaction mysigaction;
+
+ sigemptyset(&mysigaction.sa_mask);
+ mysigaction.sa_flags = 0;
+ mysigaction.sa_handler = SIG_IGN;
+ sigaction(SIGPIPE, &mysigaction, NULL);
+#endif
+}
+
+
+
+static xmlrpc_value *
+sample_add(xmlrpc_env * const envP,
+ xmlrpc_value * const paramArrayP,
+ void * const serverInfo ATTR_UNUSED,
+ void * const channelInfo ATTR_UNUSED) {
+
+ xmlrpc_int x, y, z;
+
+ /* Parse our argument array. */
+ xmlrpc_decompose_value(envP, paramArrayP, "(ii)", &x, &y);
+ if (envP->fault_occurred)
+ return NULL;
+
+ /* Add our two numbers. */
+ z = x + y;
+
+ /* Return our result. */
+ return xmlrpc_build_value(envP, "i", z);
+}
+
+
+
+int
+main(int const argc,
+ const char ** const argv) {
+
+ TServer abyssServer;
+ xmlrpc_registry * registryP;
+ xmlrpc_env env;
+
+ if (argc-1 != 0) {
+ fprintf(stderr, "There are no arguments. You must supply a "
+ "bound socket on which to listen for client connections "
+ "as Standard Input\n");
+ if (argv) {} /* silence unused parameter warning */
+ exit(1);
+ }
+ xmlrpc_env_init(&env);
+
+ registryP = xmlrpc_registry_new(&env);
+
+ xmlrpc_registry_add_method2(
+ &env, registryP, "sample.add", &sample_add, NULL, NULL, NULL);
+
+ ServerCreateNoAccept(&abyssServer, "XmlRpcServer", NULL, NULL);
+
+ xmlrpc_server_abyss_set_handlers(&abyssServer, registryP);
+
+ setupSignalHandlers();
+
+ ServerRunConn(&abyssServer, STDIN_FILENO);
+ /* This reads the HTTP POST request from Standard Input and
+ executes the indicated RPC.
+ */
+
+ ServerFree(&abyssServer);
+
+ return 0;
+}
Modified: freeswitch/trunk/libs/xmlrpc-c/examples/xmlrpc_loop_server.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/examples/xmlrpc_loop_server.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/examples/xmlrpc_loop_server.c Fri May 23 16:56:24 2008
@@ -9,6 +9,9 @@
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
#include <xmlrpc-c/base.h>
#include <xmlrpc-c/abyss.h>
#include <xmlrpc-c/server.h>
@@ -29,12 +32,33 @@
obviously don't want to die just because a client didn't complete
an RPC, so we ignore SIGPIPE.
*/
+#ifndef WIN32
struct sigaction mysigaction;
sigemptyset(&mysigaction.sa_mask);
mysigaction.sa_flags = 0;
mysigaction.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &mysigaction, NULL);
+#endif
+}
+
+
+
+static void
+printPeerIpAddr(TSession * const abyssSessionP) {
+
+ struct abyss_unix_chaninfo * channelInfoP;
+ struct sockaddr_in * sockAddrInP;
+ unsigned char * ipAddr; /* 4 byte array */
+
+ SessionGetChannelInfo(abyssSessionP, (void*)&channelInfoP);
+
+ sockAddrInP = (struct sockaddr_in *) &channelInfoP->peerAddr;
+
+ ipAddr = (unsigned char *)&sockAddrInP->sin_addr.s_addr;
+
+ printf("RPC is from IP address %u.%u.%u.%u\n",
+ ipAddr[0], ipAddr[1], ipAddr[2], ipAddr[3]);
}
@@ -42,10 +66,13 @@
static xmlrpc_value *
sample_add(xmlrpc_env * const envP,
xmlrpc_value * const paramArrayP,
- void * const userData ATTR_UNUSED) {
+ void * const serverInfo ATTR_UNUSED,
+ void * const channelInfo) {
xmlrpc_int x, y, z;
+ printPeerIpAddr(channelInfo);
+
/* Parse our argument array. */
xmlrpc_decompose_value(envP, paramArrayP, "(ii)", &x, &y);
if (envP->fault_occurred)
@@ -60,6 +87,32 @@
+static xmlrpc_server_shutdown_fn requestShutdown;
+
+static void
+requestShutdown(xmlrpc_env * const faultP,
+ void * const context,
+ const char * const comment,
+ void * const callInfo) {
+
+ /* You make this run by executing the system method
+ 'system.shutdown'. This function is registered in the method
+ registry as the thing to call for that.
+ */
+ int * const terminationRequestedP = context;
+ TSession * const abyssSessionP = callInfo;
+
+ xmlrpc_env_init(faultP);
+
+ fprintf(stderr, "Termination requested: %s\n", comment);
+
+ printPeerIpAddr(abyssSessionP);
+
+ *terminationRequestedP = 1;
+}
+
+
+
int
main(int const argc,
const char ** const argv) {
@@ -67,6 +120,8 @@
TServer abyssServer;
xmlrpc_registry * registryP;
xmlrpc_env env;
+ int terminationRequested; /* A boolean value */
+ const char * error;
if (argc-1 != 1) {
fprintf(stderr, "You must specify 1 argument: The TCP port number "
@@ -74,34 +129,42 @@
"You specified %d.\n", argc-1);
exit(1);
}
+
+ AbyssInit(&error);
xmlrpc_env_init(&env);
registryP = xmlrpc_registry_new(&env);
- xmlrpc_registry_add_method(
- &env, registryP, NULL, "sample.add", &sample_add, NULL);
+ xmlrpc_registry_add_method2(
+ &env, registryP, "sample.add", &sample_add, NULL, NULL, NULL);
- MIMETypeInit();
+ xmlrpc_registry_set_shutdown(registryP,
+ &requestShutdown, &terminationRequested);
- ServerCreate(&abyssServer, "XmlRpcServer", atoi(argv[1]),
- NULL, NULL);
+ ServerCreate(&abyssServer, "XmlRpcServer", atoi(argv[1]), NULL, NULL);
- xmlrpc_server_abyss_set_handlers(&abyssServer, registryP);
+ xmlrpc_server_abyss_set_handlers2(&abyssServer, "/RPC2", registryP);
ServerInit(&abyssServer);
setupSignalHandlers();
- while (1) {
+ terminationRequested = 0;
+
+ while (!terminationRequested) {
printf("Waiting for next RPC...\n");
- ServerRunOnce2(&abyssServer, ABYSS_FOREGROUND);
+ ServerRunOnce(&abyssServer);
/* This waits for the next connection, accepts it, reads the
HTTP POST request, executes the indicated RPC, and closes
the connection.
*/
}
+ ServerFree(&abyssServer);
+
+ AbyssTerm();
+
return 0;
}
Modified: freeswitch/trunk/libs/xmlrpc-c/examples/xmlrpc_sample_add_client.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/examples/xmlrpc_sample_add_client.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/examples/xmlrpc_sample_add_client.c Fri May 23 16:56:24 2008
@@ -16,10 +16,10 @@
#define VERSION "1.0"
static void
-die_if_fault_occurred (xmlrpc_env *env) {
- if (env->fault_occurred) {
+die_if_fault_occurred (xmlrpc_env * const envP) {
+ if (envP->fault_occurred) {
fprintf(stderr, "XML-RPC Fault: %s (%d)\n",
- env->fault_string, env->fault_code);
+ envP->fault_string, envP->fault_code);
exit(1);
}
}
@@ -31,10 +31,10 @@
const char ** const argv ATTR_UNUSED) {
xmlrpc_env env;
- xmlrpc_value *result;
+ xmlrpc_value * resultP;
xmlrpc_int32 sum;
- char * const serverUrl = "http://localhost:8080/RPC2";
- char * const methodName = "sample.add";
+ const char * const serverUrl = "http://localhost:8080/RPC2";
+ const char * const methodName = "sample.add";
if (argc-1 > 0) {
fprintf(stderr, "This program has no arguments\n");
@@ -53,17 +53,17 @@
"of 5 and 7...\n", serverUrl, methodName);
/* Make the remote procedure call */
- result = xmlrpc_client_call(&env, serverUrl, methodName,
- "(ii)", (xmlrpc_int32) 5, (xmlrpc_int32) 7);
+ resultP = xmlrpc_client_call(&env, serverUrl, methodName,
+ "(ii)", (xmlrpc_int32) 5, (xmlrpc_int32) 7);
die_if_fault_occurred(&env);
/* Get our sum and print it out. */
- xmlrpc_read_int(&env, result, &sum);
+ xmlrpc_read_int(&env, resultP, &sum);
die_if_fault_occurred(&env);
- printf("The sum is %d\n", sum);
+ printf("The sum is %d\n", sum);
/* Dispose of our result value. */
- xmlrpc_DECREF(result);
+ xmlrpc_DECREF(resultP);
/* Clean up our error-handling environment. */
xmlrpc_env_clean(&env);
Modified: freeswitch/trunk/libs/xmlrpc-c/examples/xmlrpc_sample_add_server.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/examples/xmlrpc_sample_add_server.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/examples/xmlrpc_sample_add_server.c Fri May 23 16:56:24 2008
@@ -2,6 +2,11 @@
#include <stdlib.h>
#include <stdio.h>
+#ifdef WIN32
+# include <windows.h>
+#else
+# include <unistd.h>
+#endif
#include <xmlrpc-c/base.h>
#include <xmlrpc-c/server.h>
@@ -9,23 +14,38 @@
#include "config.h" /* information about this build environment */
+
+#ifdef WIN32
+ #define SLEEP(seconds) SleepEx(seconds * 1000, 1);
+#else
+ #define SLEEP(seconds) sleep(seconds);
+#endif
+
+
static xmlrpc_value *
-sample_add(xmlrpc_env * const env,
- xmlrpc_value * const param_array,
- void * const user_data ATTR_UNUSED) {
+sample_add(xmlrpc_env * const envP,
+ xmlrpc_value * const paramArrayP,
+ void * const serverInfo ATTR_UNUSED,
+ void * const channelInfo ATTR_UNUSED) {
xmlrpc_int32 x, y, z;
/* Parse our argument array. */
- xmlrpc_decompose_value(env, param_array, "(ii)", &x, &y);
- if (env->fault_occurred)
+ xmlrpc_decompose_value(envP, paramArrayP, "(ii)", &x, &y);
+ if (envP->fault_occurred)
return NULL;
/* Add our two numbers. */
z = x + y;
+ /* Sometimes, make it look hard (so client can see what it's like
+ to do an RPC that takes a while).
+ */
+ if (y == 1)
+ SLEEP(3);
+
/* Return our result. */
- return xmlrpc_build_value(env, "i", z);
+ return xmlrpc_build_value(envP, "i", z);
}
@@ -41,7 +61,8 @@
if (argc-1 != 1) {
fprintf(stderr, "You must specify 1 argument: The TCP port "
"number on which the server will accept connections "
- "for RPCs. You specified %d arguments.\n", argc-1);
+ "for RPCs (8080 is a common choice). "
+ "You specified %d arguments.\n", argc-1);
exit(1);
}
@@ -49,17 +70,17 @@
registryP = xmlrpc_registry_new(&env);
- xmlrpc_registry_add_method(
- &env, registryP, NULL, "sample.add", &sample_add, NULL);
+ xmlrpc_registry_add_method2(
+ &env, registryP, "sample.add", &sample_add, NULL, NULL, NULL);
/* In the modern form of the Abyss API, we supply parameters in memory
like a normal API. We select the modern form by setting
config_file_name to NULL:
*/
serverparm.config_file_name = NULL;
- serverparm.registryP = registryP;
- serverparm.port_number = atoi(argv[1]);
- serverparm.log_file_name = "/tmp/xmlrpc_log";
+ serverparm.registryP = registryP;
+ serverparm.port_number = atoi(argv[1]);
+ serverparm.log_file_name = "/tmp/xmlrpc_log";
printf("Running XML-RPC server...\n");
Modified: freeswitch/trunk/libs/xmlrpc-c/examples/xmlrpc_sample_add_server_cgi.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/examples/xmlrpc_sample_add_server_cgi.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/examples/xmlrpc_sample_add_server_cgi.c Fri May 23 16:56:24 2008
@@ -10,22 +10,22 @@
#include "config.h" /* information about this build environment */
static xmlrpc_value *
-sample_add(xmlrpc_env * const env,
- xmlrpc_value * const param_array,
+sample_add(xmlrpc_env * const envP,
+ xmlrpc_value * const paramArrayP,
void * const user_data ATTR_UNUSED) {
xmlrpc_int32 x, y, z;
/* Parse our argument array. */
- xmlrpc_decompose_value(env, param_array, "(ii)", &x, &y);
- if (env->fault_occurred)
+ xmlrpc_decompose_value(envP, paramArrayP, "(ii)", &x, &y);
+ if (envP->fault_occurred)
return NULL;
/* Add our two numbers. */
z = x + y;
/* Return our result. */
- return xmlrpc_build_value(env, "i", z);
+ return xmlrpc_build_value(envP, "i", z);
}
Modified: freeswitch/trunk/libs/xmlrpc-c/examples/xmlrpc_sample_add_server_w32httpsys.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/examples/xmlrpc_sample_add_server_w32httpsys.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/examples/xmlrpc_sample_add_server_w32httpsys.c Fri May 23 16:56:24 2008
@@ -167,8 +167,8 @@
serverparm.portNum=8080;
//if this is set, we will use the authorization function
- serverparm.authfn=NULL;
- //serverparm.authfn=&handleAuthorization;
+ //serverparm.authfn=NULL;
+ serverparm.authfn=&handleAuthorization;
//set the logging level and log file
serverparm.logLevel=2;
Modified: freeswitch/trunk/libs/xmlrpc-c/examples/xmlrpc_server_validatee.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/examples/xmlrpc_server_validatee.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/examples/xmlrpc_server_validatee.c Fri May 23 16:56:24 2008
@@ -51,9 +51,9 @@
#include "config.h" /* information about this build environment */
-#define RETURN_IF_FAULT(env) \
+#define RETURN_IF_FAULT(envP) \
do { \
- if ((env)->fault_occurred) \
+ if ((envP)->fault_occurred) \
return NULL; \
} while (0)
@@ -65,20 +65,19 @@
static xmlrpc_value *
array_of_structs(xmlrpc_env * const envP,
- xmlrpc_value * const param_array,
+ xmlrpc_value * const paramArrayP,
void * const user_data ATTR_UNUSED) {
- xmlrpc_value * array;
+ xmlrpc_value * arrayP;
xmlrpc_value * retval;
- /* Parse our argument array. */
- xmlrpc_decompose_value(envP, param_array, "(A)", &array);
+ xmlrpc_decompose_value(envP, paramArrayP, "(A)", &arrayP);
if (envP->fault_occurred)
retval = NULL;
else {
/* Add up all the struct elements named "curly". */
size_t size;
- size = xmlrpc_array_size(envP, array);
+ size = xmlrpc_array_size(envP, arrayP);
if (envP->fault_occurred)
retval = NULL;
else {
@@ -86,18 +85,20 @@
unsigned int i;
sum = 0;
for (i = 0; i < size && !envP->fault_occurred; ++i) {
- xmlrpc_value * strct;
- strct = xmlrpc_array_get_item(envP, array, i);
+ xmlrpc_value * strctP;
+ strctP = xmlrpc_array_get_item(envP, arrayP, i);
if (!envP->fault_occurred) {
xmlrpc_int32 curly;
- xmlrpc_decompose_value(envP, strct, "{s:i,*}",
+ xmlrpc_decompose_value(envP, strctP, "{s:i,*}",
"curly", &curly);
if (!envP->fault_occurred)
sum += curly;
}
}
- xmlrpc_DECREF(array);
- if (!envP->fault_occurred)
+ xmlrpc_DECREF(arrayP);
+ if (envP->fault_occurred)
+ retval = NULL;
+ else
retval = xmlrpc_build_value(envP, "i", sum);
}
}
@@ -111,30 +112,31 @@
*/
static xmlrpc_value *
-count_entities(xmlrpc_env * const env,
- xmlrpc_value * const param_array,
+count_entities(xmlrpc_env * const envP,
+ xmlrpc_value * const paramArrayP,
void * const user_data ATTR_UNUSED) {
- const char *str;
+
+ const char * str;
size_t len, i;
xmlrpc_int32 left, right, amp, apos, quote;
- xmlrpc_decompose_value(env, param_array, "(s#)", &str, &len);
- RETURN_IF_FAULT(env);
+ xmlrpc_decompose_value(envP, paramArrayP, "(s#)", &str, &len);
+ RETURN_IF_FAULT(envP);
left = right = amp = apos = quote = 0;
- for (i = 0; i < len; i++) {
+ for (i = 0; i < len; ++i) {
switch (str[i]) {
- case '<': left++; break;
- case '>': right++; break;
- case '&': amp++; break;
- case '\'': apos++; break;
- case '\"': quote++; break;
+ case '<': ++left; break;
+ case '>': ++right; break;
+ case '&': ++amp; break;
+ case '\'': ++apos; break;
+ case '\"': ++quote; break;
default: break;
}
}
free((void*)str);
- return xmlrpc_build_value(env, "{s:i,s:i,s:i,s:i,s:i}",
+ return xmlrpc_build_value(envP, "{s:i,s:i,s:i,s:i,s:i}",
"ctLeftAngleBrackets", left,
"ctRightAngleBrackets", right,
"ctAmpersands", amp,
@@ -150,43 +152,46 @@
*/
static xmlrpc_value *
-easy_struct(xmlrpc_env * const env,
- xmlrpc_value * const param_array,
+easy_struct(xmlrpc_env * const envP,
+ xmlrpc_value * const paramArrayP,
void * const user_data ATTR_UNUSED) {
xmlrpc_int32 larry, moe, curly;
/* Parse our argument array and get the stooges. */
- xmlrpc_decompose_value(env, param_array, "({s:i,s:i,s:i,*})",
+ xmlrpc_decompose_value(envP, paramArrayP, "({s:i,s:i,s:i,*})",
"larry", &larry,
"moe", &moe,
"curly", &curly);
- RETURN_IF_FAULT(env);
+ RETURN_IF_FAULT(envP);
/* Return our result. */
- return xmlrpc_build_value(env, "i", larry + moe + curly);
+ return xmlrpc_build_value(envP, "i", larry + moe + curly);
}
+
/*=========================================================================
** validator1.echoStructTest
**=========================================================================
*/
static xmlrpc_value *
-echo_struct(xmlrpc_env * const env,
- xmlrpc_value * const param_array,
+echo_struct(xmlrpc_env * const envP,
+ xmlrpc_value * const paramArrayP,
void * const user_data ATTR_UNUSED) {
- xmlrpc_value *s;
+
+ xmlrpc_value * sP;
/* Parse our argument array. */
- xmlrpc_decompose_value(env, param_array, "(S)", &s);
- RETURN_IF_FAULT(env);
+ xmlrpc_decompose_value(envP, paramArrayP, "(S)", &sP);
+ RETURN_IF_FAULT(envP);
- return s; /* We transfer our reference on 's' to Caller */
+ return sP; /* We transfer our reference on '*sP' to Caller */
}
+
/*=========================================================================
** validator1.manyTypesTest
**=========================================================================
@@ -203,6 +208,7 @@
}
+
/*=========================================================================
** validator1.moderateSizeArrayCheck
**=========================================================================
@@ -214,7 +220,7 @@
size_t const str1_len,
const char * const str2,
size_t const str2_len,
- xmlrpc_value ** const resultP) {
+ xmlrpc_value ** const resultPP) {
/* Concatenate the two strings. */
@@ -227,8 +233,8 @@
} else {
memcpy(buffer, str1, str1_len);
memcpy(&buffer[str1_len], str2, str2_len);
- *resultP = xmlrpc_build_value(envP, "s#",
- buffer, str1_len + str2_len);
+ *resultPP = xmlrpc_build_value(envP, "s#",
+ buffer, str1_len + str2_len);
free(buffer);
}
}
@@ -236,31 +242,34 @@
static xmlrpc_value *
-moderate_array(xmlrpc_env * const envP,
- xmlrpc_value * const param_array,
+moderate_array(xmlrpc_env * const envP,
+ xmlrpc_value * const paramArrayP,
void * const user_data ATTR_UNUSED) {
- xmlrpc_value *array, *item, *result;
- int size;
- const char * str1;
- const char * str2;
- size_t str1_len, str2_len;
xmlrpc_value * retval;
+ xmlrpc_value * arrayP;
/* Parse our argument array. */
- xmlrpc_decompose_value(envP, param_array, "(A)", &array);
+ xmlrpc_decompose_value(envP, paramArrayP, "(A)", &arrayP);
if (!envP->fault_occurred) {
- size = xmlrpc_array_size(envP, array);
+ int const size = xmlrpc_array_size(envP, arrayP);
if (!envP->fault_occurred) {
/* Get our first string. */
- item = xmlrpc_array_get_item(envP, array, 0);
+ xmlrpc_value * const firstItemP =
+ xmlrpc_array_get_item(envP, arrayP, 0);
if (!envP->fault_occurred) {
- xmlrpc_read_string_lp(envP, item, &str1_len, &str1);
+ const char * str1;
+ size_t str1_len;
+ xmlrpc_read_string_lp(envP, firstItemP, &str1_len, &str1);
if (!envP->fault_occurred) {
/* Get our last string. */
- item = xmlrpc_array_get_item(envP, array, size - 1);
+ xmlrpc_value * const lastItemP =
+ xmlrpc_array_get_item(envP, arrayP, size - 1);
if (!envP->fault_occurred) {
- xmlrpc_read_string_lp(envP, item, &str2_len, &str2);
+ const char * str2;
+ size_t str2_len;
+ xmlrpc_read_string_lp(envP, lastItemP,
+ &str2_len, &str2);
if (!envP->fault_occurred) {
concatenate(envP, str1, str1_len, str2, str2_len,
&retval);
@@ -271,12 +280,13 @@
}
}
}
- xmlrpc_DECREF(array);
+ xmlrpc_DECREF(arrayP);
}
- return result;
+ return retval;
}
+
/*=========================================================================
** validator1.nestedStructTest
**=========================================================================
@@ -284,15 +294,17 @@
static xmlrpc_value *
nested_struct(xmlrpc_env * const envP,
- xmlrpc_value * const param_array,
+ xmlrpc_value * const paramArrayP,
void * const user_data ATTR_UNUSED) {
xmlrpc_value * yearsP;
xmlrpc_value * retval;
/* Parse our argument array. */
- xmlrpc_decompose_value(envP, param_array, "(S)", &yearsP);
- if (!envP->fault_occurred) {
+ xmlrpc_decompose_value(envP, paramArrayP, "(S)", &yearsP);
+ if (envP->fault_occurred)
+ retval = NULL;
+ else {
/* Get values of larry, moe and curly for 2000-04-01. */
xmlrpc_int32 larry, moe, curly;
xmlrpc_decompose_value(envP, yearsP,
@@ -301,36 +313,41 @@
"larry", &larry,
"moe", &moe,
"curly", &curly);
- if (!envP->fault_occurred)
+ if (envP->fault_occurred)
+ retval = NULL;
+ else
retval = xmlrpc_build_value(envP, "i", larry + moe + curly);
+
xmlrpc_DECREF(yearsP);
}
return retval;
}
+
/*=========================================================================
** validator1.simpleStructReturnTest
**=========================================================================
*/
static xmlrpc_value *
-struct_return(xmlrpc_env * const env,
- xmlrpc_value * const param_array,
+struct_return(xmlrpc_env * const envP,
+ xmlrpc_value * const paramArrayP,
void * const user_data ATTR_UNUSED) {
xmlrpc_int32 i;
- xmlrpc_decompose_value(env, param_array, "(i)", &i);
- RETURN_IF_FAULT(env);
+ xmlrpc_decompose_value(envP, paramArrayP, "(i)", &i);
+ RETURN_IF_FAULT(envP);
- return xmlrpc_build_value(env, "{s:i,s:i,s:i}",
+ return xmlrpc_build_value(envP, "{s:i,s:i,s:i}",
"times10", (xmlrpc_int32) i * 10,
"times100", (xmlrpc_int32) i * 100,
"times1000", (xmlrpc_int32) i * 1000);
}
+
/*=========================================================================
** main
**=========================================================================
Added: freeswitch/trunk/libs/xmlrpc-c/examples/xmlrpc_socket_server.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/examples/xmlrpc_socket_server.c Fri May 23 16:56:24 2008
@@ -0,0 +1,102 @@
+/* A simple standalone XML-RPC server written in C as an example of use of
+ the Xmlrpc-c libraries.
+
+ This example expects an already bound socket on Standard Input, ready to
+ be listened on for client connections. Also see xmlrpc_sample_add_server,
+ which is the same thing, except you tell it a TCP port number and it
+ creates the socket itself. Also see xmlrpc_inetd_server.c, which is
+ the same thing except you give it a socket which is already connected
+ to a client.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#ifdef WIN32
+# include <windows.h>
+#else
+# include <unistd.h>
+#endif
+
+#include <xmlrpc-c/base.h>
+#include <xmlrpc-c/server.h>
+#include <xmlrpc-c/server_abyss.h>
+
+#include "config.h" /* information about this build environment */
+
+#ifdef WIN32
+ #define SLEEP(seconds) SleepEx(seconds * 1000, 1);
+#else
+ #define SLEEP(seconds) sleep(seconds);
+#endif
+
+
+static xmlrpc_value *
+sample_add(xmlrpc_env * const envP,
+ xmlrpc_value * const paramArrayP,
+ void * const user_data ATTR_UNUSED) {
+
+ xmlrpc_int32 x, y, z;
+
+ /* Parse our argument array. */
+ xmlrpc_decompose_value(envP, paramArrayP, "(ii)", &x, &y);
+ if (envP->fault_occurred)
+ return NULL;
+
+ /* Add our two numbers. */
+ z = x + y;
+
+ /* Sometimes, make it look hard (so client can see what it's like
+ to do an RPC that takes a while).
+ */
+ if (y == 1)
+ SLEEP(2);
+
+ /* Return our result. */
+ return xmlrpc_build_value(envP, "i", z);
+}
+
+
+
+int
+main(int const argc,
+ const char ** const argv) {
+
+ xmlrpc_server_abyss_parms serverparm;
+ xmlrpc_registry * registryP;
+ xmlrpc_env env;
+
+ if (argc-1 != 0) {
+ fprintf(stderr, "There are no arguments. You must supply a "
+ "bound socket on which to listen for client connections "
+ "as Standard Input\n");
+ if (argv) {} /* silence unused parameter warning */
+ exit(1);
+ }
+
+ xmlrpc_env_init(&env);
+
+ registryP = xmlrpc_registry_new(&env);
+
+ xmlrpc_registry_add_method(
+ &env, registryP, NULL, "sample.add", &sample_add, NULL);
+
+ /* In the modern form of the Abyss API, we supply parameters in memory
+ like a normal API. We select the modern form by setting
+ config_file_name to NULL:
+ */
+ serverparm.config_file_name = NULL;
+ serverparm.registryP = registryP;
+ serverparm.log_file_name = "/tmp/xmlrpc_log";
+ serverparm.keepalive_timeout = 0;
+ serverparm.keepalive_max_conn = 0;
+ serverparm.timeout = 0;
+ serverparm.dont_advertise = FALSE;
+ serverparm.socket_bound = TRUE;
+ serverparm.socket_handle = STDIN_FILENO;
+
+ printf("Running XML-RPC server...\n");
+
+ xmlrpc_server_abyss(&env, &serverparm, XMLRPC_APSIZE(socket_handle));
+
+ return 0;
+}
Modified: freeswitch/trunk/libs/xmlrpc-c/include/Makefile
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/include/Makefile (original)
+++ freeswitch/trunk/libs/xmlrpc-c/include/Makefile Fri May 23 16:56:24 2008
@@ -1,60 +1,146 @@
-ifeq ($(SRCDIR)x,x)
-SRCDIR = $(CURDIR)/..
+ifeq ($(SRCDIR),)
+ updir = $(shell echo $(dir $(1)) | sed 's/.$$//')
+ SRCDIR := $(call updir,$(CURDIR))
+ BLDDIR := $(SRCDIR)
endif
-SUBDIR = src
-BUILDDIR = $(SRCDIR)
-VPATH = .:$(SRCDIR)
+SUBDIR := include
-include $(BUILDDIR)/Makefile.config
+include $(BLDDIR)/config.mk
+
+default: all
+
+all: xmlrpc-c/config.h
+
+xmlrpc-c/config.h: $(BLDDIR)/$(SUBDIR)/xmlrpc-c
+ >$@
+ @echo "Lots of echoes to '$@' suppressed here ..."
+ @echo '#ifndef XMLRPC_C_CONFIG_H_INCLUDED' >>$@
+ @echo '#define XMLRPC_C_CONFIG_H_INCLUDED' >>$@
+ @echo '' >>$@
+ @echo '/* This file, part of XML-RPC For C/C++, is meant to ' >>$@
+ @echo ' define characteristics of this particular installation '>>$@
+ @echo ' that the other <xmlrpc-c/...> header files need in ' >>$@
+ @echo ' order to compile correctly when #included in Xmlrpc-c' >>$@
+ @echo ' user code.' >>$@
+ @echo '' >>$@
+ @echo ' Those header files #include this one.' >>$@
+ @echo '' >>$@
+ @echo ' This file was created by a make rule.' >>$@
+ @echo '*/' >>$@
+ @echo '#define XMLRPC_HAVE_WCHAR $(HAVE_WCHAR_H_DEFINE)' >>$@
+ @echo '#ifdef WIN32' >>$@
+ @echo ' /* SOCKET is a type defined by <winsock.h>. Anyone who' >>$@
+ @echo ' uses XMLRPC_SOCKET on a WIN32 system must #include' >>$@
+ @echo ' <winsock.h>' >>$@
+ @echo ' */' >>$@
+ @echo ' #define XMLRPC_SOCKET SOCKET' >>$@
+ @echo ' #define XMLRPC_HAVE_TIMEVAL 0' >>$@
+ @echo ' #define XMLRPC_HAVE_TIMESPEC 0' >>$@
+ @echo '#else' >>$@
+ @echo ' #define XMLRPC_SOCKET int' >>$@
+ @echo ' #define XMLRPC_HAVE_TIMEVAL 1' >>$@
+ @echo ' #define XMLRPC_HAVE_TIMESPEC 1' >>$@
+ @echo '#endif' >>$@
+ @echo '' >>$@
+ @echo '#if defined(_MSC_VER)' >>$@
+ @echo ' /* Newer MSVC has long long, but MSVC 6 does not */' >>$@
+ @echo ' #define XMLRPC_INT64 __int64' >>$@
+ @echo ' #define XMLRPC_INT32 __int32' >>$@
+ @echo '#else' >>$@
+ @echo ' #define XMLRPC_INT64 long long' >>$@
+ @echo ' #define XMLRPC_INT32 int' >>$@
+ @echo '#endif' >>$@
+ @echo '#endif' >>$@
+
+$(BLDDIR)/$(SUBDIR)/xmlrpc-c:
+ mkdir $@
+
+COMPAT_LINK_CMDS = \
+ $(LN_S) xmlrpc-c/oldxmlrpc.h xmlrpc.h; \
+ $(LN_S) xmlrpc-c/server.h xmlrpc_server.h; \
+ $(LN_S) xmlrpc-c/server_abyss.h xmlrpc_server_abyss.h; \
+ $(LN_S) xmlrpc-c/server_w32httpsys.h xmlrpc_server_w32httpsys.h; \
HEADERS_TO_INSTALL = \
- xmlrpc-c/oldxmlrpc.h \
+ xmlrpc-c/config.h \
+ xmlrpc-c/inttypes.h \
+ xmlrpc-c/c_util.h \
+ xmlrpc-c/util.h \
xmlrpc-c/base.h \
xmlrpc-c/abyss.h \
+ xmlrpc-c/abyss_unixsock.h \
+ xmlrpc-c/abyss_winsock.h \
xmlrpc-c/server.h \
xmlrpc-c/server_abyss.h \
xmlrpc-c/server_w32httpsys.h \
+ xmlrpc-c/oldxmlrpc.h \
ifeq ($(ENABLE_CPLUSPLUS),yes)
HEADERS_TO_INSTALL += \
xmlrpc-c/oldcppwrapper.hpp \
+ xmlrpc-c/girerr.hpp \
+ xmlrpc-c/girmem.hpp \
xmlrpc-c/base.hpp \
xmlrpc-c/timeout.hpp \
xmlrpc-c/xml.hpp \
xmlrpc-c/registry.hpp \
- xmlrpc-c/server_abyss.hpp\
- xmlrpc-c/girerr.hpp\
- xmlrpc-c/girmem.hpp\
+ xmlrpc-c/server_abyss.hpp \
+ xmlrpc-c/packetsocket.hpp \
+ xmlrpc-c/server_pstream.hpp \
+ COMPAT_LINK_CMDS += $(LN_S) xmlrpc-c/oldcppwrapper.hpp XmlRpcCpp.h;
endif
-
-
HEADERINST_PREFIX = /xmlrpc-c
ifeq ($(MUST_BUILD_CLIENT),yes)
HEADERS_TO_INSTALL += \
xmlrpc-c/client.h \
xmlrpc-c/transport.h \
+ xmlrpc-c/client_global.h \
+
+ COMPAT_LINK_CMDS += $(LN_S) xmlrpc-c/client.h xmlrpc_client.h;
ifeq ($(ENABLE_CPLUSPLUS),yes)
- HEADERS_TO_INSTALL += xmlrpc-c/client.hpp xmlrpc-c/client_simple.hpp
+ HEADERS_TO_INSTALL += \
+ xmlrpc-c/client.hpp \
+ xmlrpc-c/client_transport.hpp \
+ xmlrpc-c/client_simple.hpp \
+
endif
endif
ifeq ($(ENABLE_CGI_SERVER),yes)
HEADERS_TO_INSTALL += xmlrpc-c/server_cgi.h
+ COMPAT_LINK_CMDS += $(LN_S) xmlrpc-c/server_cgi.h xmlrpc_cgi.h;
endif
default: all
all:
+.PHONY: install-compat-hdr
+install-compat-hdr:
+# Install old names of header files for backward compatibility
+ cd $(DESTDIR)$(HEADERINST_DIR); \
+ rm -f xmlrpc.h xmlrpc_client.h xmlrpc_server.h xmlrpc_cgi.h \
+ xmlrpc_server_abyss.h xmlrpc_server_w32httpsys.h \
+ XmlRpcCpp.h; \
+ $(COMPAT_LINK_CMDS)
+
.PHONY: install
-install: install-common
+install: install-common install-compat-hdr
.PHONY: clean distclean dep
clean:
distclean:
+ rm -f xmlrpc-c/config.h
+
+.PHONY: check
+check:
+
+.PHONY: dep
dep:
-include $(SRCDIR)/Makefile.common
+OMIT_CONFIG_H_RULE = Y
+
+include $(SRCDIR)/common.mk
Modified: freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/abyss.h
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/abyss.h (original)
+++ freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/abyss.h Fri May 23 16:56:24 2008
@@ -11,711 +11,504 @@
Copyright information is at the end of the file.
****************************************************************************/
-#ifndef _ABYSS_H_
-#define _ABYSS_H_
+#ifndef XMLRPC_ABYSS_H_INCLUDED
+#define XMLRPC_ABYSS_H_INCLUDED
#ifdef __cplusplus
extern "C" {
#endif
-#ifdef ABYSS_WIN32
-#include "xmlrpc_config.h"
-#else
-#include <inttypes.h>
-#endif
-/*********************************************************************
-** Paths and so on...
-*********************************************************************/
-
-#ifdef ABYSS_WIN32
-#define DEFAULT_ROOT "c:\\abyss"
-#define DEFAULT_DOCS DEFAULT_ROOT"\\htdocs"
-#define DEFAULT_CONF_FILE DEFAULT_ROOT"\\conf\\abyss.conf"
-#define DEFAULT_LOG_FILE DEFAULT_ROOT"\\log\\abyss.log"
-#else
-#ifdef __rtems__
-#define DEFAULT_ROOT "/abyss"
-#else
-#define DEFAULT_ROOT "/usr/local/abyss"
-#endif
-#define DEFAULT_DOCS DEFAULT_ROOT"/htdocs"
-#define DEFAULT_CONF_FILE DEFAULT_ROOT"/conf/abyss.conf"
-#define DEFAULT_LOG_FILE DEFAULT_ROOT"/log/abyss.log"
-#endif
-
-/*********************************************************************
-** Maximum numer of simultaneous connections
-*********************************************************************/
-
-#define MAX_CONN 4000
-
-/*********************************************************************
-** Server Info Definitions
-*********************************************************************/
-
-#define SERVER_VERSION "0.3"
-#define SERVER_HVERSION "ABYSS/0.3"
-#define SERVER_HTML_INFO \
- "<p><HR><b><i><a href=\"http:\057\057abyss.linuxave.net\">" \
- "ABYSS Web Server</a></i></b> version "SERVER_VERSION"<br>" \
- "© <a href=\"mailto:mmoez at bigfoot.com\">Moez Mahfoudh</a> - 2000</p>"
-#define SERVER_PLAIN_INFO \
- CRLF "----------------------------------------" \
- "----------------------------------------" \
- CRLF "ABYSS Web Server version "SERVER_VERSION CRLF"(C) Moez Mahfoudh - 2000"
-
-/*********************************************************************
-** General purpose definitions
-*********************************************************************/
-
-#ifdef ABYSS_WIN32
-#define strcasecmp(a,b) stricmp((a),(b))
-#else
-#define ioctlsocket(a,b,c) ioctl((a),(b),(c))
-#endif /* ABYSS_WIN32 */
-
-#ifndef NULL
-#define NULL ((void *)0)
-#endif /* NULL */
+#include <sys/types.h>
-#ifndef TRUE
-#define TRUE 1
-#endif /* TRUE */
+#include <xmlrpc-c/inttypes.h>
-#ifndef FALSE
-#define FALSE 0
-#endif /* FALSE */
-
-#ifdef ABYSS_WIN32
-#define LBR "\n"
-#else
-#define LBR "\n"
-#endif /* ABYSS_WIN32 */
+/****************************************************************************
+ STUFF FOR THE OUTER CONTROL PROGRAM TO USE
+****************************************************************************/
typedef int abyss_bool;
-/*********************************************************************
-** Buffer
-*********************************************************************/
-
-typedef struct
-{
- void *data;
- uint32_t size;
- uint32_t staticid;
-} TBuffer;
-
-abyss_bool BufferAlloc(TBuffer *buf,uint32_t memsize);
-abyss_bool BufferRealloc(TBuffer *buf,uint32_t memsize);
-void BufferFree(TBuffer *buf);
-
-
-/*********************************************************************
-** String
-*********************************************************************/
+/****************************************************************************
+ GLOBAL (STATIC) PROGRAM STUFF
+****************************************************************************/
-typedef struct
-{
- TBuffer buffer;
- uint32_t size;
-} TString;
-
-abyss_bool StringAlloc(TString *s);
-abyss_bool StringConcat(TString *s,char *s2);
-abyss_bool StringBlockConcat(TString *s,char *s2,char **ref);
-void StringFree(TString *s);
-char *StringData(TString *s);
+void
+AbyssInit(const char ** const errorP);
+void
+AbyssTerm(void);
/*********************************************************************
-** List
+** MIMEType
*********************************************************************/
-typedef struct {
- void **item;
- uint16_t size;
- uint16_t maxsize;
- abyss_bool autofree;
-} TList;
+typedef struct MIMEType MIMEType;
-void
-ListInit(TList * const listP);
+MIMEType *
+MIMETypeCreate(void);
void
-ListInitAutoFree(TList * const listP);
+MIMETypeDestroy(MIMEType * const MIMETypeP);
void
-ListFree(TList * const listP);
+MIMETypeInit(void);
void
-ListFreeItems(TList * const listP);
+MIMETypeTerm(void);
abyss_bool
-ListAdd(TList * const listP,
- void * const str);
-
-void
-ListRemove(TList * const listP);
-
-abyss_bool
-ListAddFromString(TList * const listP,
- char * const c);
+MIMETypeAdd2(MIMEType * const MIMETypeP,
+ const char * const type,
+ const char * const ext);
abyss_bool
-ListFindString(TList * const listP,
- char * const str,
- uint16_t * const indexP);
+MIMETypeAdd(const char * const type,
+ const char * const ext);
-/*********************************************************************
-** Table
-*********************************************************************/
-
-typedef struct
-{
- char *name,*value;
- uint16_t hash;
-} TTableItem;
-
-typedef struct
-{
- TTableItem *item;
- uint16_t size,maxsize;
-} TTable;
-
-void TableInit(TTable *t);
-void TableFree(TTable *t);
-abyss_bool TableAdd(TTable *t,char *name,char *value);
-abyss_bool TableAddReplace(TTable *t,char *name,char *value);
-abyss_bool TableFindIndex(TTable *t,char *name,uint16_t *index);
-char *TableFind(TTable *t,char *name);
+enum abyss_foreback {ABYSS_FOREGROUND, ABYSS_BACKGROUND};
+#define HAVE_CHANSWITCH
-/*********************************************************************
-** Thread
-*********************************************************************/
+typedef struct _TChanSwitch TChanSwitch;
+typedef struct _TChannel TChannel;
+typedef struct _TSocket TSocket;
-#ifdef ABYSS_WIN32
-#include <windows.h>
-#define THREAD_ENTRYTYPE WINAPI
-#else
-#define THREAD_ENTRYTYPE
-#include <pthread.h>
-#endif /* ABYSS_WIN32 */
-
-typedef uint32_t (THREAD_ENTRYTYPE *TThreadProc)(void *);
-#ifdef ABYSS_WIN32
-typedef HANDLE TThread;
+#ifdef WIN32
+ #include <xmlrpc-c/abyss_winsock.h>
#else
-typedef pthread_t TThread;
-typedef void* (*PTHREAD_START_ROUTINE)(void *);
-#endif /* ABYSS_WIN32 */
-
-abyss_bool ThreadCreate(TThread *t,TThreadProc func,void *arg);
-abyss_bool ThreadRun(TThread *t);
-abyss_bool ThreadStop(TThread *t);
-abyss_bool ThreadKill(TThread *t);
-void ThreadWait(uint32_t ms);
-void ThreadExit( TThread *t, int ret_value );
-void ThreadClose( TThread *t );
+ #include <xmlrpc-c/abyss_unixsock.h>
+#endif
-/*********************************************************************
-** Mutex
-*********************************************************************/
+void
+ChanSwitchInit(const char ** const errorP);
-#ifdef ABYSS_WIN32
-typedef HANDLE TMutex;
-#else
-typedef pthread_mutex_t TMutex;
-#endif /* ABYSS_WIN32 */
+void
+ChanSwitchTerm(void);
-abyss_bool MutexCreate(TMutex *m);
-abyss_bool MutexLock(TMutex *m);
-abyss_bool MutexUnlock(TMutex *m);
-abyss_bool MutexTryLock(TMutex *m);
-void MutexFree(TMutex *m);
+/* If you're wondering where the constructors for TChanSwitch,
+ TChannel, and TSocket are: They're implementation-specific, so look
+ in abyss_unixsock.h, etc.
+*/
+void
+ChanSwitchDestroy(TChanSwitch * const chanSwitchP);
-/*********************************************************************
-** Pool
-*********************************************************************/
+void
+ChannelInit(const char ** const errorP);
-typedef struct _TPoolZone
-{
- char *pos,*maxpos;
- struct _TPoolZone *next,*prev;
-/* char data[0]; */
- char data[1];
-} TPoolZone;
-
-typedef struct
-{
- TPoolZone *firstzone,*currentzone;
- uint32_t zonesize;
- TMutex mutex;
-} TPool;
+void
+ChannelTerm(void);
-abyss_bool PoolCreate(TPool *p,uint32_t zonesize);
-void PoolFree(TPool *p);
+void
+ChannelDestroy(TChannel * const channelP);
-void *PoolAlloc(TPool *p,uint32_t size);
-char *PoolStrdup(TPool *p,char *s);
+void
+SocketDestroy(TSocket * const socketP);
-/*********************************************************************
-** Socket
-*********************************************************************/
+typedef struct {
+ /* Before Xmlrpc-c 1.04, the internal server representation,
+ struct _TServer, was exposed to users and was the only way to
+ set certain parameters of the server. Now, use the (new)
+ ServerSet...() functions. Use the HAVE_ macros to determine
+ which method you have to use.
+ */
+ struct _TServer * srvP;
+} TServer;
-#ifdef ABYSS_WIN32
-#include <winsock.h>
-#else
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <netdb.h>
-#include <arpa/inet.h>
-#include <errno.h>
-#include <unistd.h>
+typedef struct _TSession TSession;
-#ifdef HAVE_SYS_FILIO_H
-#include <sys/filio.h>
-#endif
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-
-#endif /* ABYSS_WIN32 */
+abyss_bool
+ServerCreate(TServer * const serverP,
+ const char * const name,
+ xmlrpc_uint16_t const port,
+ const char * const filespath,
+ const char * const logfilename);
-#define TIME_INFINITE 0xffffffff
+void
+ServerCreateSwitch(TServer * const serverP,
+ TChanSwitch * const chanSwitchP,
+ const char ** const errorP);
-#ifdef ABYSS_WIN32
-typedef SOCKET TSocket;
-#else
-typedef uint32_t TSocket;
-#endif /* ABYSS_WIN32 */
+abyss_bool
+ServerCreateSocket(TServer * const serverP,
+ const char * const name,
+ TOsSocket const socketFd,
+ const char * const filespath,
+ const char * const logfilename);
-typedef struct in_addr TIPAddr;
+#define HAVE_SERVER_CREATE_SOCKET_2
+void
+ServerCreateSocket2(TServer * const serverP,
+ TSocket * const socketP,
+ const char ** const errorP);
-#define IPB1(x) (((unsigned char *)(&x))[0])
-#define IPB2(x) (((unsigned char *)(&x))[1])
-#define IPB3(x) (((unsigned char *)(&x))[2])
-#define IPB4(x) (((unsigned char *)(&x))[3])
+abyss_bool
+ServerCreateNoAccept(TServer * const serverP,
+ const char * const name,
+ const char * const filespath,
+ const char * const logfilename);
-abyss_bool SocketInit(void);
+void
+ServerFree(TServer * const serverP);
-abyss_bool SocketCreate(TSocket *s);
-abyss_bool SocketClose(TSocket *s);
+void
+ServerSetName(TServer * const serverP,
+ const char * const name);
-int SocketWrite(TSocket *s, char *buffer, uint32_t len);
-uint32_t SocketRead(TSocket *s, char *buffer, uint32_t len);
-uint32_t SocketPeek(TSocket *s, char *buffer, uint32_t len);
+void
+ServerSetFilesPath(TServer * const serverP,
+ const char * const filesPath);
-abyss_bool SocketConnect(TSocket *s, TIPAddr *addr, uint16_t port);
-abyss_bool SocketBind(TSocket *s, TIPAddr *addr, uint16_t port);
+void
+ServerSetLogFileName(TServer * const serverP,
+ const char * const logFileName);
-abyss_bool SocketListen(TSocket *s, uint32_t backlog);
-abyss_bool SocketAccept(TSocket *s, TSocket *ns,TIPAddr *ip);
+#define HAVE_SERVER_SET_KEEPALIVE_TIMEOUT 1
+void
+ServerSetKeepaliveTimeout(TServer * const serverP,
+ xmlrpc_uint32_t const keepaliveTimeout);
-uint32_t SocketError(void);
+#define HAVE_SERVER_SET_KEEPALIVE_MAX_CONN 1
+void
+ServerSetKeepaliveMaxConn(TServer * const serverP,
+ xmlrpc_uint32_t const keepaliveMaxConn);
-uint32_t SocketWait(TSocket *s,abyss_bool rd,abyss_bool wr,uint32_t timems);
+#define HAVE_SERVER_SET_TIMEOUT 1
+void
+ServerSetTimeout(TServer * const serverP,
+ xmlrpc_uint32_t const timeout);
-abyss_bool SocketBlocking(TSocket *s, abyss_bool b);
-uint32_t SocketAvailableReadBytes(TSocket *s);
+#define HAVE_SERVER_SET_ADVERTISE 1
+void
+ServerSetAdvertise(TServer * const serverP,
+ abyss_bool const advertise);
+#define HAVE_SERVER_SET_MIME_TYPE 1
+void
+ServerSetMimeType(TServer * const serverP,
+ MIMEType * const MIMETypeP);
-/*********************************************************************
-** File
-*********************************************************************/
+void
+ServerInit(TServer * const serverP);
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <limits.h>
+void
+ServerRun(TServer * const serverP);
-#ifndef NAME_MAX
-#define NAME_MAX 1024
-#endif
+void
+ServerRunOnce(TServer * const serverP);
-#ifdef ABYSS_WIN32
-#ifndef __BORLANDC__
-#define O_APPEND _O_APPEND
-#define O_CREAT _O_CREAT
-#define O_EXCL _O_EXCL
-#define O_RDONLY _O_RDONLY
-#define O_RDWR _O_RDWR
-#define O_TRUNC _O_TRUNC
-#define O_WRONLY _O_WRONLY
-#define O_TEXT _O_TEXT
-#define O_BINARY _O_BINARY
-#endif
+/* ServerRunOnce2() is obsolete. See user's guide. */
+void
+ServerRunOnce2(TServer * const serverP,
+ enum abyss_foreback const foregroundBackground);
-#define A_HIDDEN _A_HIDDEN
-#define A_NORMAL _A_NORMAL
-#define A_RDONLY _A_RDONLY
-#define A_SUBDIR _A_SUBDIR
-#else
-#define A_SUBDIR 1
-#define O_BINARY 0
-#define O_TEXT 0
-#endif /* ABYSS_WIN32 */
-
-#ifdef ABYSS_WIN32
-
-#ifndef __BORLANDC__
-typedef struct _stati64 TFileStat;
-typedef struct _finddata_t TFileInfo;
-typedef long TFileFind;
+void
+ServerRunChannel(TServer * const serverP,
+ TChannel * const channelP,
+ void * const channelInfoP,
+ const char ** const errorP);
-#else
+#define HAVE_SERVER_RUN_CONN_2
+void
+ServerRunConn2(TServer * const serverP,
+ TSocket * const connectedSocketP,
+ const char ** const errorP);
-typedef struct stat TFileStat;
-typedef struct finddata_t
-{
- char name[NAME_MAX+1];
- int attrib;
- uint64_t size;
- time_t time_write;
- WIN32_FIND_DATA data;
-} TFileInfo;
-typedef HANDLE TFileFind;
-#endif
+void
+ServerRunConn(TServer * const serverP,
+ TOsSocket const connectedSocket);
-#else
+void
+ServerDaemonize(TServer * const serverP);
-#include <unistd.h>
-#include <dirent.h>
+void
+ServerTerminate(TServer * const serverP);
-typedef struct stat TFileStat;
+void
+ServerResetTerminate(TServer * const serverP);
-typedef struct finddata_t
-{
- char name[NAME_MAX+1];
- int attrib;
- uint64_t size;
- time_t time_write;
-} TFileInfo;
-
-typedef struct
-{
- char path[NAME_MAX+1];
- DIR *handle;
-} TFileFind;
+void
+ServerUseSigchld(TServer * const serverP);
+#ifndef WIN32
+void
+ServerHandleSigchld(pid_t const pid);
#endif
-typedef int TFile;
-
-abyss_bool FileOpen(TFile *f, const char *name,uint32_t attrib);
-abyss_bool FileOpenCreate(TFile *f, const char *name, uint32_t attrib);
-abyss_bool FileClose(TFile *f);
+typedef abyss_bool (*URIHandler) (TSession *); /* deprecated */
-abyss_bool FileWrite(TFile *f, void *buffer, uint32_t len);
-int32_t FileRead(TFile *f, void *buffer, uint32_t len);
+struct URIHandler2;
-abyss_bool FileSeek(TFile *f, uint64_t pos, uint32_t attrib);
-uint64_t FileSize(TFile *f);
+typedef void (*initHandlerFn)(struct URIHandler2 *,
+ abyss_bool *);
-abyss_bool FileStat(char *filename,TFileStat *filestat);
+typedef void (*termHandlerFn)(void *);
-abyss_bool FileFindFirst(TFileFind *filefind,char *path,TFileInfo *fileinfo);
-abyss_bool FileFindNext(TFileFind *filefind,TFileInfo *fileinfo);
-void FileFindClose(TFileFind *filefind);
+typedef void (*handleReq2Fn)(struct URIHandler2 *,
+ TSession *,
+ abyss_bool *);
-/*********************************************************************
-** Server (1/2)
-*********************************************************************/
+typedef struct URIHandler2 {
+ initHandlerFn init;
+ termHandlerFn term;
+ handleReq2Fn handleReq2;
+ URIHandler handleReq1; /* deprecated */
+ void * userdata;
+} URIHandler2;
-typedef struct _TServer
-{
- TSocket listensock;
- TFile logfile;
- TMutex logmutex;
- char *name;
- char *filespath;
- uint16_t port;
- uint32_t keepalivetimeout,keepalivemaxconn,timeout;
- TList handlers;
- TList defaultfilenames;
- void *defaulthandler;
- abyss_bool advertise;
- int running;
-#ifndef _WIN32
- uid_t uid;
- gid_t gid;
- TFile pidfile;
-#endif
-} TServer;
+void
+ServerAddHandler2(TServer * const srvP,
+ URIHandler2 * const handlerP,
+ abyss_bool * const successP);
+abyss_bool
+ServerAddHandler(TServer * const srvP,
+ URIHandler const handler);
-/*********************************************************************
-** Conn
-*********************************************************************/
+typedef abyss_bool (*THandlerDflt) (TSession *);
-#define BUFFER_SIZE 4096
+/* Note: 'handler' used to be URIHandler; THandlerDflt is a newer name
+ for the same type
+*/
-typedef struct _TConn
-{
- TServer *server;
- uint32_t buffersize,bufferpos;
- uint32_t inbytes,outbytes;
- TSocket socket;
- TIPAddr peerip;
- abyss_bool hasOwnThread;
- TThread thread;
- abyss_bool connected;
- abyss_bool inUse;
- const char * trace;
- void (*job)(struct _TConn *);
- char buffer[BUFFER_SIZE];
-} TConn;
+void
+ServerDefaultHandler(TServer * const srvP,
+ THandlerDflt const handler);
-TConn *ConnAlloc(void);
-void ConnFree(TConn *c);
+/* ConfReadServerFile() is inappropriately named; it was a mistake.
+ But then, so is having this function at all. The config file is
+ inappropriate for an API.
+*/
-enum abyss_foreback {ABYSS_FOREGROUND, ABYSS_BACKGROUND};
+abyss_bool
+ConfReadServerFile(const char * const filename,
+ TServer * const srvP);
-abyss_bool ConnCreate(TConn *c, TSocket *s, void (*func)(TConn *));
-abyss_bool ConnCreate2(TConn * const connectionP,
- TServer * const serverP,
- TSocket const connectedSocket,
- TIPAddr const peerIpAddr,
- void ( * func)(TConn *),
- enum abyss_foreback const foregroundBackground);
-abyss_bool ConnProcess(TConn *c);
-abyss_bool ConnKill(TConn *c);
-void ConnClose(TConn *c);
-
-abyss_bool ConnWrite(TConn *c,void *buffer,uint32_t size);
-abyss_bool ConnRead(TConn *c, uint32_t timems);
-void ConnReadInit(TConn *c);
-abyss_bool ConnReadLine(TConn *c,char **z,uint32_t timems);
+void
+LogWrite(TServer * const srvP,
+ const char * const c);
-abyss_bool ConnWriteFromFile(TConn *c,TFile *file,uint64_t start,uint64_t end,
- void *buffer,uint32_t buffersize,uint32_t rate);
+/****************************************************************************
+ STUFF FOR HTTP REQUEST HANDLERS TO USE
+****************************************************************************/
+typedef enum {
+ m_unknown, m_get, m_put, m_head, m_post, m_delete, m_trace, m_options
+} TMethod;
-/*********************************************************************
-** Range
-*********************************************************************/
+typedef struct {
+ TMethod method;
+ const char * uri;
+ /* This is NOT the URI. It is the pathname part of the URI.
+ We really should fix that and put the pathname in another
+ member. If the URI does not contain a pathname, this is "*".
+ */
+ const char * query;
+ /* The query part of the URI (stuff after '?'). NULL if none. */
+ const char * host;
+ /* NOT the value of the host: header. Rather, the name of the
+ target host (could be part of the host: value; could be from the
+ URI). No port number. NULL if request does not specify a host
+ name.
+ */
+ const char * from;
+ const char * useragent;
+ const char * referer;
+ const char * requestline;
+ const char * user;
+ /* Requesting user (from authorization: header). NULL if
+ request doesn't specify or handler has not authenticated it.
+ */
+ xmlrpc_uint16_t port;
+ /* The port number from the URI, or default 80 if the URI doesn't
+ specify a port.
+ */
+ abyss_bool keepalive;
+} TRequestInfo;
-abyss_bool RangeDecode(char *str,uint64_t filesize,uint64_t *start,uint64_t *end);
+abyss_bool
+SessionRefillBuffer(TSession * const sessionP);
-/*********************************************************************
-** Date
-*********************************************************************/
+size_t
+SessionReadDataAvail(TSession * const sessionP);
-#include <time.h>
+void
+SessionGetReadData(TSession * const sessionP,
+ size_t const max,
+ const char ** const outStartP,
+ size_t * const outLenP);
-typedef struct tm TDate;
+void
+SessionGetRequestInfo(TSession * const sessionP,
+ const TRequestInfo ** const requestInfoPP);
-abyss_bool DateToString(TDate *tm,char *s);
-abyss_bool DateToLogString(TDate *tm,char *s);
+void
+SessionGetChannelInfo(TSession * const sessionP,
+ void ** const channelInfoPP);
-abyss_bool DateDecode(char *s,TDate *tm);
+void *
+SessionGetDefaultHandlerCtx(TSession * const sessionP);
-int32_t DateCompare(TDate *d1,TDate *d2);
+char *
+RequestHeaderValue(TSession * const sessionP,
+ const char * const name);
-abyss_bool DateFromGMT(TDate *d,time_t t);
-abyss_bool DateFromLocal(TDate *d,time_t t);
+abyss_bool
+ResponseAddField(TSession * const sessionP,
+ const char * const name,
+ const char * const value);
-abyss_bool DateInit(void);
+void
+ResponseWriteStart(TSession * const sessionP);
-/*********************************************************************
-** Base64
-*********************************************************************/
+/* For backward compatibility: */
+#define ResponseWrite ResponseWriteStart
-void Base64Encode(char *s,char *d);
+abyss_bool
+ResponseWriteBody(TSession * const sessionP,
+ const char * const data,
+ xmlrpc_uint32_t const len);
-/*********************************************************************
-** Session
-*********************************************************************/
+abyss_bool
+ResponseWriteEnd(TSession * const sessionP);
-typedef enum
-{
- m_unknown,m_get,m_put,m_head,m_post,m_delete,m_trace,m_options
-} TMethod;
+abyss_bool
+ResponseChunked(TSession * const sessionP);
-typedef struct
-{
- TMethod method;
- uint32_t nbfileds;
- char *uri;
- char *query;
- char *host;
- char *from;
- char *useragent;
- char *referer;
- char *requestline;
- char *user;
- uint16_t port;
- TList cookies;
- TList ranges;
-
- uint16_t status;
- TString header;
-
- abyss_bool keepalive,cankeepalive;
- abyss_bool done;
-
- TServer *server;
- TConn *conn;
+xmlrpc_uint16_t
+ResponseStatusFromErrno(int const errnoArg);
- uint8_t versionminor,versionmajor;
+void
+ResponseStatus(TSession * const sessionP,
+ xmlrpc_uint16_t const code);
- TTable request_headers,response_headers;
+void
+ResponseStatusErrno(TSession * const sessionP);
- TDate date;
+abyss_bool
+ResponseContentType(TSession * const serverP,
+ const char * const type);
- abyss_bool chunkedwrite,chunkedwritemode;
-} TSession;
+abyss_bool
+ResponseContentLength(TSession * const sessionP,
+ xmlrpc_uint64_t const len);
-/*********************************************************************
-** Request
-*********************************************************************/
+void
+ResponseError2(TSession * const sessionP,
+ const char * const explanation);
-#define CR '\r'
-#define LF '\n'
-#define CRLF "\r\n"
+void
+ResponseError(TSession * const sessionP);
-abyss_bool RequestValidURI(TSession *r);
-abyss_bool RequestValidURIPath(TSession *r);
-abyss_bool RequestUnescapeURI(TSession *r);
+const char *
+MIMETypeFromExt(const char * const ext);
-char *RequestHeaderValue(TSession *r,char *name);
+const char *
+MIMETypeFromExt2(MIMEType * const MIMETypeP,
+ const char * const ext);
-abyss_bool RequestRead(TSession *r);
-void RequestInit(TSession *r,TConn *c);
-void RequestFree(TSession *r);
+const char *
+MIMETypeFromFileName2(MIMEType * const MIMETypeP,
+ const char * const fileName);
-abyss_bool RequestAuth(TSession *r,char *credential,char *user,char *pass);
+const char *
+MIMETypeFromFileName(const char * const fileName);
-/*********************************************************************
-** Response
-*********************************************************************/
+const char *
+MIMETypeGuessFromFile2(MIMEType * const MIMETypeP,
+ const char * const fileName);
-abyss_bool ResponseAddField(TSession *r,char *name,char *value);
-void ResponseWrite(TSession *r);
+const char *
+MIMETypeGuessFromFile(const char * const filename);
-abyss_bool ResponseChunked(TSession *s);
-void ResponseStatus(TSession *r,uint16_t code);
-void ResponseStatusErrno(TSession *r);
+/****************************************************************************
+ STUFF THAT PROBABLY DOESN'T BELONG IN THIS FILE BECAUSE IT IS INTERNAL
-abyss_bool ResponseContentType(TSession *r,char *type);
-abyss_bool ResponseContentLength(TSession *r,uint64_t len);
+ Some day, we sort this out.
+****************************************************************************/
-void ResponseError(TSession *r);
+#define CR '\r'
+#define LF '\n'
+#define CRLF "\r\n"
/*********************************************************************
-** HTTP
+** Paths and so on...
*********************************************************************/
-char *HTTPReasonByStatus(uint16_t status);
-
-int32_t HTTPRead(TSession *s,char *buffer,uint32_t len);
-
-abyss_bool HTTPWrite(TSession *s,char *buffer,uint32_t len);
-abyss_bool HTTPWriteEnd(TSession *s);
+#ifdef WIN32
+#define DEFAULT_ROOT "c:\\abyss"
+#define DEFAULT_DOCS DEFAULT_ROOT"\\htdocs"
+#define DEFAULT_CONF_FILE DEFAULT_ROOT"\\conf\\abyss.conf"
+#define DEFAULT_LOG_FILE DEFAULT_ROOT"\\log\\abyss.log"
+#else
+#ifdef __rtems__
+#define DEFAULT_ROOT "/abyss"
+#else
+#define DEFAULT_ROOT "/usr/local/abyss"
+#endif
+#define DEFAULT_DOCS DEFAULT_ROOT"/htdocs"
+#define DEFAULT_CONF_FILE DEFAULT_ROOT"/conf/abyss.conf"
+#define DEFAULT_LOG_FILE DEFAULT_ROOT"/log/abyss.log"
+#endif
/*********************************************************************
-** Server (2/2)
+** Maximum number of simultaneous connections
*********************************************************************/
-abyss_bool ServerCreate(TServer *srv,
- const char *name,
- uint16_t port,
- const char *filespath,
- const char *logfilename);
-
-void ServerFree(TServer *srv);
-
-int ServerInit(TServer *srv);
-void ServerRun(TServer *srv);
-void ServerRunOnce(TServer *srv);
-void ServerRunOnce2(TServer * const srv,
- enum abyss_foreback const foregroundBackground);
-
-typedef abyss_bool (*URIHandler) (TSession *); /* deprecated */
-
-struct URIHandler2;
-
-typedef void (*initHandlerFn)(struct URIHandler2 *,
- abyss_bool *);
-
-typedef void (*termHandlerFn)(struct URIHandler2 *);
-
-typedef void (*handleReq2Fn)(struct URIHandler2 *,
- TSession *,
- abyss_bool *);
-
-typedef struct URIHandler2 {
- initHandlerFn init;
- termHandlerFn term;
- handleReq2Fn handleReq2;
- URIHandler handleReq1; /* deprecated */
- void * userdata;
-} URIHandler2;
-
-void
-ServerAddHandler2(TServer * const srvP,
- URIHandler2 * const handlerP,
- abyss_bool * const successP);
-
-abyss_bool
-ServerAddHandler(TServer * const srvP,
- URIHandler const handler);
-
-void
-ServerDefaultHandler(TServer * const srvP,
- URIHandler const handler);
-
-abyss_bool LogOpen(TServer *srv, const char *filename);
-void LogWrite(TServer *srv,char *c);
-void LogClose(TServer *srv);
-
+#define MAX_CONN 16
/*********************************************************************
-** MIMEType
+** General purpose definitions
*********************************************************************/
-void MIMETypeInit(void);
-abyss_bool MIMETypeAdd(char *type,char *ext);
-char *MIMETypeFromExt(char *ext);
-char *MIMETypeFromFileName(char *filename);
-char *MIMETypeGuessFromFile(char *filename);
+#ifndef NULL
+#define NULL ((void *)0)
+#endif /* NULL */
+
+#ifndef TRUE
+#define TRUE 1
+#endif /* TRUE */
+#ifndef FALSE
+#define FALSE 0
+#endif /* FALSE */
/*********************************************************************
-** Conf
+** Range
*********************************************************************/
-abyss_bool ConfReadMIMETypes(char *filename);
-abyss_bool ConfReadServerFile(const char *filename,TServer *srv);
+abyss_bool
+RangeDecode(char * const str,
+ xmlrpc_uint64_t const filesize,
+ xmlrpc_uint64_t * const start,
+ xmlrpc_uint64_t * const end);
+abyss_bool DateInit(void);
/*********************************************************************
-** Trace
+** Base64
*********************************************************************/
-void TraceMsg(char *fmt,...);
-void TraceExit(char *fmt,...);
-
+void
+Base64Encode(const char * const chars,
+ char * const base64);
/*********************************************************************
** Session
*********************************************************************/
-abyss_bool SessionLog(TSession *s);
+abyss_bool SessionLog(TSession * const s);
#ifdef __cplusplus
}
+
+
#endif
/*****************************************************************************
Added: freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/abyss_opensslsock.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/abyss_opensslsock.h Fri May 23 16:56:24 2008
@@ -0,0 +1,28 @@
+/* This is just a sub-file for abyss.h */
+
+#include <sys/socket.h>
+
+struct abyss_openssl_chaninfo {
+ /* TODO: figure out useful information to put in here.
+ Maybe client IP address and port. Maybe authenticated host name.
+ Maybe authentication level.
+ Maybe a certificate.
+ */
+ int dummy;
+};
+
+void
+ChanSwitchOpensslCreate(unsigned short const portNumber,
+ TChanSwitch ** const chanSwitchPP,
+ const char ** const errorP);
+
+void
+ChanSwitchOpensslCreateFd(int const fd,
+ TChanSwitch ** const chanSwitchPP,
+ const char ** const errorP);
+
+void
+ChannelOpensslCreateSsl(SSL * const sslP,
+ TChannel ** const channelPP,
+ struct abyss_openssl_chaninfo ** const channelInfoPP,
+ const char ** const errorP);
Added: freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/abyss_unixsock.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/abyss_unixsock.h Fri May 23 16:56:24 2008
@@ -0,0 +1,42 @@
+/* This is just a sub-file for abyss.h */
+
+#include <sys/socket.h>
+
+struct abyss_unix_chaninfo {
+ size_t peerAddrLen;
+ struct sockaddr peerAddr;
+};
+
+void
+ChanSwitchUnixCreate(unsigned short const portNumber,
+ TChanSwitch ** const chanSwitchPP,
+ const char ** const errorP);
+
+void
+ChanSwitchUnixCreateFd(int const fd,
+ TChanSwitch ** const chanSwitchPP,
+ const char ** const errorP);
+
+void
+ChannelUnixCreateFd(int const fd,
+ TChannel ** const channelPP,
+ struct abyss_unix_chaninfo ** const channelInfoPP,
+ const char ** const errorP);
+
+void
+ChannelUnixGetPeerName(TChannel * const channelP,
+ struct sockaddr ** const sockaddrPP,
+ size_t * const sockaddrLenP,
+ const char ** const errorP);
+
+void
+SocketUnixCreateFd(int const fd,
+ TSocket ** const socketPP);
+
+typedef int TOsSocket;
+ /* TOsSocket is the type of a conventional socket offered by our OS.
+ This is for backward compatibility; everyone should use TChanSwitch
+ and TChannel instead today.
+ */
+
+
Added: freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/abyss_winsock.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/abyss_winsock.h Fri May 23 16:56:24 2008
@@ -0,0 +1,27 @@
+/* This is just a sub-file for abyss.h */
+
+#include <winsock.h>
+
+struct abyss_win_chaninfo {
+ size_t peerAddrLen;
+ struct sockaddr peerAddr;
+};
+
+
+void
+ChanSwitchWinCreate(unsigned short const portNumber,
+ TChanSwitch ** const chanSwitchPP,
+ const char ** const errorP);
+
+void
+ChanSwitchWinCreateWinsock(SOCKET const winsock,
+ TChanSwitch ** const chanSwitchPP,
+ const char ** const errorP);
+
+void
+ChannelWinCreateWinsock(SOCKET const fd,
+ TChannel ** const channelPP,
+ struct abyss_win_chaninfo ** const channelInfoPP,
+ const char ** const errorP);
+
+typedef SOCKET TOsSocket;
Modified: freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/base.h
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/base.h (original)
+++ freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/base.h Fri May 23 16:56:24 2008
@@ -6,8 +6,11 @@
#include <stddef.h>
#include <stdarg.h>
#include <time.h>
+#include <xmlrpc-c/util.h>
+#include <xmlrpc-c/config.h>
+ /* Defines XMLRPC_HAVE_WCHAR, XMLRPC_INT64 */
-#ifdef HAVE_UNICODE_WCHAR
+#if XMLRPC_HAVE_WCHAR
#include <wchar.h>
#endif
@@ -17,16 +20,26 @@
/*=========================================================================
-** Typedefs
-**=========================================================================
-** We define names for these types, because they may change from platform
-** to platform.
+** Version of libxmlrpc
+**=======================================================================*/
+extern unsigned int const xmlrpc_version_major;
+extern unsigned int const xmlrpc_version_minor;
+extern unsigned int const xmlrpc_version_point;
+
+/*=========================================================================
+** C types equivalent to XML-RPC types
+**=======================================================================*/
+
+/* We define names for these types, because they may change from platform
+ to platform.
*/
typedef signed int xmlrpc_int;
/* An integer of the type defined by XML-RPC <int>; i.e. 32 bit */
-typedef signed int xmlrpc_int32;
- /* An integer of the type defined by XML-RPC <int4>; i.e. 32 bit */
+typedef XMLRPC_INT32 xmlrpc_int32;
+ /* An integer of the type defined by XML-RPC <i4>; i.e. 32 bit */
+typedef XMLRPC_INT64 xmlrpc_int64;
+ /* An integer of the type defined by "XML-RPC" <i8>; i.e. 64 bit */
typedef int xmlrpc_bool;
/* A boolean (of the type defined by XML-RPC <boolean>, but there's
really only one kind)
@@ -38,296 +51,19 @@
for mathematical completeness.
*/
-#define XMLRPC_INT32_MAX (2147483647)
-#define XMLRPC_INT32_MIN (-XMLRPC_INT32_MAX - 1)
-
-
-
-/*=========================================================================
-** C struct size computations
-**=======================================================================*/
-
-/* Use XMLRPC_STRUCT_MEMBER_SIZE() to determine how big a structure is
- up to and including a specified member. E.g. if you have
- struct mystruct {int red; int green; int blue};, then
- XMLRPC_STRUCT_MEMBER_SIZE(mystruct, green) is (8).
-*/
-
-#define _XMLRPC_STRUCT_MEMBER_OFFSET(TYPE, MBRNAME) \
- ((unsigned long)(char*)&((TYPE *)0)->MBRNAME)
-#define _XMLRPC_STRUCT_MEMBER_SIZE(TYPE, MBRNAME) \
- sizeof(((TYPE *)0)->MBRNAME)
-#define XMLRPC_STRUCTSIZE(TYPE, MBRNAME) \
- (_XMLRPC_STRUCT_MEMBER_OFFSET(TYPE, MBRNAME) + \
- _XMLRPC_STRUCT_MEMBER_SIZE(TYPE, MBRNAME))
-
-/*=========================================================================
-** Assertions and Debugging
-**=========================================================================
-** Note that an assertion is _not_ a directive to check a condition and
-** crash if it isn't true. It is an assertion that the condition _is_
-** true. This assertion helps people to read the code. The program
-** may also check the assertion as it runs, and if it conflicts with reality,
-** recognize that the program is incorrect and abort it. In practice,
-** it does this checking when the program was compiled without the NDEBUG
-** macro defined.
-*/
-
-#ifndef NDEBUG
-
-#define XMLRPC_ASSERT(cond) \
- do \
- if (!(cond)) \
- xmlrpc_assertion_failed(__FILE__, __LINE__); \
- while (0)
-
-#else
-#define XMLRPC_ASSERT(cond) (0)
-#endif
-
-extern void xmlrpc_assertion_failed (char* file, int line);
-
-/* Validate a pointer. */
-#define XMLRPC_ASSERT_PTR_OK(ptr) \
- XMLRPC_ASSERT((ptr) != NULL)
-
-/* We only call this if something truly drastic happens. */
-#define XMLRPC_FATAL_ERROR(msg) xmlrpc_fatal_error(__FILE__, __LINE__, (msg))
-
-extern void xmlrpc_fatal_error (char* file, int line, char* msg);
-
-
-/*=========================================================================
-** Strings
-**=======================================================================*/
-
-/* Traditional C strings are char *, because they come from a time before
- there was 'const'. Now, const char * makes a lot more sense. Also,
- in modern times, we tend to dynamically allocate memory for strings.
- We need this free function accordingly. Ordinary free() doesn't check
- the type, and can generate a warning due to the 'const'.
+/* xmlrpc_socket is just for backward compatibility, in case someone decided
+ to use this in user code. New code should use the native type for a
+ socket (e.g. int or SOCKET). (We stopped using this because for winsock
+ users, we would have to #include <winsock.h> in every file that
+ #includes <xmlrpc-c/base.h> and we don't want that).
*/
-void
-xmlrpc_strfree(const char * const string);
-
-
+typedef int xmlrpc_socket;
-/*=========================================================================
-** xmlrpc_env
-**=========================================================================
-** XML-RPC represents runtime errors as <fault> elements. These contain
-** <faultCode> and <faultString> elements.
-**
-** Since we need as much thread-safety as possible, we borrow an idea from
-** CORBA--we store exception information in an "environment" object.
-** You'll pass this to many different functions, and it will get filled
-** out appropriately.
-**
-** For example:
-**
-** xmlrpc_env env;
-**
-** xmlrpc_env_init(&env);
-**
-** xmlrpc_do_something(&env);
-** if (env.fault_occurred)
-** report_error_appropriately();
-**
-** xmlrpc_env_clean(&env);
-*/
-
-#define XMLRPC_INTERNAL_ERROR (-500)
-#define XMLRPC_TYPE_ERROR (-501)
-#define XMLRPC_INDEX_ERROR (-502)
-#define XMLRPC_PARSE_ERROR (-503)
-#define XMLRPC_NETWORK_ERROR (-504)
-#define XMLRPC_TIMEOUT_ERROR (-505)
-#define XMLRPC_NO_SUCH_METHOD_ERROR (-506)
-#define XMLRPC_REQUEST_REFUSED_ERROR (-507)
-#define XMLRPC_INTROSPECTION_DISABLED_ERROR (-508)
-#define XMLRPC_LIMIT_EXCEEDED_ERROR (-509)
-#define XMLRPC_INVALID_UTF8_ERROR (-510)
-
-typedef struct _xmlrpc_env {
- int fault_occurred;
- xmlrpc_int32 fault_code;
- char* fault_string;
-} xmlrpc_env;
-
-/* Initialize and destroy the contents of the provided xmlrpc_env object.
-** These functions will never fail. */
-void xmlrpc_env_init (xmlrpc_env* env);
-void xmlrpc_env_clean (xmlrpc_env* env);
-
-/* Fill out an xmlrpc_fault with the specified values, and set the
-** fault_occurred flag. This function will make a private copy of 'string',
-** so you retain responsibility for your copy. */
-void
-xmlrpc_env_set_fault(xmlrpc_env * const env,
- int const faultCode,
- const char * const faultDescription);
-
-/* The same as the above, but using a printf-style format string. */
-void
-xmlrpc_env_set_fault_formatted (xmlrpc_env * const envP,
- int const code,
- const char * const format,
- ...);
-
-/* This one infers XMLRPC_INTERNAL_ERROR and has a shorter name.
- So a call takes up less source code space.
-*/
-void
-xmlrpc_faultf(xmlrpc_env * const envP,
- const char * const format,
- ...);
-
-/* A simple debugging assertion. */
-#define XMLRPC_ASSERT_ENV_OK(env) \
- XMLRPC_ASSERT((env) != NULL && !(env)->fault_occurred)
-
-/* This version must *not* interpret 'str' as a format string, to avoid
-** several evil attacks. */
-#define XMLRPC_FAIL(env,code,str) \
- do { xmlrpc_env_set_fault((env),(code),(str)); goto cleanup; } while (0)
-
-#define XMLRPC_FAIL1(env,code,str,arg1) \
- do { \
- xmlrpc_env_set_fault_formatted((env),(code),(str),(arg1)); \
- goto cleanup; \
- } while (0)
-
-#define XMLRPC_FAIL2(env,code,str,arg1,arg2) \
- do { \
- xmlrpc_env_set_fault_formatted((env),(code),(str),(arg1),(arg2)); \
- goto cleanup; \
- } while (0)
-
-#define XMLRPC_FAIL3(env,code,str,arg1,arg2,arg3) \
- do { \
- xmlrpc_env_set_fault_formatted((env),(code), \
- (str),(arg1),(arg2),(arg3)); \
- goto cleanup; \
- } while (0)
-
-#define XMLRPC_FAIL_IF_NULL(ptr,env,code,str) \
- do { \
- if ((ptr) == NULL) \
- XMLRPC_FAIL((env),(code),(str)); \
- } while (0)
-
-#define XMLRPC_FAIL_IF_FAULT(env) \
- do { if ((env)->fault_occurred) goto cleanup; } while (0)
-
-
-/*=========================================================================
-** Resource Limits
-**=========================================================================
-** To discourage denial-of-service attacks, we provide several adjustable
-** resource limits. These functions are *not* re-entrant.
-*/
-
-/* Limit IDs. There will be more of these as time goes on. */
-#define XMLRPC_NESTING_LIMIT_ID (0)
-#define XMLRPC_XML_SIZE_LIMIT_ID (1)
-#define XMLRPC_LAST_LIMIT_ID (XMLRPC_XML_SIZE_LIMIT_ID)
-
-/* By default, deserialized data may be no more than 64 levels deep. */
-#define XMLRPC_NESTING_LIMIT_DEFAULT (64)
-
-/* By default, XML data from the network may be no larger than 512K.
-** Some client and server modules may fail to enforce this properly. */
-#define XMLRPC_XML_SIZE_LIMIT_DEFAULT (512*1024)
-
-/* Set a specific limit to the specified value. */
-extern void xmlrpc_limit_set (int limit_id, size_t value);
-
-/* Get the value of a specified limit. */
-extern size_t xmlrpc_limit_get (int limit_id);
-
-
-/*=========================================================================
-** xmlrpc_mem_block
-**=========================================================================
-** A resizable chunk of memory. This is mostly used internally, but it is
-** also used by the public API in a few places.
-** The struct fields are private!
-*/
-
-typedef struct _xmlrpc_mem_block {
- size_t _size;
- size_t _allocated;
- void* _block;
-} xmlrpc_mem_block;
-
-/* Allocate a new xmlrpc_mem_block. */
-xmlrpc_mem_block* xmlrpc_mem_block_new (xmlrpc_env* env, size_t size);
-
-/* Destroy an existing xmlrpc_mem_block, and everything it contains. */
-void xmlrpc_mem_block_free (xmlrpc_mem_block* block);
-
-/* Initialize the contents of the provided xmlrpc_mem_block. */
-void xmlrpc_mem_block_init
- (xmlrpc_env* env, xmlrpc_mem_block* block, size_t size);
-
-/* Deallocate the contents of the provided xmlrpc_mem_block, but not the
-** block itself. */
-void xmlrpc_mem_block_clean (xmlrpc_mem_block* block);
-
-/* Get the size and contents of the xmlrpc_mem_block. */
-size_t
-xmlrpc_mem_block_size(const xmlrpc_mem_block * const block);
-
-void *
-xmlrpc_mem_block_contents(const xmlrpc_mem_block * const block);
-
-/* Resize an xmlrpc_mem_block, preserving as much of the contents as
-** possible. */
-void xmlrpc_mem_block_resize
- (xmlrpc_env* env, xmlrpc_mem_block* block, size_t size);
-
-/* Append data to an existing xmlrpc_mem_block. */
-void xmlrpc_mem_block_append
- (xmlrpc_env* env, xmlrpc_mem_block* block, const void *data, size_t len);
-
-#define XMLRPC_MEMBLOCK_NEW(type,env,size) \
- xmlrpc_mem_block_new((env), sizeof(type) * (size))
-#define XMLRPC_MEMBLOCK_FREE(type,block) \
- xmlrpc_mem_block_free(block)
-#define XMLRPC_MEMBLOCK_INIT(type,env,block,size) \
- xmlrpc_mem_block_init((env), (block), sizeof(type) * (size))
-#define XMLRPC_MEMBLOCK_CLEAN(type,block) \
- xmlrpc_mem_block_clean(block)
-#define XMLRPC_MEMBLOCK_SIZE(type,block) \
- (xmlrpc_mem_block_size(block) / sizeof(type))
-#define XMLRPC_MEMBLOCK_CONTENTS(type,block) \
- ((type*) xmlrpc_mem_block_contents(block))
-#define XMLRPC_MEMBLOCK_RESIZE(type,env,block,size) \
- xmlrpc_mem_block_resize(env, block, sizeof(type) * (size))
-#define XMLRPC_MEMBLOCK_APPEND(type,env,block,data,size) \
- xmlrpc_mem_block_append(env, block, data, sizeof(type) * (size))
-
-/* Here are some backward compatibility definitions. These longer names
- used to be the only ones and typed memory blocks were considered
- special.
-*/
-#define XMLRPC_TYPED_MEM_BLOCK_NEW(type,env,size) \
- XMLRPC_MEMBLOCK_NEW(type,env,size)
-#define XMLRPC_TYPED_MEM_BLOCK_FREE(type,block) \
- XMLRPC_MEMBLOCK_FREE(type,block)
-#define XMLRPC_TYPED_MEM_BLOCK_INIT(type,env,block,size) \
- XMLRPC_MEMBLOCK_INIT(type,env,block,size)
-#define XMLRPC_TYPED_MEM_BLOCK_CLEAN(type,block) \
- XMLRPC_MEMBLOCK_CLEAN(type,block)
-#define XMLRPC_TYPED_MEM_BLOCK_SIZE(type,block) \
- XMLRPC_MEMBLOCK_SIZE(type,block)
-#define XMLRPC_TYPED_MEM_BLOCK_CONTENTS(type,block) \
- XMLRPC_MEMBLOCK_CONTENTS(type,block)
-#define XMLRPC_TYPED_MEM_BLOCK_RESIZE(type,env,block,size) \
- XMLRPC_MEMBLOCK_RESIZE(type,env,block,size)
-#define XMLRPC_TYPED_MEM_BLOCK_APPEND(type,env,block,data,size) \
- XMLRPC_MEMBLOCK_APPEND(type,env,block,data,size)
+#define XMLRPC_INT32_MAX 0x7fffffff
+#define XMLRPC_INT32_MIN (-XMLRPC_INT32_MAX - 1)
+#define XMLRPC_INT64_MAX 0x7fffffffffffffffll
+#define XMLRPC_INT64_MIN (-XMLRPC_INT64_MAX - 1)
/*=========================================================================
@@ -337,22 +73,28 @@
*/
typedef enum {
- XMLRPC_TYPE_INT = 0,
- XMLRPC_TYPE_BOOL = 1,
- XMLRPC_TYPE_DOUBLE = 2,
- XMLRPC_TYPE_DATETIME = 3,
- XMLRPC_TYPE_STRING = 4,
- XMLRPC_TYPE_BASE64 = 5,
- XMLRPC_TYPE_ARRAY = 6,
- XMLRPC_TYPE_STRUCT = 7,
- XMLRPC_TYPE_C_PTR = 8,
- XMLRPC_TYPE_NIL = 9,
+ XMLRPC_TYPE_INT = 0,
+ XMLRPC_TYPE_BOOL = 1,
+ XMLRPC_TYPE_DOUBLE = 2,
+ XMLRPC_TYPE_DATETIME = 3,
+ XMLRPC_TYPE_STRING = 4,
+ XMLRPC_TYPE_BASE64 = 5,
+ XMLRPC_TYPE_ARRAY = 6,
+ XMLRPC_TYPE_STRUCT = 7,
+ XMLRPC_TYPE_C_PTR = 8,
+ XMLRPC_TYPE_NIL = 9,
+ XMLRPC_TYPE_I8 = 10,
XMLRPC_TYPE_DEAD = 0xDEAD
} xmlrpc_type;
+#define XMLRPC_HAVE_I8 1
+
/* These are *always* allocated on the heap. No exceptions. */
typedef struct _xmlrpc_value xmlrpc_value;
+const char *
+xmlrpc_type_name(xmlrpc_type const type);
+
void
xmlrpc_abort_if_array_bad(xmlrpc_value * const arrayP);
@@ -360,19 +102,23 @@
xmlrpc_abort_if_array_bad(val)
/* Increment the reference count of an xmlrpc_value. */
-extern void xmlrpc_INCREF (xmlrpc_value* value);
+extern void xmlrpc_INCREF (xmlrpc_value* const value);
/* Decrement the reference count of an xmlrpc_value. If there
** are no more references, free it. */
-extern void xmlrpc_DECREF (xmlrpc_value* value);
+extern void xmlrpc_DECREF (xmlrpc_value* const value);
/* Get the type of an XML-RPC value. */
-extern xmlrpc_type xmlrpc_value_type (xmlrpc_value* value);
+extern xmlrpc_type xmlrpc_value_type (xmlrpc_value* const value);
xmlrpc_value *
xmlrpc_int_new(xmlrpc_env * const envP,
int const intValue);
+xmlrpc_value *
+xmlrpc_i8_new(xmlrpc_env * const envP,
+ xmlrpc_int64 const value);
+
void
xmlrpc_read_int(xmlrpc_env * const envP,
const xmlrpc_value * const valueP,
@@ -423,6 +169,25 @@
size_t const length,
const char * const stringValue);
+xmlrpc_value *
+xmlrpc_string_new_va(xmlrpc_env * const envP,
+ const char * const format,
+ va_list args);
+
+xmlrpc_value *
+xmlrpc_string_new_f(xmlrpc_env * const envP,
+ const char * const format,
+ ...);
+
+xmlrpc_value *
+xmlrpc_string_new_lp_cr(xmlrpc_env * const envP,
+ size_t const length,
+ const char * const value);
+
+xmlrpc_value *
+xmlrpc_string_new_cr(xmlrpc_env * const envP,
+ const char * const value);
+
void
xmlrpc_read_string(xmlrpc_env * const envP,
const xmlrpc_value * const valueP,
@@ -430,12 +195,23 @@
void
+xmlrpc_read_string_crlf(xmlrpc_env * const envP,
+ const xmlrpc_value * const valueP,
+ const char ** const stringValueP);
+
+void
+xmlrpc_read_string_lp_crlf(xmlrpc_env * const envP,
+ const xmlrpc_value * const valueP,
+ size_t * const lengthP,
+ const char ** const stringValueP);
+
+void
xmlrpc_read_string_lp(xmlrpc_env * const envP,
const xmlrpc_value * const valueP,
size_t * const lengthP,
const char ** const stringValueP);
-#ifdef HAVE_UNICODE_WCHAR
+#if XMLRPC_HAVE_WCHAR
xmlrpc_value *
xmlrpc_string_w_new(xmlrpc_env * const envP,
const wchar_t * const stringValue);
@@ -451,11 +227,32 @@
const wchar_t ** const stringValueP);
void
+xmlrpc_read_string_w_crlf(xmlrpc_env * const envP,
+ xmlrpc_value * const valueP,
+ const wchar_t ** const stringValueP);
+
+void
xmlrpc_read_string_w_lp(xmlrpc_env * const envP,
xmlrpc_value * const valueP,
size_t * const lengthP,
const wchar_t ** const stringValueP);
-#endif
+
+void
+xmlrpc_read_string_w_lp_crlf(xmlrpc_env * const envP,
+ xmlrpc_value * const valueP,
+ size_t * const lengthP,
+ const wchar_t ** const stringValueP);
+
+xmlrpc_value *
+xmlrpc_string_w_new_lp_cr(xmlrpc_env * const envP,
+ size_t const length,
+ const wchar_t * const value);
+
+xmlrpc_value *
+xmlrpc_string_w_new_cr(xmlrpc_env * const envP,
+ const wchar_t * const value);
+
+#endif /* XMLRPC_HAVE_WCHAR */
xmlrpc_value *
xmlrpc_base64_new(xmlrpc_env * const envP,
@@ -485,9 +282,9 @@
/* Append an item to an XML-RPC array.
** Sets XMLRPC_TYPE_ERROR if 'array' is not an array. */
extern void
-xmlrpc_array_append_item (xmlrpc_env * envP,
- xmlrpc_value * arrayP,
- xmlrpc_value * valueP);
+xmlrpc_array_append_item (xmlrpc_env * const envP,
+ xmlrpc_value * const arrayP,
+ xmlrpc_value * const valueP);
void
xmlrpc_array_read_item(xmlrpc_env * const envP,
@@ -515,18 +312,8 @@
xmlrpc_value* value);
*/
-void
-xmlrpc_read_nil(xmlrpc_env * const envP,
- xmlrpc_value * const valueP);
-
-
-void
-xmlrpc_read_cptr(xmlrpc_env * const envP,
- const xmlrpc_value * const valueP,
- void ** const ptrValueP);
-
xmlrpc_value *
-xmlrpc_struct_new(xmlrpc_env * env);
+xmlrpc_struct_new(xmlrpc_env * const env);
/* Return the number of key/value pairs in a struct.
** Sets XMLRPC_TYPE_ERROR if 'strct' is not a struct. */
@@ -574,17 +361,17 @@
xmlrpc_value ** const valuePP);
void
+xmlrpc_struct_read_value(xmlrpc_env * const envP,
+ xmlrpc_value * const structP,
+ const char * const key,
+ xmlrpc_value ** const valuePP);
+
+void
xmlrpc_struct_read_value_v(xmlrpc_env * const envP,
xmlrpc_value * const structP,
xmlrpc_value * const keyP,
xmlrpc_value ** const valuePP);
-void
-xmlrpc_struct_read_value(xmlrpc_env * const envP,
- xmlrpc_value * const strctP,
- const char * const key,
- xmlrpc_value ** const valuePP);
-
/* The "get_value" functions are deprecated. Use the "find_value"
and "read_value" functions instead.
*/
@@ -650,11 +437,27 @@
Deprecated. Use xmlrpc_struct_read_member() instead.
*/
void
-xmlrpc_struct_get_key_and_value(xmlrpc_env * env,
- xmlrpc_value * strct,
- int index,
- xmlrpc_value ** out_keyval,
- xmlrpc_value ** out_value);
+xmlrpc_struct_get_key_and_value(xmlrpc_env * const env,
+ xmlrpc_value * const strct,
+ int const index,
+ xmlrpc_value ** const out_keyval,
+ xmlrpc_value ** const out_value);
+
+void
+xmlrpc_read_cptr(xmlrpc_env * const envP,
+ const xmlrpc_value * const valueP,
+ void ** const ptrValueP);
+
+void
+xmlrpc_read_nil(xmlrpc_env * const envP,
+ xmlrpc_value * const valueP);
+
+
+void
+xmlrpc_read_i8(xmlrpc_env * const envP,
+ const xmlrpc_value * const valueP,
+ xmlrpc_int64 * const intValueP);
+
xmlrpc_value *
xmlrpc_cptr_new(xmlrpc_env * const envP,
@@ -675,7 +478,7 @@
void
xmlrpc_build_value_va(xmlrpc_env * const env,
const char * const format,
- va_list args,
+ va_list const args,
xmlrpc_value ** const valPP,
const char ** const tailP);
@@ -689,7 +492,7 @@
xmlrpc_decompose_value_va(xmlrpc_env * const envP,
xmlrpc_value * const value,
const char * const format,
- va_list args);
+ va_list const args);
/* xmlrpc_parse_value... is the same as xmlrpc_decompose_value... except
that it doesn't do proper memory management -- it returns xmlrpc_value's
@@ -709,44 +512,67 @@
xmlrpc_parse_value_va(xmlrpc_env * const envP,
xmlrpc_value * const value,
const char * const format,
- va_list args);
+ va_list const args);
/*=========================================================================
** Encoding XML
**=======================================================================*/
-/* Serialize an XML value without any XML header. This is primarily used
-** for testing purposes. */
+typedef enum xmlrpc_dialect {
+ xmlrpc_dialect_i8,
+ xmlrpc_dialect_apache
+} xmlrpc_dialect;
+
+void
+xmlrpc_serialize_value2(xmlrpc_env * const envP,
+ xmlrpc_mem_block * const outputP,
+ xmlrpc_value * const valueP,
+ xmlrpc_dialect const dialect);
+
void
-xmlrpc_serialize_value(xmlrpc_env * env,
- xmlrpc_mem_block * output,
- xmlrpc_value * value);
+xmlrpc_serialize_value(xmlrpc_env * const envP,
+ xmlrpc_mem_block * const outputP,
+ xmlrpc_value * const valueP);
+
+void
+xmlrpc_serialize_params2(xmlrpc_env * const envP,
+ xmlrpc_mem_block * const outputP,
+ xmlrpc_value * const paramArrayP,
+ xmlrpc_dialect const dialect);
-/* Serialize a list of parameters without any XML header. This is
-** primarily used for testing purposes. */
void
-xmlrpc_serialize_params(xmlrpc_env * env,
- xmlrpc_mem_block * output,
- xmlrpc_value * param_array);
+xmlrpc_serialize_params(xmlrpc_env * const envP,
+ xmlrpc_mem_block * const outputP,
+ xmlrpc_value * const paramArrayP);
-/* Serialize an XML-RPC call. */
void
-xmlrpc_serialize_call (xmlrpc_env * const env,
- xmlrpc_mem_block * const output,
- const char * const method_name,
- xmlrpc_value * const param_array);
+xmlrpc_serialize_call2(xmlrpc_env * const envP,
+ xmlrpc_mem_block * const outputP,
+ const char * const methodName,
+ xmlrpc_value * const paramArrayP,
+ xmlrpc_dialect const dialect);
-/* Serialize an XML-RPC return value. */
-extern void
-xmlrpc_serialize_response(xmlrpc_env * env,
- xmlrpc_mem_block * output,
- xmlrpc_value * value);
+void
+xmlrpc_serialize_call(xmlrpc_env * const envP,
+ xmlrpc_mem_block * const outputP,
+ const char * const methodName,
+ xmlrpc_value * const paramArrayP);
-/* Serialize an XML-RPC fault (as specified by 'fault'). */
-extern void
-xmlrpc_serialize_fault(xmlrpc_env * env,
- xmlrpc_mem_block * output,
- xmlrpc_env * fault);
+void
+xmlrpc_serialize_response2(xmlrpc_env * const envP,
+ xmlrpc_mem_block * const outputP,
+ xmlrpc_value * const valueP,
+ xmlrpc_dialect const dialect);
+
+void
+xmlrpc_serialize_response(xmlrpc_env * const envP,
+ xmlrpc_mem_block * const outputP,
+ xmlrpc_value * const valueP);
+
+void
+xmlrpc_serialize_fault(xmlrpc_env * const envP,
+ xmlrpc_mem_block * const outputP,
+ const xmlrpc_env * const faultP);
/*=========================================================================
@@ -764,13 +590,21 @@
const char ** const out_method_name,
xmlrpc_value ** const out_param_array);
-/* Parse an XML-RPC response. If a fault occurs (or was received over the
-** wire), return NULL and set up 'env'. The calling is responsible for
-** calling xmlrpc_DECREF on the return value (if it isn't NULL). */
-xmlrpc_value *
-xmlrpc_parse_response(xmlrpc_env * env,
- const char * xml_data,
- size_t xml_len);
+void
+xmlrpc_parse_response2(xmlrpc_env * const envP,
+ const char * const xmlData,
+ size_t const xmlDataLen,
+ xmlrpc_value ** const resultPP,
+ int * const faultCodeP,
+ const char ** const faultStringP);
+
+
+/* xmlrpc_parse_response() is for backward compatibility */
+
+xmlrpc_value *
+xmlrpc_parse_response(xmlrpc_env * const envP,
+ const char * const xmlData,
+ size_t const xmlDataLen);
/*=========================================================================
@@ -802,42 +636,6 @@
/*=========================================================================
-** UTF-8 Encoding and Decoding
-**=========================================================================
-** We need a correct, reliable and secure UTF-8 decoder. This decoder
-** raises a fault if it encounters invalid UTF-8.
-**
-** Note that ANSI C does not precisely define the representation used
-** by wchar_t--it may be UCS-2, UTF-16, UCS-4, or something from outer
-** space. If your platform does something especially bizarre, you may
-** need to reimplement these routines.
-*/
-
-#ifdef HAVE_UNICODE_WCHAR
-
-/* Ensure that a string contains valid, legally-encoded UTF-8 data.
-** (Incorrectly-encoded UTF-8 strings are often used to bypass security
-** checks.) */
-void
-xmlrpc_validate_utf8 (xmlrpc_env * const env,
- const char * const utf8_data,
- size_t const utf8_len);
-
-/* Decode a UTF-8 string. */
-xmlrpc_mem_block *
-xmlrpc_utf8_to_wcs(xmlrpc_env * env,
- char * utf8_data,
- size_t utf8_len);
-
-/* Encode a UTF-8 string. */
-xmlrpc_mem_block *
-xmlrpc_wcs_to_utf8(xmlrpc_env * env,
- wchar_t * wcs_data,
- size_t wcs_len);
-
-#endif /* HAVE_UNICODE_WCHAR */
-
-/*=========================================================================
** Authorization Cookie Handling
**=========================================================================
** Routines to get and set values for authorizing via authorization
@@ -847,12 +645,44 @@
** a cookie replacement of basic authentication.)
**/
-extern void xmlrpc_authcookie_set(xmlrpc_env * env,
- const char * username,
- const char * password);
+extern void xmlrpc_authcookie_set(xmlrpc_env * const env,
+ const char * const username,
+ const char * const password);
char *xmlrpc_authcookie(void);
+/*=========================================================================
+ Resource Limits
+
+ Ideally, there would be enough resource limits to ensure that
+ XML-RPC partners cannot cause libxmlrpc objects and routines to use
+ more resource than is available for them (either by accident or
+ malice). We have a long way to go to get there.
+
+=========================================================================*/
+/* These functions are _not_ re-entrant and the limits are per-process
+ (i.e. their values live in static global variables).
+*/
+
+/* Limit IDs. There will be more of these as time goes on. */
+#define XMLRPC_NESTING_LIMIT_ID (0)
+#define XMLRPC_XML_SIZE_LIMIT_ID (1)
+#define XMLRPC_LAST_LIMIT_ID (XMLRPC_XML_SIZE_LIMIT_ID)
+
+/* By default, deserialized data may be no more than 64 levels deep. */
+#define XMLRPC_NESTING_LIMIT_DEFAULT (64)
+
+/* By default, XML data from the network may be no larger than 512K.
+** Some client and server modules may fail to enforce this properly. */
+#define XMLRPC_XML_SIZE_LIMIT_DEFAULT (512*1024)
+
+/* Set a specific limit to the specified value. */
+extern void xmlrpc_limit_set (int const limit_id, size_t const value);
+
+/* Get the value of a specified limit. */
+extern size_t xmlrpc_limit_get (int const limit_id);
+
+
#ifdef __cplusplus
}
#endif
Modified: freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/base.hpp
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/base.hpp (original)
+++ freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/base.hpp Fri May 23 16:56:24 2008
@@ -1,5 +1,5 @@
-#ifndef XMLRPC_HPP_INCLUDED
-#define XMLRPC_HPP_INCLUDED
+#ifndef XMLRPC_BASE_HPP_INCLUDED
+#define XMLRPC_BASE_HPP_INCLUDED
#include <climits>
#include <cfloat>
@@ -8,7 +8,7 @@
#include <map>
#include <string>
-#include "xmlrpc-c/base.h"
+#include <xmlrpc-c/base.h>
namespace xmlrpc_c {
@@ -36,6 +36,7 @@
TYPE_STRUCT = 7,
TYPE_C_PTR = 8,
TYPE_NIL = 9,
+ TYPE_I8 = 10,
TYPE_DEAD = 0xDEAD
};
@@ -44,6 +45,9 @@
xmlrpc_c::value&
operator=(xmlrpc_c::value const&);
+ bool
+ isInstantiated() const;
+
// The following are not meant to be public to users, but just to
// other Xmlrpc-c library modules. If we ever go to a pure C++
// implementation, not based on C xmlrpc_value objects, this shouldn't
@@ -54,7 +58,7 @@
void
addToCStruct(xmlrpc_value * const structP,
- std::string const key) const;
+ std::string const key) const;
xmlrpc_value *
cValue() const;
@@ -63,7 +67,7 @@
void
instantiate(xmlrpc_value * const valueP);
- // Work only on a placeholder object created by the no-argument
+ // Works only on a placeholder object created by the no-argument
// constructor.
xmlrpc_value * cValueP;
@@ -96,10 +100,18 @@
class value_string : public value {
public:
- value_string(std::string const& cvalue);
+ enum nlCode {nlCode_all, nlCode_lf};
+
+ value_string(std::string const& cppvalue,
+ nlCode const nlCode);
+
+ value_string(std::string const& cppvalue);
value_string(xmlrpc_c::value const baseValue);
+ std::string
+ crlfValue() const;
+
operator std::string() const;
};
@@ -120,8 +132,12 @@
public:
value_datetime(std::string const cvalue);
value_datetime(time_t const cvalue);
+#if XMLRPC_HAVE_TIMEVAL
value_datetime(struct timeval const& cvalue);
+#endif
+#if XMLRPC_HAVE_TIMESPEC
value_datetime(struct timespec const& cvalue);
+#endif
value_datetime(xmlrpc_c::value const baseValue);
@@ -147,15 +163,6 @@
-class value_nil : public value {
-public:
- value_nil();
-
- value_nil(xmlrpc_c::value const baseValue);
-};
-
-
-
class value_struct : public value {
public:
value_struct(std::map<std::string, xmlrpc_c::value> const& cvalue);
@@ -182,6 +189,26 @@
+class value_nil : public value {
+public:
+ value_nil();
+
+ value_nil(xmlrpc_c::value const baseValue);
+};
+
+
+
+class value_i8 : public value {
+public:
+ value_i8(xmlrpc_int64 const cvalue);
+
+ value_i8(xmlrpc_c::value const baseValue);
+
+ operator xmlrpc_int64() const;
+};
+
+
+
class fault {
/*----------------------------------------------------------------------------
This is an XML-RPC fault.
@@ -255,9 +282,12 @@
public:
paramList(unsigned int const paramCount = 0);
- void
+ paramList&
add(xmlrpc_c::value const param);
+ paramList&
+ addx(xmlrpc_c::value const param);
+
unsigned int
size() const;
@@ -300,6 +330,11 @@
void
getNil(unsigned int const paramNumber) const;
+ xmlrpc_int64
+ getI8(unsigned int const paramNumber,
+ xmlrpc_int64 const minimum = XMLRPC_INT64_MIN,
+ xmlrpc_int64 const maximum = XMLRPC_INT64_MAX) const;
+
void
verifyEnd(unsigned int const paramNumber) const;
Added: freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/base64.hpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/base64.hpp Fri May 23 16:56:24 2008
@@ -0,0 +1,25 @@
+#ifndef XMLRPC_BASE64_HPP_INCLUDED
+#define XMLRPC_BASE64_HPP_INCLUDED
+
+#include <string>
+#include <vector>
+
+namespace xmlrpc_c {
+
+
+enum newlineCtl {NEWLINE_NO, NEWLINE_YES};
+
+std::string
+base64FromBytes(
+ std::vector<unsigned char> const& bytes,
+ xmlrpc_c::newlineCtl const newlineCtl = xmlrpc_c::NEWLINE_YES);
+
+
+
+std::vector<unsigned char>
+bytesFromBase64(std::string const& base64);
+
+
+} // namespace
+
+#endif
Modified: freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/base_int.h
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/base_int.h (original)
+++ freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/base_int.h Fri May 23 16:56:24 2008
@@ -1,5 +1,5 @@
/*============================================================================
- xmlrpc_client_int.h
+ base_int.h
==============================================================================
This header file defines the interface between modules inside
xmlrpc-c.
@@ -11,12 +11,19 @@
============================================================================*/
-#ifndef XMLRPC_INT_H_INCLUDED
-#define XMLRPC_INT_H_INCLUDED
+#ifndef XMLRPC_C_BASE_INT_H_INCLUDED
+#define XMLRPC_C_BASE_INT_H_INCLUDED
+
+#include "xmlrpc_config.h"
+#include "bool.h"
+#include "int.h"
+
+#include <xmlrpc-c/base.h>
+#include <xmlrpc-c/util_int.h>
#ifdef __cplusplus
extern "C" {
-#endif /* __cplusplus */
+#endif
struct _xmlrpc_value {
@@ -26,20 +33,37 @@
/* Certain data types store their data directly in the xmlrpc_value. */
union {
xmlrpc_int32 i;
+ xmlrpc_int64 i8;
xmlrpc_bool b;
double d;
/* time_t t */
- void *c_ptr;
+ void * c_ptr;
} _value;
/* Other data types use a memory block.
- For a string, this is the characters of the string in UTF-8, plus
- a NUL added to the end.
+ For a string, this is the characters of the lines of the string
+ in UTF-8, with lines delimited by either CR, LF, or CRLF, plus
+ a NUL added to the end. The characters of the lines may be any
+ character representable in UTF-8, even the ones that are not
+ legal XML (XML doesn't allow ASCII control characters except
+ tab, CR, LF). But note that a line can't contain CR or LF
+ because that would form a line delimiter. To disambiguate:
+ CRLF together is always one line delimiter.
+
+ This format for string is quite convenient because it is also
+ the format of that part of an XML document which is the
+ contents of a <string> element (except of course that for the
+ non-XML characters, we have to stretch the definition of XML).
+
+ For base64, this is bytes of the byte string, directly.
+
+ For datetime, this is in the same format as the contents of
+ a <dateTime.iso8601> XML element. That really ought to be changed
+ to time_t some day.
*/
xmlrpc_mem_block _block;
-#ifdef HAVE_UNICODE_WCHAR
xmlrpc_mem_block *_wcs_block;
/* This is a copy of the string value in _block, but in UTF-16
instead of UTF-8. This member is not always present. If NULL,
@@ -49,8 +73,10 @@
redundant with _block.
This member is always NULL when the data type is not string.
+
+ This member is always NULL on a system that does not have
+ Unicode wchar functions.
*/
-#endif
};
#define XMLRPC_ASSERT_VALUE_OK(val) \
@@ -65,9 +91,9 @@
typedef struct {
- unsigned char key_hash;
- xmlrpc_value *key;
- xmlrpc_value *value;
+ uint32_t keyHash;
+ xmlrpc_value * key;
+ xmlrpc_value * value;
} _struct_member;
@@ -78,38 +104,20 @@
const char *
xmlrpc_typeName(xmlrpc_type const type);
-
-struct _xmlrpc_registry {
- int _introspection_enabled;
- xmlrpc_value *_methods;
- xmlrpc_value *_default_method;
- xmlrpc_value *_preinvoke_method;
-};
-
-
-/* When we deallocate a pointer in a struct, we often replace it with
-** this and throw in a few assertions here and there. */
-#define XMLRPC_BAD_POINTER ((void*) 0xDEADBEEF)
-
-
void
xmlrpc_traceXml(const char * const label,
const char * const xml,
unsigned int const xmlLength);
void
+xmlrpc_destroyString(xmlrpc_value * const stringP);
+
+void
xmlrpc_destroyStruct(xmlrpc_value * const structP);
void
xmlrpc_destroyArrayContents(xmlrpc_value * const arrayP);
-const char *
-xmlrpc_makePrintable(const char * const input);
-
-const char *
-xmlrpc_makePrintableChar(char const input);
-
-
/*----------------------------------------------------------------------------
The following are for use by the legacy xmlrpc_parse_value(). They don't
do proper memory management, so they aren't appropriate for general use,
@@ -138,7 +146,7 @@
size_t * const lengthP,
const char ** const stringValueP);
-#ifdef HAVE_UNICODE_WCHAR
+#if XMLRPC_HAVE_WCHAR
void
xmlrpc_read_string_w_old(xmlrpc_env * const envP,
xmlrpc_value * const valueP,
@@ -185,6 +193,6 @@
#ifdef __cplusplus
}
-#endif /* __cplusplus */
+#endif
#endif
Added: freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/c_util.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/c_util.h Fri May 23 16:56:24 2008
@@ -0,0 +1,14 @@
+#ifndef XMLRPC_C_C_UTIL_H_INCLUDED
+#define XMLRPC_C_C_UTIL_H_INCLUDED
+
+/* GNU_PRINTF_ATTR lets the GNU compiler check printf-type
+ calls to be sure the arguments match the format string, thus preventing
+ runtime segmentation faults and incorrect messages.
+*/
+#ifdef __GNUC__
+#define GNU_PRINTF_ATTR(a,b) __attribute__ ((format (printf, a, b)))
+#else
+#define GNU_PRINTF_ATTR(a,b)
+#endif
+
+#endif
Modified: freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/client.h
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/client.h (original)
+++ freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/client.h Fri May 23 16:56:24 2008
@@ -16,33 +16,61 @@
extern "C" {
#endif /* __cplusplus */
-/*=========================================================================
-** Initialization and Shutdown
-**=========================================================================
-** These routines initialize and terminate the XML-RPC client. If you're
-** already using libwww on your own, you can pass
-** XMLRPC_CLIENT_SKIP_LIBWWW_INIT to avoid initializing it twice.
+struct xmlrpc_client;
+struct xmlrpc_client_transport;
+struct xmlrpc_client_transport_ops;
+#ifndef __cplusplus
+typedef struct xmlrpc_client xmlrpc_client;
+typedef struct xmlrpc_client_transport xmlrpc_client_transport;
+typedef struct xmlrpc_client_transport_ops xmlrpc_client_transport_ops;
+#endif
+
+/* libxmlrpc_client typically does _not_ actually include all of the
+ XML transports declared here by xmlrpc_*_transport_ops.
+
+ Use 'xmlrpc-c-config --features' to determine which features are
+ installed.
*/
-#define XMLRPC_CLIENT_NO_FLAGS (0)
-#define XMLRPC_CLIENT_SKIP_LIBWWW_INIT (1)
+/* Before Xmlrpc-c 1.13 (December 2007), we declared struct
+ xmlrpc_xportparms, as a sort of "base class." The struct was never
+ complete -- you just cast pointer to it it to pointers to other
+ types. It turned out not to be really helpful and casts are ugly,
+ so now we just use void * as a base class pointer.
+*/
-extern void
-xmlrpc_client_init(int const flags,
- const char * const appname,
- const char * const appversion);
-
-struct xmlrpc_xportparms;
- /* This is a "base class". The struct is never complete; you're
- supposed to cast between struct xmlrpc_xportparms * and
- "struct xmlrpc_..._xportparms *" in order to use it.
- */
+extern struct xmlrpc_client_transport_ops xmlrpc_libwww_transport_ops;
+extern struct xmlrpc_client_transport_ops xmlrpc_wininet_transport_ops;
+extern struct xmlrpc_client_transport_ops xmlrpc_curl_transport_ops;
+
+enum xmlrpc_sslversion {
+ XMLRPC_SSLVERSION_DEFAULT,
+ XMLRPC_SSLVERSION_TLSv1,
+ XMLRPC_SSLVERSION_SSLv2,
+ XMLRPC_SSLVERSION_SSLv3
+};
struct xmlrpc_curl_xportparms {
+ /* This is designed so that zero values are always the defaults. */
const char * network_interface;
xmlrpc_bool no_ssl_verifypeer;
xmlrpc_bool no_ssl_verifyhost;
const char * user_agent;
+ const char * ssl_cert;
+ const char * sslcerttype;
+ const char * sslcertpasswd;
+ const char * sslkey;
+ const char * sslkeytype;
+ const char * sslkeypasswd;
+ const char * sslengine;
+ xmlrpc_bool sslengine_default;
+ enum xmlrpc_sslversion sslversion;
+ const char * cainfo;
+ const char * capath;
+ const char * randomfile;
+ const char * egdsocket;
+ const char * ssl_cipher_list;
+ unsigned int timeout;
};
@@ -61,10 +89,17 @@
/* XMLRPC_WXPSIZE(xyz) is analogous to XMLRPC_CPSIZE, below */
struct xmlrpc_clientparms {
+ /* (transport, transportparmsP, transportparm_size) and
+ (transportOpsP, transportP) are mutually exclusive.
+ */
const char * transport;
- struct xmlrpc_xportparms * transportparmsP;
- /* Cast a "struct ..._xportparms *" to fit here */
+ const void * transportparmsP;
+ /* This should be type "const struct ..._xportparms *" */
size_t transportparm_size;
+
+ const struct xmlrpc_client_transport_ops * transportOpsP;
+ xmlrpc_client_transport * transportP;
+ xmlrpc_dialect dialect;
};
#define XMLRPC_CPSIZE(mbrname) \
@@ -77,24 +112,9 @@
not the caller is new enough to have supplied a certain parameter.
*/
-void
-xmlrpc_client_init2(xmlrpc_env * const env,
- int const flags,
- const char * const appname,
- const char * const appversion,
- const struct xmlrpc_clientparms * const clientparms,
- unsigned int const parm_size);
-
-extern void
-xmlrpc_client_cleanup(void);
-
const char *
xmlrpc_client_get_default_transport(xmlrpc_env * const env);
-/*=========================================================================
-** Required for both internal and external development.
-**=========================================================================
-*/
/* A callback function to handle the response to an asynchronous call.
** If 'fault->fault_occurred' is true, then response will be NULL. All
** arguments except 'user_data' will be deallocated internally; please do
@@ -112,32 +132,39 @@
/*=========================================================================
-** xmlrpc_server_info
-**=========================================================================
-** We normally refer to servers by URL. But sometimes we need to do extra
-** setup for particular servers. In that case, we can create an
-** xmlrpc_server_info object, configure it in various ways, and call the
-** remote server.
-**
-** (This interface is also designed to discourage further multiplication
-** of xmlrpc_client_call APIs. We have enough of those already. Please
-** add future options and flags using xmlrpc_server_info.)
-*/
+ xmlrpc_server_info
+===========================================================================
+ We normally refer to servers by URL. But sometimes we need to do extra
+ setup for particular servers. In that case, we can create an
+ xmlrpc_server_info object, configure it in various ways, and call the
+ remote server.
+
+ (This interface is also designed to discourage further multiplication
+ of xmlrpc_client_call APIs. We have enough of those already. Please
+ add future options and flags using xmlrpc_server_info.)
+=========================================================================*/
typedef struct _xmlrpc_server_info xmlrpc_server_info;
/* Create a new server info record, pointing to the specified server. */
xmlrpc_server_info *
-xmlrpc_server_info_new(xmlrpc_env * const env,
- const char * const server_url);
+xmlrpc_server_info_new(xmlrpc_env * const envP,
+ const char * const serverUrl);
/* Create a new server info record, with a copy of the old server. */
extern xmlrpc_server_info *
-xmlrpc_server_info_copy(xmlrpc_env *env, xmlrpc_server_info *src_server);
+xmlrpc_server_info_copy(xmlrpc_env * const envP,
+ xmlrpc_server_info * const srcP);
+
+void
+xmlrpc_server_info_free(xmlrpc_server_info * const serverP);
-/* Delete a server info record. */
-extern void
-xmlrpc_server_info_free (xmlrpc_server_info *server);
+
+void
+xmlrpc_server_info_set_user(xmlrpc_env * const envP,
+ xmlrpc_server_info * const serverInfoP,
+ const char * const username,
+ const char * const password);
void
xmlrpc_server_info_set_basic_auth(xmlrpc_env * const envP,
@@ -145,118 +172,116 @@
const char * const username,
const char * const password);
+void
+xmlrpc_server_info_allow_auth_basic(xmlrpc_env * const envP,
+ xmlrpc_server_info * const sP);
-/*=========================================================================
-** xmlrpc_client_call
-**=========================================================================
-** A synchronous XML-RPC client. Do not attempt to call any of these
-** functions from inside an asynchronous callback!
-*/
+void
+xmlrpc_server_info_disallow_auth_basic(xmlrpc_env * const envP,
+ xmlrpc_server_info * const sP);
-xmlrpc_value *
-xmlrpc_client_call(xmlrpc_env * const envP,
- const char * const server_url,
- const char * const method_name,
- const char * const format,
- ...);
-
-xmlrpc_value *
-xmlrpc_client_call_params(xmlrpc_env * const envP,
- const char * const serverUrl,
- const char * const methodName,
- xmlrpc_value * const paramArrayP);
-
-xmlrpc_value *
-xmlrpc_client_call_server(xmlrpc_env * const envP,
- const xmlrpc_server_info * const server,
- const char * const method_name,
- const char * const format,
- ...);
+void
+xmlrpc_server_info_allow_auth_digest(xmlrpc_env * const envP,
+ xmlrpc_server_info * const sP);
-xmlrpc_value *
-xmlrpc_client_call_server_params(
- xmlrpc_env * const envP,
- const xmlrpc_server_info * const serverP,
- const char * const method_name,
- xmlrpc_value * const paramArrayP);
+void
+xmlrpc_server_info_disallow_auth_digest(xmlrpc_env * const envP,
+ xmlrpc_server_info * const sP);
+
+void
+xmlrpc_server_info_allow_auth_negotiate(xmlrpc_env * const envP,
+ xmlrpc_server_info * const sP);
+
+void
+xmlrpc_server_info_disallow_auth_negotiate(xmlrpc_env * const envP,
+ xmlrpc_server_info * const sP);
+
+void
+xmlrpc_server_info_allow_auth_ntlm(xmlrpc_env * const envP,
+ xmlrpc_server_info * const sP);
+
+void
+xmlrpc_server_info_disallow_auth_ntlm(xmlrpc_env * const envP,
+ xmlrpc_server_info * const sP);
+
+extern unsigned int const xmlrpc_client_version_major;
+extern unsigned int const xmlrpc_client_version_minor;
+extern unsigned int const xmlrpc_client_version_point;
+
+void
+xmlrpc_client_setup_global_const(xmlrpc_env * const envP);
+
+void
+xmlrpc_client_teardown_global_const(void);
+
+void
+xmlrpc_client_create(xmlrpc_env * const envP,
+ int const flags,
+ const char * const appname,
+ const char * const appversion,
+ const struct xmlrpc_clientparms * const clientparmsP,
+ unsigned int const parmSize,
+ xmlrpc_client ** const clientPP);
+
+void
+xmlrpc_client_destroy(xmlrpc_client * const clientP);
void
-xmlrpc_client_transport_call(
+xmlrpc_client_transport_call2(
xmlrpc_env * const envP,
- void * const reserved, /* for client handle */
+ xmlrpc_client * const clientP,
const xmlrpc_server_info * const serverP,
xmlrpc_mem_block * const callXmlP,
xmlrpc_mem_block ** const respXmlPP);
+void
+xmlrpc_client_call2(xmlrpc_env * const envP,
+ struct xmlrpc_client * const clientP,
+ const xmlrpc_server_info * const serverInfoP,
+ const char * const methodName,
+ xmlrpc_value * const paramArrayP,
+ xmlrpc_value ** const resultPP);
-/*=========================================================================
-** xmlrpc_client_call_asynch
-**=========================================================================
-** An asynchronous XML-RPC client.
-*/
+void
+xmlrpc_client_call2f(xmlrpc_env * const envP,
+ xmlrpc_client * const clientP,
+ const char * const serverUrl,
+ const char * const methodName,
+ xmlrpc_value ** const resultPP,
+ const char * const format,
+ ...);
-/* Make an asynchronous XML-RPC call. We make internal copies of all
-** arguments except user_data, so you can deallocate them safely as soon
-** as you return. Errors will be passed to the callback. You will need
-** to run the event loop somehow; see below.
-** WARNING: If an error occurs while building the argument, the
-** response handler will be called with a NULL param_array. */
void
-xmlrpc_client_call_asynch(const char * const server_url,
- const char * const method_name,
- xmlrpc_response_handler callback,
- void * const user_data,
- const char * const format,
- ...);
+xmlrpc_client_event_loop_finish(xmlrpc_client * const clientP);
-/* As above, but use an xmlrpc_server_info object. The server object can be
-** safely destroyed as soon as this function returns. */
void
-xmlrpc_client_call_server_asynch(xmlrpc_server_info * const server,
- const char * const method_name,
- xmlrpc_response_handler callback,
- void * const user_data,
- const char * const format,
- ...);
+xmlrpc_client_event_loop_finish_timeout(xmlrpc_client * const clientP,
+ unsigned long const milliseconds);
-/* As above, but the parameter list is supplied as an xmlrpc_value
-** containing an array.
-*/
void
-xmlrpc_client_call_asynch_params(const char * const server_url,
- const char * const method_name,
- xmlrpc_response_handler callback,
- void * const user_data,
- xmlrpc_value * const paramArrayP);
-
-/* As above, but use an xmlrpc_server_info object. The server object can be
-** safely destroyed as soon as this function returns. */
-void
-xmlrpc_client_call_server_asynch_params(
- xmlrpc_server_info * const server,
- const char * const method_name,
- xmlrpc_response_handler callback,
- void * const user_data,
- xmlrpc_value * const paramArrayP);
-
-/*=========================================================================
-** Event Loop Interface
-**=========================================================================
-** These functions can be used to run the XML-RPC event loop. If you
-** don't like these, you can also run the libwww event loop directly.
-*/
-
-/* Finish all outstanding asynchronous calls. Alternatively, the loop
-** will exit if someone calls xmlrpc_client_event_loop_end. */
-extern void
-xmlrpc_client_event_loop_finish_asynch(void);
+xmlrpc_client_start_rpc(xmlrpc_env * const envP,
+ struct xmlrpc_client * const clientP,
+ xmlrpc_server_info * const serverInfoP,
+ const char * const methodName,
+ xmlrpc_value * const argP,
+ xmlrpc_response_handler responseHandler,
+ void * const userData);
+void
+xmlrpc_client_start_rpcf(xmlrpc_env * const envP,
+ xmlrpc_client * const clientP,
+ const char * const serverUrl,
+ const char * const methodName,
+ xmlrpc_response_handler callback,
+ void * const userData,
+ const char * const format,
+ ...);
-/* Finish all outstanding asynchronous calls. */
-extern void
-xmlrpc_client_event_loop_finish_asynch_timeout(unsigned long milliseconds);
-
+void
+xmlrpc_client_set_interrupt(xmlrpc_client * const clientP,
+ int * const interruptP);
+#include <xmlrpc-c/client_global.h>
/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
**
Modified: freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/client.hpp
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/client.hpp (original)
+++ freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/client.hpp Fri May 23 16:56:24 2008
@@ -2,33 +2,17 @@
#define CLIENT_HPP_INCLUDED
#include <string>
+#include <vector>
+#include <memory>
#include <xmlrpc-c/girerr.hpp>
#include <xmlrpc-c/girmem.hpp>
#include <xmlrpc-c/base.hpp>
#include <xmlrpc-c/timeout.hpp>
-#include <xmlrpc-c/client.h>
+#include <xmlrpc-c/client_transport.hpp>
namespace xmlrpc_c {
-
-class carriageParm {
-/*----------------------------------------------------------------------------
- The parameter to a client for an individual RPC. It tells specifics
- of how to carry the call to the server and the response back. For
- example, it may identify the server. It may identify communication
- protocols to use. It may indicate permission and accounting
- information.
-
- This is a base class; the carriage parameter is specific to the
- class of client. For example, an HTTP-based client would have a
- URL and HTTP basic authentication info as parameter.
------------------------------------------------------------------------------*/
-protected:
- virtual ~carriageParm();
- carriageParm();
-};
-
class clientTransactionPtr;
class clientTransaction : public girmem::autoObject {
@@ -50,13 +34,18 @@
public:
clientTransactionPtr();
+
+ clientTransactionPtr(clientTransaction * const transP);
+
virtual ~clientTransactionPtr();
virtual xmlrpc_c::clientTransaction *
operator->() const;
};
-class client {
+class clientPtr;
+
+class client : public girmem::autoObject {
/*----------------------------------------------------------------------------
A generic client -- a means of performing an RPC. This is so generic
that it can be used for clients that are not XML-RPC.
@@ -64,196 +53,91 @@
This is a base class. Derived classes define things such as that
XML and HTTP get used to perform the RPC.
-----------------------------------------------------------------------------*/
+ friend class clientTransactionPtr;
+
public:
virtual ~client();
virtual void
- call(carriageParm * const carriageParmP,
- std::string const methodName,
- xmlrpc_c::paramList const& paramList,
- xmlrpc_c::rpcOutcome * const outcomeP) = 0;
+ call(xmlrpc_c::carriageParm * const carriageParmP,
+ std::string const& methodName,
+ xmlrpc_c::paramList const& paramList,
+ xmlrpc_c::rpcOutcome * const outcomeP) = 0;
virtual void
start(xmlrpc_c::carriageParm * const carriageParmP,
- std::string const methodName,
+ std::string const& methodName,
xmlrpc_c::paramList const& paramList,
xmlrpc_c::clientTransactionPtr const& tranP);
-};
-
-class connection {
-/*----------------------------------------------------------------------------
- A nexus of a particular client and a particular server, along with
- carriage parameters for performing RPCs between the two.
-
- This is a minor convenience for client programs that always talk to
- the same server the same way.
-
- Use this as a parameter to rpc.call().
------------------------------------------------------------------------------*/
-public:
- connection(xmlrpc_c::client * const clientP,
- xmlrpc_c::carriageParm * const carriageParmP);
-
- ~connection();
-
- xmlrpc_c::client * clientP;
- xmlrpc_c::carriageParm * carriageParmP;
-};
-
-class carriageParm_http0 : public carriageParm {
-
-public:
- carriageParm_http0(std::string const serverUrl);
-
- ~carriageParm_http0();
-
- void
- setBasicAuth(std::string const userid,
- std::string const password);
-
- xmlrpc_server_info * c_serverInfoP;
-
-protected:
- // Only a derived class is allowed to create an object with no
- // server URL, and the derived class expected to follow it up
- // with an instantiate() to establish the server URL.
-
- carriageParm_http0();
void
- instantiate(std::string const serverUrl);
+ finishAsync(xmlrpc_c::timeout const timeout);
+
+ virtual void
+ setInterrupt(int *);
};
-class carriageParm_curl0 : public xmlrpc_c::carriageParm_http0 {
-
+class clientPtr : public girmem::autoObjectPtr {
public:
- carriageParm_curl0(std::string const serverUrl);
-
-};
+ clientPtr();
-class carriageParm_libwww0 : public xmlrpc_c::carriageParm_http0 {
+ explicit clientPtr(xmlrpc_c::client * const clientP);
-public:
- carriageParm_libwww0(std::string const serverUrl);
+ xmlrpc_c::client *
+ operator->() const;
+ xmlrpc_c::client *
+ get() const;
};
-class carriageParm_wininet0 : public xmlrpc_c::carriageParm_http0 {
-
+class serverAccessor : public girmem::autoObject {
+
public:
- carriageParm_wininet0(std::string const serverUrl);
+ serverAccessor(xmlrpc_c::clientPtr const clientP,
+ xmlrpc_c::carriageParmPtr const carriageParmP);
-};
-
-class xmlTransactionPtr;
-
-class xmlTransaction : public girmem::autoObject {
-
- friend class xmlTransactionPtr;
-
-public:
- virtual void
- finish(std::string const& responseXml) const;
-
- virtual void
- finishErr(girerr::error const& error) const;
+ void
+ call(std::string const& methodName,
+ xmlrpc_c::paramList const& paramList,
+ xmlrpc_c::rpcOutcome * const outcomeP) const;
-protected:
- xmlTransaction();
+private:
+ xmlrpc_c::clientPtr const clientP;
+ xmlrpc_c::carriageParmPtr const carriageParmP;
};
-class xmlTransactionPtr : public girmem::autoObjectPtr {
+class serverAccessorPtr : public girmem::autoObjectPtr {
public:
- xmlTransactionPtr();
-
- xmlrpc_c::xmlTransaction *
- operator->() const;
-};
-
-class clientXmlTransport {
-/*----------------------------------------------------------------------------
- An object which transports XML to and from an XML-RPC server for an
- XML-RPC client.
+ serverAccessorPtr();
- This is a base class. Derived classes define methods to perform the
- transportation in particular ways.
------------------------------------------------------------------------------*/
-public:
- virtual ~clientXmlTransport();
+ explicit
+ serverAccessorPtr(xmlrpc_c::serverAccessor * const serverAccessorP);
- virtual void
- call(xmlrpc_c::carriageParm * const carriageParmP,
- std::string const& callXml,
- std::string * const responseXmlP) = 0;
-
- virtual void
- start(xmlrpc_c::carriageParm * const carriageParmP,
- std::string const& callXml,
- xmlrpc_c::xmlTransactionPtr const& xmlTranP);
-
- virtual void
- finishAsync(xmlrpc_c::timeout const timeout);
+ xmlrpc_c::serverAccessor *
+ operator->() const;
- static void
- asyncComplete(
- struct xmlrpc_call_info * const callInfoP,
- xmlrpc_mem_block * const responseXmlMP,
- xmlrpc_env const transportEnv);
+ xmlrpc_c::serverAccessor *
+ get() const;
};
-class clientXmlTransport_http : public xmlrpc_c::clientXmlTransport {
+class connection {
/*----------------------------------------------------------------------------
- A base class for client XML transports that use the simple, classic
- C HTTP transports.
------------------------------------------------------------------------------*/
-public:
- virtual ~clientXmlTransport_http();
-
- void
- call(xmlrpc_c::carriageParm * const carriageParmP,
- std::string const& callXml,
- std::string * const responseXmlP);
-
- void
- start(xmlrpc_c::carriageParm * const carriageParmP,
- std::string const& callXml,
- xmlrpc_c::xmlTransactionPtr const& xmlTranP);
-
- virtual void
- finishAsync(xmlrpc_c::timeout const timeout);
-
-protected:
- clientXmlTransport_http() {} // ensure no one can create
- struct xmlrpc_client_transport * c_transportP;
- const struct xmlrpc_client_transport_ops * c_transportOpsP;
-};
-
-class clientXmlTransport_curl : public xmlrpc_c::clientXmlTransport_http {
-
-public:
- clientXmlTransport_curl(std::string const networkInterface = "",
- bool const noSslVerifyPeer = false,
- bool const noSslVerifyHost = false,
- std::string const userAgent = "");
+ A nexus of a particular client and a particular server, along with
+ carriage parameters for performing RPCs between the two.
- ~clientXmlTransport_curl();
-};
+ This is a minor convenience for client programs that always talk to
+ the same server the same way.
-class clientXmlTransport_libwww : public xmlrpc_c::clientXmlTransport_http {
-
+ Use this as a parameter to rpc.call().
+-----------------------------------------------------------------------------*/
public:
- clientXmlTransport_libwww(std::string const appname = "",
- std::string const appversion = "");
-
- ~clientXmlTransport_libwww();
-};
-
-class clientXmlTransport_wininet : public xmlrpc_c::clientXmlTransport_http {
+ connection(xmlrpc_c::client * const clientP,
+ xmlrpc_c::carriageParm * const carriageParmP);
-public:
- clientXmlTransport_wininet(bool const allowInvalidSslCerts = false);
+ ~connection();
- ~clientXmlTransport_wininet();
+ xmlrpc_c::client * clientP;
+ xmlrpc_c::carriageParm * carriageParmP;
};
class client_xml : public xmlrpc_c::client {
@@ -264,23 +148,36 @@
public:
client_xml(xmlrpc_c::clientXmlTransport * const transportP);
+ client_xml(xmlrpc_c::clientXmlTransport * const transportP,
+ xmlrpc_dialect const dialect);
+
+ client_xml(xmlrpc_c::clientXmlTransportPtr const transportP);
+
+ client_xml(xmlrpc_c::clientXmlTransportPtr const transportP,
+ xmlrpc_dialect const dialect);
+
+ ~client_xml();
+
void
call(carriageParm * const carriageParmP,
- std::string const methodName,
+ std::string const& methodName,
xmlrpc_c::paramList const& paramList,
xmlrpc_c::rpcOutcome * const outcomeP);
void
start(xmlrpc_c::carriageParm * const carriageParmP,
- std::string const methodName,
+ std::string const& methodName,
xmlrpc_c::paramList const& paramList,
xmlrpc_c::clientTransactionPtr const& tranP);
void
finishAsync(xmlrpc_c::timeout const timeout);
+ virtual void
+ setInterrupt(int * interruptP);
+
private:
- xmlrpc_c::clientXmlTransport * transportP;
+ struct client_xml_impl * implP;
};
class xmlTransaction_client : public xmlrpc_c::xmlTransaction {
@@ -363,32 +260,20 @@
xmlrpc_c::fault
getFault() const;
-protected:
rpc(std::string const methodName,
xmlrpc_c::paramList const& paramList);
virtual ~rpc();
private:
- enum state {
- STATE_UNFINISHED, // RPC is running or not started yet
- STATE_ERROR, // We couldn't execute the RPC
- STATE_FAILED, // RPC executed successfully, but failed per XML-RPC
- STATE_SUCCEEDED // RPC is done, no exception
- };
- enum state state;
- girerr::error * errorP; // Defined only in STATE_ERROR
- xmlrpc_c::rpcOutcome outcome;
- // Defined only in STATE_FAILED and STATE_SUCCEEDED
- std::string methodName;
- xmlrpc_c::paramList paramList;
+ struct rpc_impl * implP;
};
class rpcPtr : public clientTransactionPtr {
public:
rpcPtr();
- rpcPtr(xmlrpc_c::rpc * const rpcP);
+ explicit rpcPtr(xmlrpc_c::rpc * const rpcP);
rpcPtr(std::string const methodName,
xmlrpc_c::paramList const& paramList);
Added: freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/client_global.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/client_global.h Fri May 23 16:56:24 2008
@@ -0,0 +1,141 @@
+#ifndef CLIENT_GLOBAL_H_INCLUDED
+#define CLIENT_GLOBAL_H_INCLUDED
+
+/*=========================================================================
+** Initialization and Shutdown
+**=========================================================================
+** These routines initialize and terminate the XML-RPC client. If you're
+** already using libwww on your own, you can pass
+** XMLRPC_CLIENT_SKIP_LIBWWW_INIT to avoid initializing it twice.
+*/
+
+#define XMLRPC_CLIENT_NO_FLAGS (0)
+#define XMLRPC_CLIENT_SKIP_LIBWWW_INIT (1)
+
+extern void
+xmlrpc_client_init(int const flags,
+ const char * const appname,
+ const char * const appversion);
+
+void
+xmlrpc_client_init2(xmlrpc_env * const env,
+ int const flags,
+ const char * const appname,
+ const char * const appversion,
+ const struct xmlrpc_clientparms * const clientparms,
+ unsigned int const parm_size);
+
+extern void
+xmlrpc_client_cleanup(void);
+
+/*=========================================================================
+** xmlrpc_client_call
+**=========================================================================
+** A synchronous XML-RPC client. Do not attempt to call any of these
+** functions from inside an asynchronous callback!
+*/
+
+xmlrpc_value *
+xmlrpc_client_call(xmlrpc_env * const envP,
+ const char * const server_url,
+ const char * const method_name,
+ const char * const format,
+ ...);
+
+xmlrpc_value *
+xmlrpc_client_call_params(xmlrpc_env * const envP,
+ const char * const serverUrl,
+ const char * const methodName,
+ xmlrpc_value * const paramArrayP);
+
+xmlrpc_value *
+xmlrpc_client_call_server(xmlrpc_env * const envP,
+ const xmlrpc_server_info * const server,
+ const char * const method_name,
+ const char * const format,
+ ...);
+
+xmlrpc_value *
+xmlrpc_client_call_server_params(
+ xmlrpc_env * const envP,
+ const xmlrpc_server_info * const serverP,
+ const char * const method_name,
+ xmlrpc_value * const paramArrayP);
+
+void
+xmlrpc_client_transport_call(
+ xmlrpc_env * const envP,
+ void * const reserved, /* for client handle */
+ const xmlrpc_server_info * const serverP,
+ xmlrpc_mem_block * const callXmlP,
+ xmlrpc_mem_block ** const respXmlPP);
+
+
+/*=========================================================================
+** xmlrpc_client_call_asynch
+**=========================================================================
+** An asynchronous XML-RPC client.
+*/
+
+/* Make an asynchronous XML-RPC call. We make internal copies of all
+** arguments except user_data, so you can deallocate them safely as soon
+** as you return. Errors will be passed to the callback. You will need
+** to run the event loop somehow; see below.
+** WARNING: If an error occurs while building the argument, the
+** response handler will be called with a NULL param_array. */
+void
+xmlrpc_client_call_asynch(const char * const server_url,
+ const char * const method_name,
+ xmlrpc_response_handler callback,
+ void * const user_data,
+ const char * const format,
+ ...);
+
+/* As above, but use an xmlrpc_server_info object. The server object can be
+** safely destroyed as soon as this function returns. */
+void
+xmlrpc_client_call_server_asynch(xmlrpc_server_info * const server,
+ const char * const method_name,
+ xmlrpc_response_handler callback,
+ void * const user_data,
+ const char * const format,
+ ...);
+
+/* As above, but the parameter list is supplied as an xmlrpc_value
+** containing an array.
+*/
+void
+xmlrpc_client_call_asynch_params(const char * const server_url,
+ const char * const method_name,
+ xmlrpc_response_handler callback,
+ void * const user_data,
+ xmlrpc_value * const paramArrayP);
+
+/* As above, but use an xmlrpc_server_info object. The server object can be
+** safely destroyed as soon as this function returns. */
+void
+xmlrpc_client_call_server_asynch_params(
+ xmlrpc_server_info * const server,
+ const char * const method_name,
+ xmlrpc_response_handler callback,
+ void * const user_data,
+ xmlrpc_value * const paramArrayP);
+
+/*=========================================================================
+** Event Loop Interface
+**=========================================================================
+** These functions can be used to run the XML-RPC event loop. If you
+** don't like these, you can also run the libwww event loop directly.
+*/
+
+/* Finish all outstanding asynchronous calls. Alternatively, the loop
+** will exit if someone calls xmlrpc_client_event_loop_end. */
+extern void
+xmlrpc_client_event_loop_finish_asynch(void);
+
+
+/* Finish all outstanding asynchronous calls. */
+extern void
+xmlrpc_client_event_loop_finish_asynch_timeout(unsigned long const milliseconds);
+
+#endif
Modified: freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/client_int.h
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/client_int.h (original)
+++ freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/client_int.h Fri May 23 16:56:24 2008
@@ -14,24 +14,43 @@
#ifndef XMLRPC_CLIENT_INT_H_INCLUDED
#define XMLRPC_CLIENT_INT_H_INCLUDED
+#include "xmlrpc-c/util.h"
+
#ifdef __cplusplus
extern "C" {
-#endif /* __cplusplus */
+#endif
struct _xmlrpc_server_info {
- char *_server_url;
- char *_http_basic_auth;
-};
-
-/* Create a new server info record, with a copy of the old server. */
-extern xmlrpc_server_info *
-xmlrpc_server_info_copy(xmlrpc_env *env, xmlrpc_server_info *aserver);
+ const char * serverUrl;
+ struct {
+ bool basic;
+ bool digest;
+ bool gssnegotiate;
+ bool ntlm;
+ } allowedAuth;
+ const char * userNamePw;
+ /* The username/password value for HTTP, i.e. in
+ "user:password" form
+
+ This can be NULL to indicate "none", but only if 'allowedAuth'
+ doesn't allow any form of authentication.
+ */
+ const char * basicAuthHdrValue;
+ /* A complete value for an HTTP Authorization: header that
+ requests HTTP basic authentication. This exists whether
+ or not 'allowedAuth' allows basic authentication, and is
+ completely redundant with 'userNamePw'. It exists mainly
+ for historical reasons, and may also save some computation
+ when the same xmrpc_server_info is used for multiple
+ HTTP connections.
+ This is NULL exactly when 'userNamePw' is NULL.
+ */
+};
/*=========================================================================
** Transport Implementation functions.
-**=========================================================================
-*/
+**========================================================================= */
#include "xmlrpc-c/transport.h"
/* The generalized event loop. This uses the above flags. For more details,
Modified: freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/client_simple.hpp
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/client_simple.hpp (original)
+++ freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/client_simple.hpp Fri May 23 16:56:24 2008
@@ -14,8 +14,6 @@
public:
clientSimple();
- ~clientSimple();
-
void
call(std::string const serverUrl,
std::string const methodName,
@@ -35,8 +33,7 @@
xmlrpc_c::value * const resultP);
private:
- xmlrpc_c::client * clientP;
- xmlrpc_c::clientXmlTransport * transportP;
+ xmlrpc_c::clientPtr clientP;
};
} // namespace
Added: freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/client_transport.hpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/client_transport.hpp Fri May 23 16:56:24 2008
@@ -0,0 +1,448 @@
+#ifndef CLIENT_TRANSPORT_HPP_INCLUDED
+#define CLIENT_TRANSPORT_HPP_INCLUDED
+
+#include <string>
+#include <vector>
+#include <xmlrpc-c/util.h>
+#include <xmlrpc-c/client.h>
+#include <xmlrpc-c/girerr.hpp>
+#include <xmlrpc-c/girmem.hpp>
+#include <xmlrpc-c/timeout.hpp>
+
+namespace xmlrpc_c {
+
+class carriageParmPtr;
+
+class carriageParm : public girmem::autoObject {
+/*----------------------------------------------------------------------------
+ The parameter to a client for an individual RPC. It tells specifics
+ of how to carry the call to the server and the response back. For
+ example, it may identify the server. It may identify communication
+ protocols to use. It may indicate permission and accounting
+ information.
+
+ This is a base class; the carriage parameter is specific to the
+ class of client. For example, an HTTP-based client would have a
+ URL and HTTP basic authentication info as parameter.
+-----------------------------------------------------------------------------*/
+protected:
+ virtual ~carriageParm();
+ carriageParm();
+};
+
+class carriageParmPtr : public girmem::autoObjectPtr {
+
+public:
+ carriageParmPtr();
+
+ explicit carriageParmPtr(xmlrpc_c::carriageParm * const carriageParmP);
+
+ xmlrpc_c::carriageParm *
+ operator->() const;
+
+ xmlrpc_c::carriageParm *
+ get() const;
+};
+
+//----------------------------------------------------------------------------
+
+class xmlTransactionPtr;
+
+class xmlTransaction : public girmem::autoObject {
+
+ friend class xmlTransactionPtr;
+
+public:
+ virtual void
+ finish(std::string const& responseXml) const;
+
+ virtual void
+ finishErr(girerr::error const& error) const;
+
+protected:
+ xmlTransaction();
+};
+
+class xmlTransactionPtr : public girmem::autoObjectPtr {
+public:
+ xmlTransactionPtr();
+
+ xmlTransactionPtr(xmlTransaction * xmlTransP);
+
+ xmlrpc_c::xmlTransaction *
+ operator->() const;
+};
+
+//----------------------------------------------------------------------------
+
+class clientXmlTransport : public girmem::autoObject {
+/*----------------------------------------------------------------------------
+ An object which transports XML to and from an XML-RPC server for an
+ XML-RPC client.
+
+ This is a base class. Derived classes define methods to perform the
+ transportation in particular ways.
+-----------------------------------------------------------------------------*/
+public:
+ virtual ~clientXmlTransport();
+
+ virtual void
+ call(xmlrpc_c::carriageParm * const carriageParmP,
+ std::string const& callXml,
+ std::string * const responseXmlP) = 0;
+
+ virtual void
+ start(xmlrpc_c::carriageParm * const carriageParmP,
+ std::string const& callXml,
+ xmlrpc_c::xmlTransactionPtr const& xmlTranP);
+
+ virtual void
+ finishAsync(xmlrpc_c::timeout const timeout);
+
+ static void
+ asyncComplete(
+ struct xmlrpc_call_info * const callInfoP,
+ xmlrpc_mem_block * const responseXmlMP,
+ xmlrpc_env const transportEnv);
+
+ virtual void
+ setInterrupt(int * const interruptP);
+};
+
+class clientXmlTransportPtr : public girmem::autoObjectPtr {
+
+public:
+ clientXmlTransportPtr();
+
+ clientXmlTransportPtr(xmlrpc_c::clientXmlTransport * const transportP);
+
+ xmlrpc_c::clientXmlTransport *
+ operator->() const;
+
+ xmlrpc_c::clientXmlTransport *
+ get() const;
+};
+
+/*===========================================================================
+ HTTP
+===========================================================================*/
+
+class carriageParm_http0 : public xmlrpc_c::carriageParm {
+
+public:
+ carriageParm_http0(std::string const serverUrl);
+
+ ~carriageParm_http0();
+
+ void
+ setUser(std::string const userid,
+ std::string const password);
+
+ void
+ allowAuthBasic();
+
+ void
+ disallowAuthBasic();
+
+ void
+ allowAuthDigest();
+
+ void
+ disallowAuthDigest();
+
+ void
+ allowAuthNegotiate();
+
+ void
+ disallowAuthNegotiate();
+
+ void
+ allowAuthNtlm();
+
+ void
+ disallowAuthNtlm();
+
+ void
+ setBasicAuth(std::string const userid,
+ std::string const password);
+
+ xmlrpc_server_info * c_serverInfoP;
+
+protected:
+ // Only a derived class is allowed to create an object with no
+ // server URL, and the derived class is expected to follow it up
+ // with an instantiate() to establish the server URL.
+
+ carriageParm_http0();
+
+ void
+ instantiate(std::string const serverUrl);
+};
+
+class carriageParm_http0Ptr : public xmlrpc_c::carriageParmPtr {
+
+public:
+ carriageParm_http0Ptr();
+ carriageParm_http0Ptr(xmlrpc_c::carriageParm_http0 * const carriageParmP);
+
+ xmlrpc_c::carriageParm_http0 *
+ operator->() const;
+};
+
+class clientXmlTransport_http : public xmlrpc_c::clientXmlTransport {
+/*----------------------------------------------------------------------------
+ A base class for client XML transports that use the simple, classic
+ C HTTP transports.
+-----------------------------------------------------------------------------*/
+public:
+ virtual ~clientXmlTransport_http();
+
+ void
+ call(xmlrpc_c::carriageParm * const carriageParmP,
+ std::string const& callXml,
+ std::string * const responseXmlP);
+
+ void
+ start(xmlrpc_c::carriageParm * const carriageParmP,
+ std::string const& callXml,
+ xmlrpc_c::xmlTransactionPtr const& xmlTranP);
+
+ virtual void
+ finishAsync(xmlrpc_c::timeout const timeout);
+
+ virtual void
+ setInterrupt(int * const interruptP);
+
+ static std::vector<std::string>
+ availableTypes();
+
+ static clientXmlTransportPtr
+ create();
+
+protected:
+ clientXmlTransport_http() {} // ensure no one can create
+ struct xmlrpc_client_transport * c_transportP;
+ const struct xmlrpc_client_transport_ops * c_transportOpsP;
+};
+
+
+/*===========================================================================
+ curl
+===========================================================================*/
+
+class carriageParm_curl0 : public xmlrpc_c::carriageParm_http0 {
+
+public:
+ carriageParm_curl0(std::string const serverUrl);
+};
+
+class carriageParm_curl0Ptr : public xmlrpc_c::carriageParm_http0Ptr {
+
+public:
+ carriageParm_curl0Ptr();
+ carriageParm_curl0Ptr(xmlrpc_c::carriageParm_curl0 * const carriageParmP);
+
+ xmlrpc_c::carriageParm_curl0 *
+ operator->() const;
+};
+
+class clientXmlTransport_curl : public xmlrpc_c::clientXmlTransport_http {
+
+public:
+ class constrOpt {
+ public:
+ constrOpt();
+
+ constrOpt & network_interface (std::string const& arg);
+ constrOpt & no_ssl_verifypeer (bool const& arg);
+ constrOpt & no_ssl_verifyhost (bool const& arg);
+ constrOpt & user_agent (std::string const& arg);
+ constrOpt & ssl_cert (std::string const& arg);
+ constrOpt & sslcerttype (std::string const& arg);
+ constrOpt & sslcertpasswd (std::string const& arg);
+ constrOpt & sslkey (std::string const& arg);
+ constrOpt & sslkeytype (std::string const& arg);
+ constrOpt & sslkeypasswd (std::string const& arg);
+ constrOpt & sslengine (std::string const& arg);
+ constrOpt & sslengine_default (bool const& arg);
+ constrOpt & sslversion (xmlrpc_sslversion const& arg);
+ constrOpt & cainfo (std::string const& arg);
+ constrOpt & capath (std::string const& arg);
+ constrOpt & randomfile (std::string const& arg);
+ constrOpt & egdsocket (std::string const& arg);
+ constrOpt & ssl_cipher_list (std::string const& arg);
+ constrOpt & timeout (unsigned int const& arg);
+
+ struct {
+ std::string network_interface;
+ bool no_ssl_verifypeer;
+ bool no_ssl_verifyhost;
+ std::string user_agent;
+ std::string ssl_cert;
+ std::string sslcerttype;
+ std::string sslcertpasswd;
+ std::string sslkey;
+ std::string sslkeytype;
+ std::string sslkeypasswd;
+ std::string sslengine;
+ bool sslengine_default;
+ xmlrpc_sslversion sslversion;
+ std::string cainfo;
+ std::string capath;
+ std::string randomfile;
+ std::string egdsocket;
+ std::string ssl_cipher_list;
+ unsigned int timeout;
+ } value;
+ struct {
+ bool network_interface;
+ bool no_ssl_verifypeer;
+ bool no_ssl_verifyhost;
+ bool user_agent;
+ bool ssl_cert;
+ bool sslcerttype;
+ bool sslcertpasswd;
+ bool sslkey;
+ bool sslkeytype;
+ bool sslkeypasswd;
+ bool sslengine;
+ bool sslengine_default;
+ bool sslversion;
+ bool cainfo;
+ bool capath;
+ bool randomfile;
+ bool egdsocket;
+ bool ssl_cipher_list;
+ bool timeout;
+ } present;
+ };
+
+ clientXmlTransport_curl(constrOpt const& opt);
+
+ clientXmlTransport_curl(std::string const networkInterface = "",
+ bool const noSslVerifyPeer = false,
+ bool const noSslVerifyHost = false,
+ std::string const userAgent = "");
+
+ ~clientXmlTransport_curl();
+
+private:
+ void
+ initialize(constrOpt const& opt);
+};
+
+/*===========================================================================
+ libwww
+===========================================================================*/
+
+class carriageParm_libwww0 : public xmlrpc_c::carriageParm_http0 {
+
+public:
+ carriageParm_libwww0(std::string const serverUrl);
+
+};
+
+class carriageParm_libwww0Ptr : public xmlrpc_c::carriageParm_http0Ptr {
+
+public:
+ carriageParm_libwww0Ptr();
+ carriageParm_libwww0Ptr(xmlrpc_c::carriageParm_libwww0 * const);
+
+ xmlrpc_c::carriageParm_libwww0 *
+ operator->() const;
+};
+
+class clientXmlTransport_libwww : public xmlrpc_c::clientXmlTransport_http {
+
+public:
+ clientXmlTransport_libwww(std::string const appname = "",
+ std::string const appversion = "");
+
+ ~clientXmlTransport_libwww();
+};
+
+/*===========================================================================
+ wininet
+===========================================================================*/
+
+class carriageParm_wininet0 : public xmlrpc_c::carriageParm_http0 {
+
+public:
+ carriageParm_wininet0(std::string const serverUrl);
+
+};
+
+class carriageParm_wininet0Ptr : public xmlrpc_c::carriageParm_http0Ptr {
+
+public:
+ carriageParm_wininet0Ptr();
+ carriageParm_wininet0Ptr(xmlrpc_c::carriageParm_wininet0 * const);
+
+ xmlrpc_c::carriageParm_wininet0 *
+ operator->() const;
+};
+
+class clientXmlTransport_wininet : public xmlrpc_c::clientXmlTransport_http {
+
+public:
+ clientXmlTransport_wininet(bool const allowInvalidSslCerts = false);
+
+ ~clientXmlTransport_wininet();
+};
+
+/*===========================================================================
+ pstream
+===========================================================================*/
+
+class packetSocket;
+
+class carriageParm_pstream : public xmlrpc_c::carriageParm {
+
+ // There are no parameters for carrying an RPC on a packet stream.
+ // There's only one way to carry it.
+};
+
+class carriageParm_pstreamPtr : public xmlrpc_c::carriageParmPtr {
+
+public:
+ carriageParm_pstreamPtr();
+ carriageParm_pstreamPtr(
+ xmlrpc_c::carriageParm_pstream * const carriageParmP);
+
+ xmlrpc_c::carriageParm_pstream *
+ operator->() const;
+};
+
+class clientXmlTransport_pstream : public xmlrpc_c::clientXmlTransport {
+
+public:
+ class constrOpt {
+ public:
+ constrOpt();
+
+ constrOpt & fd (int const& arg);
+
+ struct {
+ int fd;
+ } value;
+ struct {
+ bool fd;
+ } present;
+ };
+
+ clientXmlTransport_pstream(constrOpt const& opt);
+
+ ~clientXmlTransport_pstream();
+
+ void
+ call(xmlrpc_c::carriageParm * const carriageParmP,
+ std::string const& callXml,
+ std::string * const responseXmlP);
+
+private:
+ packetSocket * packetSocketP;
+};
+
+
+} // namespace
+#endif
Modified: freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/girerr.hpp
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/girerr.hpp (original)
+++ freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/girerr.hpp Fri May 23 16:56:24 2008
@@ -21,6 +21,11 @@
std::string _what;
};
+// throwf() always throws a girerr::error .
+
+void
+throwf(const char * const format, ...);
+
} // namespace
#endif
Modified: freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/girmem.hpp
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/girmem.hpp (original)
+++ freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/girmem.hpp Fri May 23 16:56:24 2008
@@ -19,6 +19,7 @@
# include <pthread.h>
typedef pthread_mutex_t girmem_lock;
#else
+# include <windows.h>
typedef CRITICAL_SECTION girmem_lock;
#endif
@@ -51,14 +52,20 @@
~autoObjectPtr();
void
- instantiate(girmem::autoObject * const objectP);
-
+ point(girmem::autoObject * const objectP);
+
+ void
+ unpoint();
+
autoObjectPtr
operator=(girmem::autoObjectPtr const& objectPtr);
girmem::autoObject *
operator->() const;
+ girmem::autoObject *
+ get() const;
+
protected:
girmem::autoObject * objectP;
};
Added: freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/inttypes.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/inttypes.h Fri May 23 16:56:24 2008
@@ -0,0 +1,19 @@
+#ifndef XMLRPC_INTTYPES_H_INCLUDED
+#define XMLRPC_INTTYPES_H_INCLUDED
+
+#ifdef _MSC_VER
+
+typedef unsigned short xmlrpc_uint16_t;
+typedef unsigned int xmlrpc_uint32_t;
+typedef unsigned __int64 xmlrpc_uint64_t;
+
+#else
+#include <inttypes.h>
+
+typedef uint16_t xmlrpc_uint16_t;
+typedef uint32_t xmlrpc_uint32_t;
+typedef uint64_t xmlrpc_uint64_t;
+
+#endif
+
+#endif
Modified: freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/oldcppwrapper.hpp
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/oldcppwrapper.hpp (original)
+++ freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/oldcppwrapper.hpp Fri May 23 16:56:24 2008
@@ -25,6 +25,7 @@
// -Bryan 2005.03.12.
+#include <cstdlib>
#include <string>
#include <xmlrpc-c/base.h>
#include <xmlrpc-c/client.h>
@@ -87,7 +88,7 @@
XmlRpcEnv (void) { xmlrpc_env_init(&mEnv); }
~XmlRpcEnv (void) { xmlrpc_env_clean(&mEnv); }
- bool faultOccurred (void) const { return mEnv.fault_occurred; };
+ bool faultOccurred (void) const {return (mEnv.fault_occurred != 0);};
bool hasFaultOccurred (void) const { return faultOccurred(); };
/* hasFaultOccurred() is for backward compatibility.
faultOccurred() is a superior name for this.
Added: freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/packetsocket.hpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/packetsocket.hpp Fri May 23 16:56:24 2008
@@ -0,0 +1,165 @@
+#ifndef PACKETSOCKET_HPP_INCLUDED
+#define PACKETSOCKET_HPP_INCLUDED
+
+/*============================================================================
+ packetsocket
+==============================================================================
+ This is a facility for communicating socket-style, with defined
+ packets like a datagram socket but with reliable delivery like a
+ stream socket. It's like a POSIX "sequential packet" socket, except
+ it is built on top of a stream socket, so it is usable on the many
+ systems that have stream sockets but not sequential packet sockets.
+============================================================================*/
+
+#include <sys/types.h>
+#include <string>
+#include <queue>
+
+#include <xmlrpc-c/girmem.hpp>
+
+namespace xmlrpc_c {
+
+class packet : public girmem::autoObject {
+
+public:
+ packet();
+
+ packet(const unsigned char * const data,
+ size_t const dataLength);
+
+ packet(const char * const data,
+ size_t const dataLength);
+
+ ~packet();
+
+ unsigned char *
+ getBytes() const { return this->bytes; }
+
+ size_t
+ getLength() const { return this->length; }
+
+ void
+ addData(const unsigned char * const data,
+ size_t const dataLength);
+
+private:
+ unsigned char * bytes; // malloc'ed
+ size_t length;
+ size_t allocSize;
+
+ void
+ initialize(const unsigned char * const data,
+ size_t const dataLength);
+};
+
+
+
+class packetPtr: public girmem::autoObjectPtr {
+
+public:
+ packetPtr();
+
+ explicit packetPtr(packet * const packetP);
+
+ packet *
+ operator->() const;
+};
+
+
+
+class packetSocket {
+/*----------------------------------------------------------------------------
+ This is an Internet communication vehicle that transmits individual
+ variable-length packets of text.
+
+ It is based on a stream socket.
+
+ It would be much better to use a kernel SOCK_SEQPACKET socket, but
+ Linux 2.4 does not have them.
+-----------------------------------------------------------------------------*/
+public:
+ packetSocket(int sockFd);
+
+ ~packetSocket();
+
+ void
+ writeWait(packetPtr const& packetPtr) const;
+
+ void
+ read(bool * const eofP,
+ bool * const gotPacketP,
+ packetPtr * const packetPP);
+
+ void
+ readWait(volatile const int * const interruptP,
+ bool * const eofP,
+ bool * const gotPacketP,
+ packetPtr * const packetPP);
+
+ void
+ readWait(volatile const int * const interruptP,
+ bool * const eofP,
+ packetPtr * const packetPP);
+
+ void
+ readWait(bool * const eofP,
+ packetPtr * const packetPP);
+
+private:
+ int sockFd;
+ // The kernel stream socket we use.
+ bool eof;
+ // The packet socket is at end-of-file for reads.
+ // 'readBuffer' is empty and there won't be any more data to fill
+ // it because the underlying stream socket is closed.
+ std::queue<packetPtr> readBuffer;
+ packetPtr packetAccumP;
+ // The receive packet we're currently accumulating; it will join
+ // 'readBuffer' when we've received the whole packet (and we've
+ // seen the END escape sequence so we know we've received it all).
+ // If we're not currently accumulating a packet (haven't seen a
+ // PKT escape sequence), this points to nothing.
+ bool inEscapeSeq;
+ // In our trek through the data read from the underlying stream
+ // socket, we are after an ESC character and before the end of the
+ // escape sequence. 'escAccum' shows what of the escape sequence
+ // we've seen so far.
+ bool inPacket;
+ // We're now receiving packet data from the underlying stream
+ // socket. We've seen a complete PKT escape sequence, but have not
+ // seen a complete END escape sequence since.
+ struct {
+ unsigned char bytes[3];
+ size_t len;
+ } escAccum;
+
+ void
+ bufferFinishedPacket();
+
+ void
+ takeSomeEscapeSeq(const unsigned char * const buffer,
+ size_t const length,
+ size_t * const bytesTakenP);
+
+ void
+ takeSomePacket(const unsigned char * const buffer,
+ size_t const length,
+ size_t * const bytesTakenP);
+
+ void
+ verifyNothingAccumulated();
+
+ void
+ processBytesRead(const unsigned char * const buffer,
+ size_t const bytesRead);
+
+ void
+ readFromFile();
+
+};
+
+
+
+} // namespace
+
+#endif
Modified: freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/registry.hpp
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/registry.hpp (original)
+++ freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/registry.hpp Fri May 23 16:56:24 2008
@@ -32,15 +32,6 @@
std::string signature() const { return _signature; };
std::string help() const { return _help; };
- // self() is a strange concession to the fact that we interface with
- // C code. C code needs a regular pointer to this method, but our
- // C++ interface carefully prevents one from making such a pointer,
- // since it would be an uncounted reference. So users of self() must
- // make sure that the reference it returns is always subordinate to a
- // methodPtr reference.
-
- xmlrpc_c::method * self();
-
protected:
std::string _signature;
std::string _help;
@@ -95,8 +86,6 @@
execute(std::string const& methodName,
xmlrpc_c::paramList const& paramList,
xmlrpc_c::value * const resultP) = 0;
-
- xmlrpc_c::defaultMethod * self(); // analogous to 'method' class
};
class defaultMethodPtr : public girmem::autoObjectPtr {
@@ -108,9 +97,14 @@
xmlrpc_c::defaultMethod *
operator->() const;
+
+ xmlrpc_c::defaultMethod *
+ get() const;
};
-class registry {
+
+
+class registry : public girmem::autoObject {
/*----------------------------------------------------------------------------
An Xmlrpc-c server method registry. An Xmlrpc-c server transport
(e.g. an HTTP server) uses this object to process an incoming
@@ -131,6 +125,20 @@
void
disableIntrospection();
+
+ class shutdown {
+ public:
+ virtual ~shutdown() = 0;
+ virtual void
+ doit(std::string const& comment,
+ void * const callInfo) const = 0;
+ };
+
+ void
+ setShutdown(const shutdown * const shutdownP);
+
+ void
+ setDialect(xmlrpc_dialect const dialect);
void
processCall(std::string const& body,
@@ -145,23 +153,37 @@
private:
xmlrpc_registry * c_registryP;
- /* Pointer to the C registry object we use to implement this
- object.
- */
+ // Pointer to the C registry object we use to implement this
+ // object.
std::list<xmlrpc_c::methodPtr> methodList;
- /* This is a list of all the method objects (actually, pointers
- to them). But since the real registry is the C registry object,
- all this list is for is to maintain references to the objects
- to which the C registry points so that they continue to exist.
- */
+ // This is a list of all the method objects (actually, pointers
+ // to them). But since the real registry is the C registry object,
+ // all this list is for is to maintain references to the objects
+ // to which the C registry points so that they continue to exist.
+
xmlrpc_c::defaultMethodPtr defaultMethodP;
- /* The real identifier of the default method is the C registry
- object; this member exists only to maintain a reference to the
- object to which the C registry points so that it will continue
- to exist.
- */
+ // The real identifier of the default method is the C registry
+ // object; this member exists only to maintain a reference to the
+ // object to which the C registry points so that it will continue
+ // to exist.
};
+
+
+class registryPtr : public girmem::autoObjectPtr {
+
+public:
+ registryPtr();
+
+ registryPtr(xmlrpc_c::registry * const registryP);
+
+ xmlrpc_c::registry *
+ operator->() const;
+
+ xmlrpc_c::registry *
+ get() const;
+};
+
} // namespace
#endif
Added: freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/select_int.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/select_int.h Fri May 23 16:56:24 2008
@@ -0,0 +1,24 @@
+#ifndef SELECT_INT_H_INCLUDED
+#define SELECT_INT_H_INCLUDED
+
+#ifndef WIN32
+#include <sys/select.h>
+#endif
+#include <signal.h>
+
+#include "xmlrpc-c/time_int.h"
+#ifdef WIN32
+#ifndef sigset_t
+typedef int sigset_t;
+#endif
+#endif
+
+int
+xmlrpc_pselect(int const n,
+ fd_set * const readfdsP,
+ fd_set * const writefdsP,
+ fd_set * const exceptfdsP,
+ const xmlrpc_timespec * const timeoutP,
+ sigset_t * const sigmaskP);
+
+#endif
Modified: freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/server.h
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/server.h (original)
+++ freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/server.h Fri May 23 16:56:24 2008
@@ -9,145 +9,121 @@
extern "C" {
#endif
-/*=========================================================================
-** XML-RPC Server Method Registry
-**=========================================================================
-** A method registry maintains a list of functions, and handles
-** dispatching. To build an XML-RPC server, just add an XML-RPC protocol
-** driver.
-**
-** Methods are C functions which take some combination of the following
-** parameters. All pointers except user_data belong to the library, and
-** must not be freed by the callback or used after the callback returns.
-**
-** env: An XML-RPC error-handling environment. No faults will be
-** set when the function is called. If an error occurs,
-** set an appropriate fault and return NULL. (If a fault is
-** set, the NULL return value will be enforced!)
-** host: The 'Host:' header passed by the XML-RPC client, or NULL,
-** if no 'Host:' header has been provided.
-** method_name: The name used to call this method.
-** user_data: The user_data used to register this method.
-** param_array: The parameters passed to this function, stored in an
-** XML-RPC array. You are *not* responsible for calling
-** xmlrpc_DECREF on this array.
-**
-** Return value: If no fault has been set, the function must return a
-** valid xmlrpc_value. This will be serialized, returned
-** to the caller, and xmlrpc_DECREF'd.
-*/
-
-/* A function to call before invoking a method for doing things like access
-** control or sanity checks. If a fault is set from this function, the
-** method will not be called and the fault will be returned. */
+typedef struct xmlrpc_registry xmlrpc_registry;
+
typedef void
-(*xmlrpc_preinvoke_method)(xmlrpc_env * env,
- const char * method_name,
- xmlrpc_value * param_array,
- void * user_data);
+(*xmlrpc_preinvoke_method)(xmlrpc_env * const envP,
+ const char * const methodName,
+ xmlrpc_value * const paramArrayP,
+ void * const userData);
-/* An ordinary method. */
typedef xmlrpc_value *
-(*xmlrpc_method)(xmlrpc_env * env,
- xmlrpc_value * param_array,
- void * user_data);
+(*xmlrpc_method1)(xmlrpc_env * const envP,
+ xmlrpc_value * const paramArrayP,
+ void * const serverInfo);
-/* A default method to call if no method can be found. */
typedef xmlrpc_value *
-(*xmlrpc_default_method)(xmlrpc_env * env,
- const char * host,
- const char * method_name,
- xmlrpc_value * param_array,
- void * user_data);
+(*xmlrpc_method2)(xmlrpc_env * const envP,
+ xmlrpc_value * const paramArrayP,
+ void * const serverInfo,
+ void * const callInfo);
-/* Our registry structure. This has no public members. */
-typedef struct _xmlrpc_registry xmlrpc_registry;
+typedef xmlrpc_method1 xmlrpc_method; /* backward compatibility */
+
+typedef xmlrpc_value *
+(*xmlrpc_default_method)(xmlrpc_env * const envP,
+ const char * const callInfoP,
+ const char * const methodName,
+ xmlrpc_value * const paramArrayP,
+ void * const serverInfo);
+
+extern unsigned int const xmlrpc_server_version_major;
+extern unsigned int const xmlrpc_server_version_minor;
+extern unsigned int const xmlrpc_server_version_point;
-/* Create a new method registry. */
xmlrpc_registry *
-xmlrpc_registry_new(xmlrpc_env * env);
+xmlrpc_registry_new(xmlrpc_env * const envP);
-/* Delete a method registry. */
void
-xmlrpc_registry_free(xmlrpc_registry * registry);
+xmlrpc_registry_free(xmlrpc_registry * const registryP);
-/* Disable introspection. The xmlrpc_registry has introspection
-** capability built-in. If you want to make nosy people work harder,
-** you can turn this off. */
void
-xmlrpc_registry_disable_introspection(xmlrpc_registry * registry);
+xmlrpc_registry_disable_introspection(xmlrpc_registry * const registryP);
-/* Register a method. The host parameter must be NULL (for now). You
-** are responsible for owning and managing user_data. The registry
-** will make internal copies of any other pointers it needs to
-** keep around. */
void
-xmlrpc_registry_add_method(xmlrpc_env * env,
- xmlrpc_registry * registry,
- const char * host,
- const char * method_name,
- xmlrpc_method method,
- void * user_data);
+xmlrpc_registry_add_method(xmlrpc_env * const envP,
+ xmlrpc_registry * const registryP,
+ const char * const host,
+ const char * const methodName,
+ xmlrpc_method const method,
+ void * const serverInfo);
+
+void
+xmlrpc_registry_add_method_w_doc(xmlrpc_env * const envP,
+ xmlrpc_registry * const registryP,
+ const char * const host,
+ const char * const methodName,
+ xmlrpc_method const method,
+ void * const serverInfo,
+ const char * const signatureString,
+ const char * const help);
+
+void
+xmlrpc_registry_add_method2(xmlrpc_env * const envP,
+ xmlrpc_registry * const registryP,
+ const char * const methodName,
+ xmlrpc_method2 method,
+ const char * const signatureString,
+ const char * const help,
+ void * const serverInfo);
+
+void
+xmlrpc_registry_set_default_method(xmlrpc_env * const envP,
+ xmlrpc_registry * const registryP,
+ xmlrpc_default_method const handler,
+ void * const userData);
+
+void
+xmlrpc_registry_set_preinvoke_method(xmlrpc_env * const envP,
+ xmlrpc_registry * const registryP,
+ xmlrpc_preinvoke_method const method,
+ void * const userData);
+
+
+typedef void xmlrpc_server_shutdown_fn(xmlrpc_env * const envP,
+ void * const context,
+ const char * const comment,
+ void * const callInfo);
+
+void
+xmlrpc_registry_set_shutdown(xmlrpc_registry * const registryP,
+ xmlrpc_server_shutdown_fn * const shutdownFn,
+ void * const context);
+
+void
+xmlrpc_registry_set_dialect(xmlrpc_env * const envP,
+ xmlrpc_registry * const registryP,
+ xmlrpc_dialect const dialect);
+
+/*----------------------------------------------------------------------------
+ Lower interface -- services to be used by an HTTP request handler
+-----------------------------------------------------------------------------*/
+
+void
+xmlrpc_registry_process_call2(xmlrpc_env * const envP,
+ xmlrpc_registry * const registryP,
+ const char * const xmlData,
+ size_t const xmlLen,
+ void * const callInfo,
+ xmlrpc_mem_block ** const outputPP);
-/* As above, but allow the user to supply introspection information.
-**
-** Signatures use their own little description language. It consists
-** of one-letter type code (similar to the ones used in xmlrpc_parse_value)
-** for the result, a colon, and zero or more one-letter type codes for
-** the parameters. For example:
-** i:ibdsAS86
-** If a function has more than one possible prototype, separate them with
-** commas:
-** i:,i:s,i:ii
-** If the function signature can't be represented using this language,
-** pass a single question mark:
-** ?
-** Help strings are ASCII text, and may contain HTML markup. */
-void
-xmlrpc_registry_add_method_w_doc(xmlrpc_env * env,
- xmlrpc_registry * registry,
- const char * host,
- const char * method_name,
- xmlrpc_method method,
- void * user_data,
- const char * signature,
- const char * help);
-
-/* Given a registry, a host name, and XML data; parse the <methodCall>,
-** find the appropriate method, call it, serialize the response, and
-** return it as an xmlrpc_mem_block. Most errors will be serialized
-** as <fault> responses. If a *really* bad error occurs, set a fault and
-** return NULL. (Actually, we currently give up with a fatal error,
-** but that should change eventually.)
-** The caller is responsible for destroying the memory block. */
xmlrpc_mem_block *
xmlrpc_registry_process_call(xmlrpc_env * const envP,
xmlrpc_registry * const registryP,
const char * const host,
- const char * const xml_data,
- size_t const xml_len);
-
-/* Define a default method for the specified registry. This will be invoked
-** if no other method matches. The user_data pointer is property of the
-** application, and will not be freed or manipulated by the registry. */
-void
-xmlrpc_registry_set_default_method(xmlrpc_env * env,
- xmlrpc_registry * registry,
- xmlrpc_default_method handler,
- void * user_data);
-
-/* Define a preinvoke method for the specified registry. This function will
-** be called before any method (either the default or a registered one) is
-** invoked. Applications can use this to do things like access control or
-** sanity checks. The user_data pointer is property of the application,
-** and will not be freed or manipulated by the registry. */
-void
-xmlrpc_registry_set_preinvoke_method(xmlrpc_env * env,
- xmlrpc_registry * registry,
- xmlrpc_preinvoke_method method,
- void * user_data);
+ const char * const xmlData,
+ size_t const xmlLen);
-
#ifdef __cplusplus
}
#endif
Modified: freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/server_abyss.h
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/server_abyss.h (original)
+++ freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/server_abyss.h Fri May 23 16:56:24 2008
@@ -1,33 +1,43 @@
+/*============================================================================
+ server_abyss.h
+==============================================================================
+ This declares the user interface to libxmlrpc_server_abyss, which
+ provides facilities for running an XML-RPC server based on the Xmlrpc-c
+ Abyss HTTP server.
+============================================================================*/
+
/* Copyright and license information is at the end of the file */
#ifndef XMLRPC_SERVER_ABYSS_H_INCLUDED
#define XMLRPC_SERVER_ABYSS_H_INCLUDED
-#include "xmlrpc-c/server.h"
+#ifdef WIN32
+#include <winsock.h> /* For XMLRPC_SOCKET (= SOCKET) */
+#endif
+
+#include <xmlrpc-c/config.h> /* For XMLRPC_SOCKET */
+#include <xmlrpc-c/abyss.h>
+#include <xmlrpc-c/server.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
-struct _TServer;
-
-/*=========================================================================
-** XML-RPC Server (based on Abyss)
-**=========================================================================
-** A simple XML-RPC server based on the Abyss web server. If errors
-** occur during server setup, the server will exit. In general, if you
-** want to use this API, you'll need to be familiar with Abyss.
-**
-** There are two ways to use Abyss:
-** 1) You can use the handy wrapper functions.
-** 2) You can set up Abyss yourself, and install the appropriate
-** handlers manually.
-*/
-
#define XMLRPC_SERVER_ABYSS_NO_FLAGS (0)
+/*=========================================================================
+** Global Initialization/Termination.
+**
+** These are not thread-safe. You call them at the beginning and end
+** of your program, when it is only one thread.
+**=======================================================================*/
+
+void
+xmlrpc_server_abyss_global_init(xmlrpc_env * const envP);
+void
+xmlrpc_server_abyss_global_term(void);
/*=========================================================================
** Basic Abyss Server Functions
@@ -53,7 +63,11 @@
unsigned int keepalive_max_conn;
unsigned int timeout;
xmlrpc_bool dont_advertise;
-
+ xmlrpc_bool socket_bound;
+ XMLRPC_SOCKET socket_handle;
+ const char * uri_path;
+ xmlrpc_bool chunk_response;
+ xmlrpc_bool enable_shutdown;
} xmlrpc_server_abyss_parms;
@@ -62,23 +76,81 @@
/* XMLRPC_APSIZE(xyz) is the minimum size a struct xmlrpc_server_abyss_parms
must be to include the 'xyz' member. This is essential to forward and
- backward compatbility, as new members will be added to the end of the
+ backward compatibility, as new members will be added to the end of the
struct in future releases. This is how the callee knows whether or
not the caller is new enough to have supplied a certain parameter.
*/
+/*=========================================================================
+** Simple server with Abyss under the covers
+**=======================================================================*/
+
void
xmlrpc_server_abyss(xmlrpc_env * const envP,
const xmlrpc_server_abyss_parms * const parms,
unsigned int const parm_size);
+/*=========================================================================
+** Object-oriented XML-RPC server with Abyss under the covers
+**=======================================================================*/
+
+typedef struct xmlrpc_server_abyss xmlrpc_server_abyss_t;
+
+void
+xmlrpc_server_abyss_create(xmlrpc_env * const envP,
+ const xmlrpc_server_abyss_parms * const parmsP,
+ unsigned int const parmSize,
+ xmlrpc_server_abyss_t ** const serverPP);
+
+void
+xmlrpc_server_abyss_destroy(xmlrpc_server_abyss_t * const serverP);
+
+void
+xmlrpc_server_abyss_run_server(xmlrpc_env * const envP,
+ xmlrpc_server_abyss_t * const serverP);
+
+void
+xmlrpc_server_abyss_terminate(xmlrpc_env * const envP,
+ xmlrpc_server_abyss_t * const serverP);
+
+void
+xmlrpc_server_abyss_reset_terminate(xmlrpc_env * const envP,
+ xmlrpc_server_abyss_t * const serverP);
+
+void
+xmlrpc_server_abyss_use_sigchld(xmlrpc_server_abyss_t * const serverP);
+
+
+typedef struct xmlrpc_server_abyss_sig xmlrpc_server_abyss_sig;
+
+void
+xmlrpc_server_abyss_setup_sig(
+ xmlrpc_env * const envP,
+ xmlrpc_server_abyss_t * const serverP,
+ xmlrpc_server_abyss_sig ** const oldHandlersPP);
+
+void
+xmlrpc_server_abyss_restore_sig(
+ const xmlrpc_server_abyss_sig * const oldHandlersP);
+
+
+
+/*=========================================================================
+** Functions to make an XML-RPC server out of your own Abyss server
+**=======================================================================*/
+
+void
+xmlrpc_server_abyss_set_handlers2(TServer * const srvP,
+ const char * const filename,
+ xmlrpc_registry * const registryP);
+
void
-xmlrpc_server_abyss_set_handlers(struct _TServer * const srvP,
+xmlrpc_server_abyss_set_handlers(TServer * const serverP,
xmlrpc_registry * const registryP);
void
xmlrpc_server_abyss_set_handler(xmlrpc_env * const envP,
- struct _TServer * const srvP,
+ TServer * const serverP,
const char * const filename,
xmlrpc_registry * const registryP);
@@ -109,8 +181,8 @@
** function.
**/
void
-xmlrpc_server_abyss_run_first(void (runfirst(void *)),
- void * const runfirstArg);
+xmlrpc_server_abyss_run_first(runfirstFn const runfirst,
+ void * const runfirstArg);
/*=========================================================================
** Method Registry
@@ -145,18 +217,18 @@
/* A quick & easy shorthand for adding a method. Depending on
** how you've configured your copy of Abyss, it's probably not safe to
** call this method after calling xmlrpc_server_abyss_run. */
-void xmlrpc_server_abyss_add_method (char *method_name,
- xmlrpc_method method,
- void *user_data);
+void xmlrpc_server_abyss_add_method (char * const method_name,
+ xmlrpc_method const method,
+ void * const user_data);
/* As above, but provide documentation (see xmlrpc_registry_add_method_w_doc
** for more information). You should really use this one. */
extern void
-xmlrpc_server_abyss_add_method_w_doc (char *method_name,
- xmlrpc_method method,
- void *user_data,
- char *signature,
- char *help);
+xmlrpc_server_abyss_add_method_w_doc (char * const method_name,
+ xmlrpc_method const method,
+ void * const user_data,
+ char * const signature,
+ char * const help);
/*=========================================================================
** Content Handlers
Modified: freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/server_abyss.hpp
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/server_abyss.hpp (original)
+++ freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/server_abyss.hpp Fri May 23 16:56:24 2008
@@ -1,5 +1,11 @@
#ifndef SERVER_ABYSS_HPP_INCLUDED
#define SERVER_ABYSS_HPP_INCLUDED
+
+#ifdef WIN32
+#include <winsock.h> // For XMLRPC_SOCKET (= SOCKET)
+#endif
+
+#include "xmlrpc-c/config.h" // For XMLRPC_SOCKET
#include "xmlrpc-c/base.hpp"
#include "abyss.h"
@@ -8,6 +14,52 @@
class serverAbyss {
public:
+ class constrOpt {
+ public:
+ constrOpt();
+
+ constrOpt & registryPtr (xmlrpc_c::registryPtr const& arg);
+ constrOpt & registryP (const xmlrpc_c::registry * const& arg);
+ constrOpt & socketFd (XMLRPC_SOCKET const& arg);
+ constrOpt & portNumber (unsigned int const& arg);
+ constrOpt & logFileName (std::string const& arg);
+ constrOpt & keepaliveTimeout (unsigned int const& arg);
+ constrOpt & keepaliveMaxConn (unsigned int const& arg);
+ constrOpt & timeout (unsigned int const& arg);
+ constrOpt & dontAdvertise (bool const& arg);
+ constrOpt & uriPath (std::string const& arg);
+ constrOpt & chunkResponse (bool const& arg);
+
+ struct value {
+ xmlrpc_c::registryPtr registryPtr;
+ const xmlrpc_c::registry * registryP;
+ XMLRPC_SOCKET socketFd;
+ unsigned int portNumber;
+ std::string logFileName;
+ unsigned int keepaliveTimeout;
+ unsigned int keepaliveMaxConn;
+ unsigned int timeout;
+ bool dontAdvertise;
+ std::string uriPath;
+ bool chunkResponse;
+ } value;
+ struct {
+ bool registryPtr;
+ bool registryP;
+ bool socketFd;
+ bool portNumber;
+ bool logFileName;
+ bool keepaliveTimeout;
+ bool keepaliveMaxConn;
+ bool timeout;
+ bool dontAdvertise;
+ bool uriPath;
+ bool chunkResponse;
+ } present;
+ };
+
+ serverAbyss(constrOpt const& opt);
+
serverAbyss(
xmlrpc_c::registry const& registry,
unsigned int const portNumber = 8080,
@@ -15,32 +67,67 @@
unsigned int const keepaliveTimeout = 0,
unsigned int const keepaliveMaxConn = 0,
unsigned int const timeout = 0,
- bool const dontAdvertise = false
+ bool const dontAdvertise = false,
+ bool const socketBound = false,
+ XMLRPC_SOCKET const socketFd = 0
);
~serverAbyss();
- void run();
+ void
+ run();
+
+ void
+ runOnce();
+
+ void
+ runConn(int const socketFd);
+
+ void
+ terminate();
+ class shutdown : public xmlrpc_c::registry::shutdown {
+ public:
+ shutdown(xmlrpc_c::serverAbyss * const severAbyssP);
+ virtual ~shutdown();
+ void doit(std::string const& comment, void * const callInfo) const;
+ private:
+ xmlrpc_c::serverAbyss * const serverAbyssP;
+ };
+
private:
- // We rely on the creator to keep the registry object around as
- // long as the server object is, so that this pointer is valid.
- // We need to use some kind of automatic handle instead.
-
- const xmlrpc_c::registry * registryP;
-
- std::string configFileName;
- std::string logFileName;
- unsigned int portNumber;
- unsigned int keepaliveTimeout;
- unsigned int keepaliveMaxConn;
- unsigned int timeout;
- bool dontAdvertise;
+ // The user has the choice of supplying the registry by plain pointer
+ // (and managing the object's existence himself) or by autoObjectPtr
+ // (with automatic management). 'registryPtr' exists here only to
+ // maintain a reference count in the case that the user supplied an
+ // autoObjectPtr. The object doesn't reference the C++ registry
+ // object except during construction, because the C registry is the
+ // real registry.
+ xmlrpc_c::registryPtr registryPtr;
+
+ TServer cServer;
+
+ void
+ setAdditionalServerParms(constrOpt const& opt);
+
+ void
+ initialize(constrOpt const& opt);
};
void
server_abyss_set_handlers(TServer * const srvP,
- xmlrpc_c::registry const& registry);
+ xmlrpc_c::registry const& registry,
+ std::string const& uriPath = "/RPC2");
+
+void
+server_abyss_set_handlers(TServer * const srvP,
+ const xmlrpc_c::registry * const registryP,
+ std::string const& uriPath = "/RPC2");
+
+void
+server_abyss_set_handlers(TServer * const srvP,
+ xmlrpc_c::registryPtr const registryPtr,
+ std::string const& uriPath = "/RPC2");
} // namespace
Added: freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/server_pstream.hpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/server_pstream.hpp Fri May 23 16:56:24 2008
@@ -0,0 +1,75 @@
+#ifndef SERVER_PSTREAM_HPP_INCLUDED
+#define SERVER_PSTREAM_HPP_INCLUDED
+
+#ifdef WIN32
+#include <winsock.h> /* For XMLRPC_SOCKET (= SOCKET) */
+#endif
+
+#include <xmlrpc-c/config.h> /* For XMLRPC_SOCKET */
+#include <xmlrpc-c/registry.hpp>
+#include <xmlrpc-c/packetsocket.hpp>
+
+namespace xmlrpc_c {
+
+class serverPstreamConn {
+
+public:
+
+ class constrOpt {
+ public:
+ constrOpt();
+
+ constrOpt & registryPtr (xmlrpc_c::registryPtr const& arg);
+ constrOpt & registryP (const xmlrpc_c::registry * const& arg);
+ constrOpt & socketFd (XMLRPC_SOCKET const& arg);
+
+ struct value {
+ xmlrpc_c::registryPtr registryPtr;
+ const xmlrpc_c::registry * registryP;
+ XMLRPC_SOCKET socketFd;
+ } value;
+ struct {
+ bool registryPtr;
+ bool registryP;
+ bool socketFd;
+ } present;
+ };
+
+ serverPstreamConn(constrOpt const& opt);
+
+ ~serverPstreamConn();
+
+ void
+ runOnce(volatile const int * const interruptP,
+ bool * const eofP);
+
+ void
+ runOnce(bool * const eofP);
+
+private:
+
+ // 'registryP' is what we actually use; 'registryHolder' just holds a
+ // reference to 'registryP' so the registry doesn't disappear while
+ // this server exists. But note that if the creator doesn't supply
+ // a registryPtr, 'registryHolder' is just a placeholder variable and
+ // the creator is responsible for making sure the registry doesn't
+ // go anywhere while the server exists.
+
+ registryPtr registryHolder;
+ const registry * registryP;
+
+ packetSocket * packetSocketP;
+ // The packet socket over which we received RPCs.
+ // This is permanently connected to our fixed client.
+
+ void
+ establishRegistry(constrOpt const& opt);
+
+ void
+ establishPacketSocket(constrOpt const& opt);
+};
+
+
+} // namespace
+
+#endif
Added: freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/sleep_int.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/sleep_int.h Fri May 23 16:56:24 2008
@@ -0,0 +1,7 @@
+#ifndef SLEEP_INT_H_INCLUDED
+#define SLEEP_INT_H_INCLUDED
+
+void
+xmlrpc_millisecond_sleep(unsigned int const milliseconds);
+
+#endif
Added: freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/string_int.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/string_int.h Fri May 23 16:56:24 2008
@@ -0,0 +1,84 @@
+#ifndef XMLRPC_C_STRING_INT_H_INCLUDED
+#define XMLRPC_C_STRING_INT_H_INCLUDED
+
+
+#include <stdarg.h>
+#include <string.h>
+
+#include "xmlrpc_config.h"
+#include "c_util.h"
+#include "bool.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern const char * const xmlrpc_strsol;
+
+void
+xmlrpc_vasprintf(const char ** const retvalP,
+ const char * const fmt,
+ va_list varargs);
+
+void GNU_PRINTF_ATTR(2,3)
+xmlrpc_asprintf(const char ** const retvalP, const char * const fmt, ...);
+
+const char *
+xmlrpc_strdupnull(const char * const string);
+
+void
+xmlrpc_strfree(const char * const string);
+
+void
+xmlrpc_strfreenull(const char * const string);
+
+static __inline__ bool
+xmlrpc_streq(const char * const a,
+ const char * const b) {
+ return (strcmp(a, b) == 0);
+}
+
+static __inline__ bool
+xmlrpc_memeq(const void * const a,
+ const void * const b,
+ size_t const size) {
+
+ return (memcmp(a, b, size) == 0);
+}
+
+static __inline__ bool
+xmlrpc_strcaseeq(const char * const a,
+ const char * const b) {
+#if HAVE_STRCASECMP
+ return (strcasecmp(a, b) == 0);
+#elif HAVE__STRICMP
+ return (_stricmp(a, b) == 0);
+#elif HAVE_STRICMP
+ return (stricmp(a, b) == 0);
+#else
+ #error "This platform has no known case-independent string compare fn"
+#endif
+}
+
+static __inline__ bool
+xmlrpc_strneq(const char * const a,
+ const char * const b,
+ size_t const len) {
+ return (strncmp(a, b, len) == 0);
+}
+
+const char *
+xmlrpc_makePrintable(const char * const input);
+
+const char *
+xmlrpc_makePrintable_lp(const char * const input,
+ size_t const inputLength);
+
+const char *
+xmlrpc_makePrintableChar(char const input);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Added: freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/time_int.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/time_int.h Fri May 23 16:56:24 2008
@@ -0,0 +1,35 @@
+#ifndef TIME_H_INCLUDED
+#define TIME_H_INCLUDED
+
+#include <time.h>
+
+#include "xmlrpc_config.h"
+#include "xmlrpc-c/util.h"
+#include "int.h"
+
+#if HAVE_TIMESPEC
+ typedef struct timespec xmlrpc_timespec;
+#else
+ typedef struct {
+ uint32_t tv_sec;
+ uint32_t tv_nsec;
+ } xmlrpc_timespec;
+#endif
+
+void
+xmlrpc_gettimeofday(xmlrpc_timespec * const todP);
+
+void
+xmlrpc_timegm(const struct tm * const brokenTime,
+ time_t * const timeValueP,
+ const char ** const errorP);
+
+void
+xmlrpc_localtime(time_t const datetime,
+ struct tm * const tmP);
+
+void
+xmlrpc_gmtime(time_t const datetime,
+ struct tm * const resultP);
+
+#endif
Modified: freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/timeout.hpp
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/timeout.hpp (original)
+++ freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/timeout.hpp Fri May 23 16:56:24 2008
@@ -8,9 +8,10 @@
timeout() : finite(false) {}
timeout(unsigned int const duration) : duration(duration) {}
+ // 'duration' is the timeout time in milliseconds
bool finite;
- unsigned int duration;
+ unsigned int duration; // in milliseconds
};
Modified: freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/transport.h
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/transport.h (original)
+++ freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/transport.h Fri May 23 16:56:24 2008
@@ -6,7 +6,8 @@
extern "C" {
#endif
-#include "xmlrpc-c/base.h"
+#include <xmlrpc-c/util.h>
+#include <xmlrpc-c/client.h>
struct xmlrpc_call_info;
@@ -16,12 +17,16 @@
** Transport function type declarations.
**=========================================================================
*/
+typedef void (*xmlrpc_transport_setup)(xmlrpc_env * const envP);
+
+typedef void (*xmlrpc_transport_teardown)(void);
+
typedef void (*xmlrpc_transport_create)(
xmlrpc_env * const envP,
int const flags,
const char * const appname,
const char * const appversion,
- const struct xmlrpc_xportparms * const transportparmsP,
+ const void * const transportparmsP,
size_t const transportparm_size,
struct xmlrpc_client_transport ** const handlePP);
@@ -58,14 +63,20 @@
xmlrpc_timeoutType const timeoutType,
xmlrpc_timeout const timeout);
+typedef void (*xmlrpc_transport_set_interrupt)(
+ struct xmlrpc_client_transport * const clientTransportP,
+ int * const interruptP);
struct xmlrpc_client_transport_ops {
+ xmlrpc_transport_setup setup_global_const;
+ xmlrpc_transport_teardown teardown_global_const;
xmlrpc_transport_create create;
xmlrpc_transport_destroy destroy;
xmlrpc_transport_send_request send_request;
xmlrpc_transport_call call;
xmlrpc_transport_finish_asynch finish_asynch;
+ xmlrpc_transport_set_interrupt set_interrupt;
};
#ifdef __cplusplus
Added: freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/util.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/util.h Fri May 23 16:56:24 2008
@@ -0,0 +1,328 @@
+/*=============================================================================
+ xmlrpc-c/util.h
+===============================================================================
+
+ This is the interface to the libxmlrpc_util library, which contains
+ utility routines that have nothing to do with XML-RPC. The library
+ exists because other Xmlrpc-c libraries use the utilities.
+
+ By Bryan Henderson, San Jose, CA 05.09.21.
+
+ Contributed to the public domain by its author.
+=============================================================================*/
+
+#ifndef XMLRPC_C_UTIL_H_INCLUDED
+#define XMLRPC_C_UTIL_H_INCLUDED
+
+#include <sys/types.h>
+#include <stdarg.h>
+
+#include <xmlrpc-c/config.h> /* Defines XMLRPC_HAVE_WCHAR */
+#include <xmlrpc-c/c_util.h> /* for GNU_PRINTF_ATTR */
+
+#if XMLRPC_HAVE_WCHAR
+#include <wchar.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*=========================================================================
+** C struct size computations
+**=======================================================================*/
+
+/* Use XMLRPC_STRUCT_MEMBER_SIZE() to determine how big a structure is
+ up to and including a specified member. E.g. if you have
+ struct mystruct {int red; int green; int blue};, then
+ XMLRPC_STRUCT_MEMBER_SIZE(mystruct, green) is (8).
+*/
+
+#define _XMLRPC_STRUCT_MEMBER_OFFSET(TYPE, MBRNAME) \
+ ((unsigned long)(char*)&((TYPE *)0)->MBRNAME)
+#define _XMLRPC_STRUCT_MEMBER_SIZE(TYPE, MBRNAME) \
+ sizeof(((TYPE *)0)->MBRNAME)
+#define XMLRPC_STRUCTSIZE(TYPE, MBRNAME) \
+ (_XMLRPC_STRUCT_MEMBER_OFFSET(TYPE, MBRNAME) + \
+ _XMLRPC_STRUCT_MEMBER_SIZE(TYPE, MBRNAME))
+
+/*=========================================================================
+** Assertions and Debugging
+**=========================================================================
+** Note that an assertion is _not_ a directive to check a condition and
+** crash if it isn't true. It is an assertion that the condition _is_
+** true. This assertion helps people to read the code. The program
+** may also check the assertion as it runs, and if it conflicts with reality,
+** recognize that the program is incorrect and abort it. In practice,
+** it does this checking when the program was compiled without the NDEBUG
+** macro defined.
+*/
+
+#ifndef NDEBUG
+
+#define XMLRPC_ASSERT(cond) \
+ do \
+ if (!(cond)) \
+ xmlrpc_assertion_failed(__FILE__, __LINE__); \
+ while (0)
+
+#else
+#define XMLRPC_ASSERT(cond) while (0) {}
+#endif
+
+void
+xmlrpc_assertion_failed(const char * const fileName,
+ int const lineNumber);
+
+/* Validate a pointer. */
+#define XMLRPC_ASSERT_PTR_OK(ptr) \
+ XMLRPC_ASSERT((ptr) != NULL)
+
+
+/*=========================================================================
+** xmlrpc_env
+**=========================================================================
+** XML-RPC represents runtime errors as <fault> elements. These contain
+** <faultCode> and <faultString> elements.
+**
+** Since we need as much thread-safety as possible, we borrow an idea from
+** CORBA--we store exception information in an "environment" object.
+** You'll pass this to many different functions, and it will get filled
+** out appropriately.
+**
+** For example:
+**
+** xmlrpc_env env;
+**
+** xmlrpc_env_init(&env);
+**
+** xmlrpc_do_something(&env);
+** if (env.fault_occurred)
+** report_error_appropriately();
+**
+** xmlrpc_env_clean(&env);
+*/
+
+#define XMLRPC_INTERNAL_ERROR (-500)
+#define XMLRPC_TYPE_ERROR (-501)
+#define XMLRPC_INDEX_ERROR (-502)
+#define XMLRPC_PARSE_ERROR (-503)
+#define XMLRPC_NETWORK_ERROR (-504)
+#define XMLRPC_TIMEOUT_ERROR (-505)
+#define XMLRPC_NO_SUCH_METHOD_ERROR (-506)
+#define XMLRPC_REQUEST_REFUSED_ERROR (-507)
+#define XMLRPC_INTROSPECTION_DISABLED_ERROR (-508)
+#define XMLRPC_LIMIT_EXCEEDED_ERROR (-509)
+#define XMLRPC_INVALID_UTF8_ERROR (-510)
+
+typedef struct _xmlrpc_env {
+ int fault_occurred;
+ int fault_code;
+ char * fault_string;
+} xmlrpc_env;
+
+/* Initialize and destroy the contents of the provided xmlrpc_env object.
+** These functions will never fail. */
+void xmlrpc_env_init (xmlrpc_env* env);
+void xmlrpc_env_clean (xmlrpc_env* const env);
+
+/* Fill out an xmlrpc_fault with the specified values, and set the
+** fault_occurred flag. This function will make a private copy of 'string',
+** so you retain responsibility for your copy. */
+void
+xmlrpc_env_set_fault(xmlrpc_env * const env,
+ int const faultCode,
+ const char * const faultDescription);
+
+/* The same as the above, but using varargs */
+void
+xmlrpc_set_fault_formatted_v(xmlrpc_env * const envP,
+ int const code,
+ const char * const format,
+ va_list const args);
+
+/* The same as the above, but using a printf-style format string. */
+void
+xmlrpc_env_set_fault_formatted(xmlrpc_env * const envP,
+ int const code,
+ const char * const format,
+ ...) GNU_PRINTF_ATTR(3,4);
+
+/* This one infers XMLRPC_INTERNAL_ERROR and has a shorter name.
+ So a call takes up less source code space.
+*/
+void
+xmlrpc_faultf(xmlrpc_env * const envP,
+ const char * const format,
+ ...) GNU_PRINTF_ATTR(2,3);
+
+/* A simple debugging assertion. */
+#define XMLRPC_ASSERT_ENV_OK(envP) \
+ XMLRPC_ASSERT((envP) != NULL && \
+ (envP->fault_string == NULL) && \
+ !(envP)->fault_occurred)
+
+/* This version must *not* interpret 'str' as a format string, to avoid
+** several evil attacks. */
+#define XMLRPC_FAIL(env,code,str) \
+ do { xmlrpc_env_set_fault((env),(code),(str)); goto cleanup; } while (0)
+
+#define XMLRPC_FAIL1(env,code,str,arg1) \
+ do { \
+ xmlrpc_env_set_fault_formatted((env),(code),(str),(arg1)); \
+ goto cleanup; \
+ } while (0)
+
+#define XMLRPC_FAIL2(env,code,str,arg1,arg2) \
+ do { \
+ xmlrpc_env_set_fault_formatted((env),(code),(str),(arg1),(arg2)); \
+ goto cleanup; \
+ } while (0)
+
+#define XMLRPC_FAIL3(env,code,str,arg1,arg2,arg3) \
+ do { \
+ xmlrpc_env_set_fault_formatted((env),(code), \
+ (str),(arg1),(arg2),(arg3)); \
+ goto cleanup; \
+ } while (0)
+
+#if !defined(__cplusplus)
+#if defined(__GNUC__)
+#define XMLRPC_FAILF( env, code, fmt, ... ) \
+ do { \
+ xmlrpc_env_set_fault_formatted((env), (code), (fmt), \
+ ##__VA_ARGS__ ); \
+ goto cleanup; \
+ } while (0)
+#endif
+#endif
+
+#define XMLRPC_FAIL_IF_NULL(ptr,env,code,str) \
+ do { \
+ if ((ptr) == NULL) \
+ XMLRPC_FAIL((env),(code),(str)); \
+ } while (0)
+
+#define XMLRPC_FAIL_IF_FAULT(env) \
+ do { if ((env)->fault_occurred) goto cleanup; } while (0)
+
+
+/*=========================================================================
+** xmlrpc_mem_block
+**=========================================================================
+** A resizable chunk of memory. This is mostly used internally, but it is
+** also used by the public API in a few places.
+** The struct fields are private!
+*/
+
+typedef struct _xmlrpc_mem_block {
+ size_t _size;
+ size_t _allocated;
+ void* _block;
+} xmlrpc_mem_block;
+
+/* Allocate a new xmlrpc_mem_block. */
+xmlrpc_mem_block* xmlrpc_mem_block_new (xmlrpc_env* const env, size_t const size);
+
+/* Destroy an existing xmlrpc_mem_block, and everything it contains. */
+void xmlrpc_mem_block_free (xmlrpc_mem_block* const block);
+
+/* Initialize the contents of the provided xmlrpc_mem_block. */
+void xmlrpc_mem_block_init
+ (xmlrpc_env* const env, xmlrpc_mem_block* const block, size_t const size);
+
+/* Deallocate the contents of the provided xmlrpc_mem_block, but not the
+** block itself. */
+void xmlrpc_mem_block_clean (xmlrpc_mem_block* const block);
+
+/* Get the size and contents of the xmlrpc_mem_block. */
+size_t
+xmlrpc_mem_block_size(const xmlrpc_mem_block * const block);
+
+void *
+xmlrpc_mem_block_contents(const xmlrpc_mem_block * const block);
+
+/* Resize an xmlrpc_mem_block, preserving as much of the contents as
+** possible. */
+void xmlrpc_mem_block_resize
+ (xmlrpc_env* const env, xmlrpc_mem_block* const block, size_t const size);
+
+/* Append data to an existing xmlrpc_mem_block. */
+void xmlrpc_mem_block_append
+ (xmlrpc_env* const env, xmlrpc_mem_block* const block, const void * const data, size_t const len);
+
+#define XMLRPC_MEMBLOCK_NEW(type,env,size) \
+ xmlrpc_mem_block_new((env), sizeof(type) * (size))
+#define XMLRPC_MEMBLOCK_FREE(type,block) \
+ xmlrpc_mem_block_free(block)
+#define XMLRPC_MEMBLOCK_INIT(type,env,block,size) \
+ xmlrpc_mem_block_init((env), (block), sizeof(type) * (size))
+#define XMLRPC_MEMBLOCK_CLEAN(type,block) \
+ xmlrpc_mem_block_clean(block)
+#define XMLRPC_MEMBLOCK_SIZE(type,block) \
+ (xmlrpc_mem_block_size(block) / sizeof(type))
+#define XMLRPC_MEMBLOCK_CONTENTS(type,block) \
+ ((type*) xmlrpc_mem_block_contents(block))
+#define XMLRPC_MEMBLOCK_RESIZE(type,env,block,size) \
+ xmlrpc_mem_block_resize(env, block, sizeof(type) * (size))
+#define XMLRPC_MEMBLOCK_APPEND(type,env,block,data,size) \
+ xmlrpc_mem_block_append(env, block, data, sizeof(type) * (size))
+
+/* Here are some backward compatibility definitions. These longer names
+ used to be the only ones and typed memory blocks were considered
+ special.
+*/
+#define XMLRPC_TYPED_MEM_BLOCK_NEW(type,env,size) \
+ XMLRPC_MEMBLOCK_NEW(type,env,size)
+#define XMLRPC_TYPED_MEM_BLOCK_FREE(type,block) \
+ XMLRPC_MEMBLOCK_FREE(type,block)
+#define XMLRPC_TYPED_MEM_BLOCK_INIT(type,env,block,size) \
+ XMLRPC_MEMBLOCK_INIT(type,env,block,size)
+#define XMLRPC_TYPED_MEM_BLOCK_CLEAN(type,block) \
+ XMLRPC_MEMBLOCK_CLEAN(type,block)
+#define XMLRPC_TYPED_MEM_BLOCK_SIZE(type,block) \
+ XMLRPC_MEMBLOCK_SIZE(type,block)
+#define XMLRPC_TYPED_MEM_BLOCK_CONTENTS(type,block) \
+ XMLRPC_MEMBLOCK_CONTENTS(type,block)
+#define XMLRPC_TYPED_MEM_BLOCK_RESIZE(type,env,block,size) \
+ XMLRPC_MEMBLOCK_RESIZE(type,env,block,size)
+#define XMLRPC_TYPED_MEM_BLOCK_APPEND(type,env,block,data,size) \
+ XMLRPC_MEMBLOCK_APPEND(type,env,block,data,size)
+
+
+/*=========================================================================
+** UTF-8 Encoding and Decoding
+**=======================================================================*/
+
+void
+xmlrpc_validate_utf8(xmlrpc_env * const envP,
+ const char * const utf8Data,
+ size_t const utf8Len);
+
+/* Decode a UTF-8 string. */
+xmlrpc_mem_block *
+xmlrpc_utf8_to_wcs(xmlrpc_env * const envP,
+ const char * const utf8_data,
+ size_t const utf8_len);
+
+/* Encode a UTF-8 string. */
+
+#if XMLRPC_HAVE_WCHAR
+xmlrpc_mem_block *
+xmlrpc_wcs_to_utf8(xmlrpc_env * const envP,
+ const wchar_t * const wcsData,
+ size_t const wcsLen);
+#endif
+
+void
+xmlrpc_force_to_utf8(char * const buffer);
+
+void
+xmlrpc_force_to_xml_chars(char * const buffer);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Added: freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/util_int.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/util_int.h Fri May 23 16:56:24 2008
@@ -0,0 +1,13 @@
+#ifndef XMLRPC_C_UTIL_INT_H_INCLUDED
+#define XMLRPC_C_UTIL_INT_H_INCLUDED
+
+#include "util.h"
+
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+
+/* When we deallocate a pointer in a struct, we often replace it with
+** this and throw in a few assertions here and there. */
+#define XMLRPC_BAD_POINTER ((void*) 0xDEADBEEF)
+
+#endif
Modified: freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/xml.hpp
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/xml.hpp (original)
+++ freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/xml.hpp Fri May 23 16:56:24 2008
@@ -13,6 +13,12 @@
std::string * const callXmlP);
void
+generateCall(std::string const& methodName,
+ xmlrpc_c::paramList const& paramList,
+ xmlrpc_dialect const dialect,
+ std::string * const callXmlP);
+
+void
parseSuccessfulResponse(std::string const& responseXml,
xmlrpc_c::value * const resultP);
Modified: freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/xmlparser.h
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/xmlparser.h (original)
+++ freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/xmlparser.h Fri May 23 16:56:24 2008
@@ -27,11 +27,12 @@
typedef struct _xml_element xml_element;
/* Destroy an xml_element. */
-void xml_element_free (xml_element *elem);
+void xml_element_free (xml_element * const elem);
/* Return a pointer to the element's name. Do not free this pointer!
** This pointer should point to standard ASCII or UTF-8 data. */
-char *xml_element_name (xml_element *elem);
+const char *
+xml_element_name(const xml_element * const elemP);
/* Return the xml_element's CDATA. Do not free this pointer!
** This pointer should point to standard ASCII or UTF-8 data.
@@ -46,8 +47,11 @@
char *xml_element_cdata (xml_element *elem);
/* Return the xml_element's child elements. Do not free this pointer! */
-size_t xml_element_children_size (xml_element *elem);
-xml_element **xml_element_children (xml_element *elem);
+size_t
+xml_element_children_size(const xml_element * const elemP);
+
+xml_element **
+xml_element_children(const xml_element * const elemP);
/*=========================================================================
@@ -58,7 +62,11 @@
** You are responsible for calling xml_element_free on the returned pointer.
*/
-xml_element *xml_parse (xmlrpc_env *env, const char *xml_data, int xml_len);
+void
+xml_parse(xmlrpc_env * const envP,
+ const char * const xmlData,
+ size_t const xmlDataLen,
+ xml_element ** const resultPP);
/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
Added: freeswitch/trunk/libs/xmlrpc-c/irix-common.make
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/irix-common.make Fri May 23 16:56:24 2008
@@ -0,0 +1,31 @@
+# -*-makefile-*- <-- an Emacs control
+
+# See unix-common.make for an explanation of this file. This file is
+# analogous to unix-common.make, but is for an Irix system.
+
+SONAME = $(@:%.$(MAJ):%)
+
+SHLIB_CMD = $(CCLD) $(LDFLAGS_SHLIB) -o $@ $^ $(LADD)
+
+SHLIB_LE_TARGETS = $(call shliblefn, $(SHARED_LIBS_TO_BUILD))
+
+$(SHLIB_LE_TARGETS):%:%.$(MAJ)
+ rm -f $@
+ $(LN_S) $< $@
+
+
+.PHONY: $(SHLIB_INSTALL_TARGETS)
+.PHONY: install-shared-libraries
+
+SHLIB_INSTALL_TARGETS = $(SHARED_LIBS_TO_INSTALL:%=%/install)
+
+#SHLIB_INSTALL_TARGETS is like "libfoo/install libbar/install"
+
+install-shared-libraries: $(SHLIB_INSTALL_TARGETS)
+
+$(SHLIB_INSTALL_TARGETS):%/install:%.$(SHLIB_SUFFIX).$(MAJ)
+# $< is a library file name, e.g. libfoo.so.3.1 .
+ $(INSTALL_SHLIB) $< $(DESTDIR)$(LIBINST_DIR)/$<
+ cd $(DESTDIR)$(LIBINST_DIR); \
+ rm -f $< $(<:%.$(MAJ)=%); \
+ $(LN_S) $< $(<:%.$(MAJ)=%)
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/Makefile
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/Makefile (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/Makefile Fri May 23 16:56:24 2008
@@ -1,11 +1,15 @@
-ifeq ($(SRCDIR)x,x)
-SRCDIR = $(CURDIR)/..
-endif
-SUBDIR = lib
-
-include $(SRCDIR)/Makefile.config
-
-SUBDIRS = util
+ifeq ($(SRCDIR),)
+ updir = $(shell echo $(dir $(1)) | sed 's/.$$//')
+ SRCDIR := $(call updir,$(CURDIR))
+ BLDDIR := $(SRCDIR)
+endif
+SUBDIR := lib
+
+include $(BLDDIR)/config.mk
+
+# Build up SUBDIRS:
+SUBDIRS =
+SUBDIRS += util libutil
ifeq ($(ENABLE_ABYSS_SERVER),yes)
SUBDIRS += abyss
endif
@@ -18,36 +22,37 @@
ifeq ($(MUST_BUILD_LIBWWW_CLIENT),yes)
SUBDIRS += libwww_transport
endif
-ifneq ($(ENABLE_LIBXML2),yes)
+ifneq ($(ENABLE_LIBXML2_BACKEND),yes)
SUBDIRS += expat
endif
default: all
-.PHONY: all
+.PHONY: all clean distclean tags distdir install check dep
+
all: $(SUBDIRS:%=%/all)
-.PHONY: clean
+# Extra dependencies to make parallel make work in spite of all the submakes
+# (See top level make file for details)
+abyss/all curl_transport/all: $(BLDDIR)/version.h
+
clean: $(SUBDIRS:%=%/clean) clean-common
-.PHONY: distclean
distclean: $(SUBDIRS:%=%/distclean) distclean-common
-.PHONY: tags
tags: $(SUBDIRS:%=%/tags) TAGS
DISTFILES =
-.PHONY: distdir
distdir: distdir-common
-.PHONY: install
install: $(SUBDIRS:%=%/install)
-.PHONY: dep
+check:
+
dep: $(SUBDIRS:%=%/dep)
-include $(SRCDIR)/Makefile.common
+include $(SRCDIR)/common.mk
Added: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/HISTORY
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/HISTORY Fri May 23 16:56:24 2008
@@ -0,0 +1,122 @@
+Here is some stuff from the README file of the original Abyss source
+package in 2000. Abyss used to be an independent package and was included
+in Xmlrpc-c for convenience when Xmlrpc-c was created. Since then, the
+code has been greatly modified and extended for Xmlrpc-c.
+
+The original Abyss project was a product of Moez Mahfoudh mmoez at bigfoot.com.
+
+
+ ABYSS Web Server
+ ------------------
+
+
+About:
+------
+
+ABYSS aims to be a fully HTTP/1.1 compliant web server. Its main design
+goals are speed, low resource usage and portability. ABYSS works on most
+UNIX based systems and on Win32 systems (Win95/98/2000/NT).
+
+Copyright:
+----------
+
+Copyright (C) 2000 Moez Mahfoudh. All rights reserved.
+
+Status:
+-------
+
+ABYSS is still in development stage. Actual version is 0.3. Many features
+are not implemented yet but the server core works well and seems to be
+stable. It is fully reliable for serving static files on medium load sites.
+In fact, primary benchmarks show that ABYSS is 70% as fast as Apache when
+using the fork system. This rate jumps to 130% when using threads.
+On UNIX platforms, some problems occurred because of the use of the Pthreads
+library. This will be corrected in the future versions. That's why only the
+fork system is usable under UNIX. This lowers performances but guarantees
+stability.
+CGI/1.1 support is still absent from the current version but will be
+included in the near future.
+
+Change Log:
+-----------
+
+ * Version 0.3 (March 23,2000):
+ o Handles conditional GET requests (by date)
+ o Conforms to all the MUSTs of the RFC2616 (newer version of the
+ HTTP/1.1 protocol draft)
+ o New configuration options (such as pidfile for UNIX systems...)
+ o Handles HEAD and OPTIONS methods
+ o Many bug fixes
+ o Tested on Sun-OS 5.7
+ o Second public release
+
+ * Version 0.2 beta (February 7,2000):
+ o Handles GET on static files
+ o Handles correctly range requests
+ o Conforms to 80% of the MUSTs of the RFC2068 (HTTP/1.1 protocol
+ draft)
+ o Improved code portability (Win32 and UNIX platforms)
+ o Tested on Linux 2.2 and Win95/98
+ o First public release
+
+ * Version 0.1 (January 2000):
+ o Completely rewritten in C
+ o Speed improvement
+ o New memory allocation scheme (using pools)
+ o Never released
+
+ * Version 0.0 (January 2000):
+ o Initial version
+ o Written in C++
+ o Never released
+
+Downloading:
+------------
+
+ * Version 0.3 (current version):
+ o UNIX package (source) abyss-0.3.tar.gz.
+ o Win32 package is not available but you can extract source files
+ from the UNIX package and compile them on Windows without any
+ modification. (Sorry for this inconvenience: I have no Windows
+ machine now to compile the program and to test it. If someone can
+ do that, please email me the zipped package and I'll add it here).
+
+ * Version 0.2 beta:
+ o UNIX package (source) abyss-0.2b.tar.gz.
+ o Win32 package (source+binary) abyss-0.2b.zip.
+
+Installation:
+-------------
+
+ * For UNIX systems:
+ o Untar/Ungzip the distribution package with a command like tar xvfz
+ abyss-x.y.tar.gz
+ o Edit the Makefile src/Makefile to meet your system requirements.
+ o Go to directory src and execute make.
+ o The server binary is generated and stored in the bin directory.
+ o Edit the conf/abyss.conf to reflect your system configuration (At
+ least change the paths).
+ o Goto to the bin directory and start the server by typing ./abyss
+ -c ../conf/abyss.conf
+
+ * For Win32 systems:
+ o Unzip the distribution package.
+ o An executable file is already present in the bin directory.
+ o If you wish to recompile the server, open the src/abyss.dsw file
+ with Microsoft Visual C++ 5.0 or higher and rebuild the project.
+ o Edit the conf/abyss.conf to reflect your system configuration (At
+ least change the paths).
+ o Goto to the bin directory and start the server by typing ./abyss
+ -c ../conf/abyss.conf
+
+
+To do:
+------
+
+ * CGI/1.1 support
+ * Web based configuration/administration
+ * Speed improvement
+ * File caching system
+ * Throttling
+ * PUT method handling
+ * ...
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/Makefile
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/abyss/Makefile (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/Makefile Fri May 23 16:56:24 2008
@@ -1,9 +1,12 @@
-ifeq ($(SRCDIR)x,x)
-SRCDIR = $(CURDIR)/../..
+ifeq ($(SRCDIR),)
+ updir = $(shell echo $(dir $(1)) | sed 's/.$$//')
+ LIBDIR := $(call updir,$(CURDIR))
+ SRCDIR := $(call updir,$(LIBDIR))
+ BLDDIR := $(SRCDIR)
endif
-SUBDIR = lib/abyss
+SUBDIR := lib/abyss
-include $(SRCDIR)/Makefile.config
+include $(BLDDIR)/config.mk
SUBDIRS = src
@@ -32,7 +35,7 @@
.PHONY: dep
dep: $(SUBDIRS:%=%/dep)
-include $(SRCDIR)/Makefile.common
+include $(SRCDIR)/common.mk
Added: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/example/conf/abyss.conf
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/example/conf/abyss.conf Fri May 23 16:56:24 2008
@@ -0,0 +1,56 @@
+# ABYSS Web Server configuration file
+# (C) Moez Mahfoudh - 2000
+
+# Cases in option names are ignored,
+# that means that PORT=port=PoRT=..
+
+# When writing paths, do not worry about / or \ use.
+# ABYSS will substitute / with \ on Win32 systems.
+
+# Options which are system specific (such as User) are
+# ignored on systems which do not handle them.
+
+# The Port option tells the server on which TCP port to listen.
+# default is 80
+Port 8080
+
+# The name or #number of the user to run the server as if it is
+# launched as root (UNIX specific)
+User nobody
+
+# The Server Root (UNIX systems style)
+ServerRoot conf/abyss_root
+
+# The Server Root (Win32 systems style)
+# ServerRoot G:\XML\xmlrpc-c-0.9.5\conf\abyss_root
+
+# The Path option specifies the web files path.
+Path htdocs
+
+# The Default option contains the name of the files the server should
+# look for when only a path is given (e.g. http://myserver/info/).
+Default index.html index.htm INDEX.HTM INDEX.HTML
+
+# The KeepAlive option is used to set the maximum number of requests
+# served using the same persistent connection.
+KeepAlive 10
+
+# The TimeOut option tells the server how much seconds to wait for
+# an idle connection before closing it.
+TimeOut 10
+
+# The MimeTypes option specifies the location of the file
+# containing the mapping of MIME types and files extensions
+MimeTypes conf/mime.types
+
+# The path of the log file
+LogFile log/access.log
+
+# The file where the pid of the server is logged (UNIX specific)
+PidFile log/abyss.pid
+
+# If AdvertiseServer if set to no, then no server field would be
+# appended to the responses. This is the way to make the server
+# identity unknown to some malicious people which can profit from
+# well known security holes in the software to crash it.
+AdvertiseServer yes
Added: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/example/conf/mime.types
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/example/conf/mime.types Fri May 23 16:56:24 2008
@@ -0,0 +1,276 @@
+# This is a comment. I love comments.
+
+# This file controls what Internet media types are sent to the client for
+# given file extension(s). Sending the correct media type to the client
+# is important so they know how to handle the content of the file.
+# Extra types can either be added here or by using an AddType directive
+# in your config files. For more information about Internet media types,
+# please read RFC 2045, 2046, 2047, 2048, and 2077. The Internet media type
+# registry is at <ftp://ftp.iana.org/in-notes/iana/assignments/media-types/>.
+
+# MIME type Extension
+application/EDI-Consent
+application/EDI-X12
+application/EDIFACT
+application/activemessage
+application/andrew-inset ez
+application/applefile
+application/atomicmail
+application/cals-1840
+application/commonground
+application/cybercash
+application/dca-rft
+application/dec-dx
+application/eshop
+application/hyperstudio
+application/iges
+application/mac-binhex40 hqx
+application/mac-compactpro cpt
+application/macwriteii
+application/marc
+application/mathematica
+application/msword doc
+application/news-message-id
+application/news-transmission
+application/octet-stream bin dms lha lzh exe class
+application/oda oda
+application/pdf pdf
+application/pgp-encrypted
+application/pgp-keys
+application/pgp-signature
+application/pkcs10
+application/pkcs7-mime
+application/pkcs7-signature
+application/postscript ai eps ps
+application/prs.alvestrand.titrax-sheet
+application/prs.cww
+application/prs.nprend
+application/remote-printing
+application/riscos
+application/rtf rtf
+application/set-payment
+application/set-payment-initiation
+application/set-registration
+application/set-registration-initiation
+application/sgml
+application/sgml-open-catalog
+application/slate
+application/smil smi smil
+application/vemmi
+application/vnd.3M.Post-it-Notes
+application/vnd.FloGraphIt
+application/vnd.acucobol
+application/vnd.anser-web-certificate-issue-initiation
+application/vnd.anser-web-funds-transfer-initiation
+application/vnd.audiograph
+application/vnd.businessobjects
+application/vnd.claymore
+application/vnd.comsocaller
+application/vnd.dna
+application/vnd.dxr
+application/vnd.ecdis-update
+application/vnd.ecowin.chart
+application/vnd.ecowin.filerequest
+application/vnd.ecowin.fileupdate
+application/vnd.ecowin.series
+application/vnd.ecowin.seriesrequest
+application/vnd.ecowin.seriesupdate
+application/vnd.enliven
+application/vnd.epson.salt
+application/vnd.fdf
+application/vnd.ffsns
+application/vnd.framemaker
+application/vnd.fujitsu.oasys
+application/vnd.fujitsu.oasys2
+application/vnd.fujitsu.oasys3
+application/vnd.fujitsu.oasysgp
+application/vnd.fujitsu.oasysprs
+application/vnd.fujixerox.docuworks
+application/vnd.hp-HPGL
+application/vnd.hp-PCL
+application/vnd.hp-PCLXL
+application/vnd.hp-hps
+application/vnd.ibm.MiniPay
+application/vnd.ibm.modcap
+application/vnd.intercon.formnet
+application/vnd.intertrust.digibox
+application/vnd.intertrust.nncp
+application/vnd.is-xpr
+application/vnd.japannet-directory-service
+application/vnd.japannet-jpnstore-wakeup
+application/vnd.japannet-payment-wakeup
+application/vnd.japannet-registration
+application/vnd.japannet-registration-wakeup
+application/vnd.japannet-setstore-wakeup
+application/vnd.japannet-verification
+application/vnd.japannet-verification-wakeup
+application/vnd.koan
+application/vnd.lotus-1-2-3
+application/vnd.lotus-approach
+application/vnd.lotus-freelance
+application/vnd.lotus-organizer
+application/vnd.lotus-screencam
+application/vnd.lotus-wordpro
+application/vnd.meridian-slingshot
+application/vnd.mif mif
+application/vnd.minisoft-hp3000-save
+application/vnd.mitsubishi.misty-guard.trustweb
+application/vnd.ms-artgalry
+application/vnd.ms-asf
+application/vnd.ms-excel xls
+application/vnd.ms-powerpoint ppt
+application/vnd.ms-project
+application/vnd.ms-tnef
+application/vnd.ms-works
+application/vnd.music-niff
+application/vnd.musician
+application/vnd.netfpx
+application/vnd.noblenet-directory
+application/vnd.noblenet-sealer
+application/vnd.noblenet-web
+application/vnd.novadigm.EDM
+application/vnd.novadigm.EDX
+application/vnd.novadigm.EXT
+application/vnd.osa.netdeploy
+application/vnd.powerbuilder6
+application/vnd.powerbuilder6-s
+application/vnd.rapid
+application/vnd.seemail
+application/vnd.shana.informed.formtemplate
+application/vnd.shana.informed.interchange
+application/vnd.shana.informed.package
+application/vnd.street-stream
+application/vnd.svd
+application/vnd.swiftview-ics
+application/vnd.truedoc
+application/vnd.visio
+application/vnd.webturbo
+application/vnd.wrq-hp3000-labelled
+application/vnd.wt.stf
+application/vnd.xara
+application/vnd.yellowriver-custom-menu
+application/wita
+application/wordperfect5.1
+application/x-bcpio bcpio
+application/x-cdlink vcd
+application/x-chess-pgn pgn
+application/x-compress
+application/x-cpio cpio
+application/x-csh csh
+application/x-director dcr dir dxr
+application/x-dvi dvi
+application/x-futuresplash spl
+application/x-gtar gtar
+application/x-gzip
+application/x-hdf hdf
+application/x-javascript js
+application/x-koan skp skd skt skm
+application/x-latex latex
+application/x-netcdf nc cdf
+application/x-sh sh
+application/x-shar shar
+application/x-shockwave-flash swf
+application/x-stuffit sit
+application/x-sv4cpio sv4cpio
+application/x-sv4crc sv4crc
+application/x-tar tar
+application/x-tcl tcl
+application/x-tex tex
+application/x-texinfo texinfo texi
+application/x-troff t tr roff
+application/x-troff-man man
+application/x-troff-me me
+application/x-troff-ms ms
+application/x-ustar ustar
+application/x-wais-source src
+application/x400-bp
+application/xml
+application/zip zip
+audio/32kadpcm
+audio/basic au snd
+audio/midi mid midi kar
+audio/mpeg mpga mp2 mp3
+audio/vnd.qcelp
+audio/x-aiff aif aiff aifc
+audio/x-pn-realaudio ram rm
+audio/x-pn-realaudio-plugin rpm
+audio/x-realaudio ra
+audio/x-wav wav
+chemical/x-pdb pdb xyz
+image/bmp bmp
+image/cgm
+image/g3fax
+image/gif gif
+image/ief ief
+image/jpeg jpeg jpg jpe
+image/naplps
+image/png png
+image/prs.btif
+image/tiff tiff tif
+image/vnd.dwg
+image/vnd.dxf
+image/vnd.fpx
+image/vnd.net-fpx
+image/vnd.svf
+image/vnd.xiff
+image/x-cmu-raster ras
+image/x-portable-anymap pnm
+image/x-portable-bitmap pbm
+image/x-portable-graymap pgm
+image/x-portable-pixmap ppm
+image/x-rgb rgb
+image/x-xbitmap xbm
+image/x-xpixmap xpm
+image/x-xwindowdump xwd
+message/delivery-status
+message/disposition-notification
+message/external-body
+message/http
+message/news
+message/partial
+message/rfc822
+model/iges igs iges
+model/mesh msh mesh silo
+model/vnd.dwf
+model/vrml wrl vrml
+multipart/alternative
+multipart/appledouble
+multipart/byteranges
+multipart/digest
+multipart/encrypted
+multipart/form-data
+multipart/header-set
+multipart/mixed
+multipart/parallel
+multipart/related
+multipart/report
+multipart/signed
+multipart/voice-message
+text/css css
+text/directory
+text/enriched
+text/html html htm
+text/plain asc txt
+text/prs.lines.tag
+text/rfc822-headers
+text/richtext rtx
+text/rtf rtf
+text/sgml sgml sgm
+text/tab-separated-values tsv
+text/uri-list
+text/vnd.abc
+text/vnd.flatland.3dml
+text/vnd.fmi.flexstor
+text/vnd.in3d.3dml
+text/vnd.in3d.spot
+text/vnd.latex-z
+text/x-setext etx
+text/xml xml
+video/mpeg mpeg mpg mpe
+video/quicktime qt mov
+video/vnd.motorola.video
+video/vnd.motorola.videop
+video/vnd.vivo
+video/x-msvideo avi
+video/x-sgi-movie movie
+x-conference/x-cooltalk ice
Added: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/example/htdocs/index.htm
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/example/htdocs/index.htm Fri May 23 16:56:24 2008
@@ -0,0 +1,21 @@
+<HTML>
+<HEAD>
+<TITLE>ABYSS is working !!!</TITLE>
+</HEAD>
+<BODY bgColor=#80a0f0 text=#000000>
+<H1 align=center>Congratulations, ABYSS is working !!!</H1>
+<BR>
+<P>
+<B>ABYSS</B> Web Server is working correctly on your system. You should now change this
+page with yours.
+<BR>
+Please include in your web pages (at least the first), the <b><i>'Powered by ABYSS'</i></b>
+banner to promote the use of <B>ABYSS</B>.
+</P>
+<hr>
+<P>
+<CENTER><FONT size=-1>
+Copyright © 2000 <A href="mailto:mmoez at bigfoot.com">Moez Mahfoudh</A>. All rights reserved.
+</FONT>
+<BR><BR><A href="http://abyss.linuxave.net/"><IMG border=0 src="pwrabyss.gif"></A></center></P>
+</BODY></HTML>
Added: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/example/htdocs/pwrabyss.gif
==============================================================================
Binary file. No diff available.
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/Makefile
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/Makefile (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/Makefile Fri May 23 16:56:24 2008
@@ -1,52 +1,102 @@
-ifeq ($(SRCDIR)x,x)
-SRCDIR = $(CURDIR)/../../..
+ifeq ($(SRCDIR),)
+ updir = $(shell echo $(dir $(1)) | sed 's/.$$//')
+ ABYSSDIR := $(call updir,$(CURDIR))
+ LIBDIR := $(call updir,$(ABYSSDIR))
+ SRCDIR := $(call updir,$(LIBDIR))
+ BLDDIR := $(SRCDIR)
endif
-SUBDIR = lib/abyss/src
+SUBDIR := lib/abyss/src
-include $(SRCDIR)/Makefile.config
+include $(BLDDIR)/config.mk
+
+default: all
+
+TARGET_LIBRARY_NAMES := libxmlrpc_abyss
+
+STATIC_LIBRARIES_TO_INSTALL = libxmlrpc_abyss.a
+
+SHARED_LIBS_TO_BUILD := libxmlrpc_abyss
+SHARED_LIBS_TO_INSTALL := libxmlrpc_abyss
-CFLAGS = $(CFLAGS_COMMON)
-CFLAGS += -D_UNIX
-ifeq ($(ENABLE_ABYSS_THREADS),yes)
-CFLAGS += -D_THREAD
-endif
-CFLAGS +=
-CFLAGS += $(CFLAGS_PERSONAL) $(CADD)
-LIBLDFLAGS = $(LDFLAGS_VERSINFO) -rpath $(LIBINST_DIR)
ifeq ($(ENABLE_ABYSS_THREADS),yes)
-LIBLDFLAGS += -lpthread
+ THREAD_MODULE = thread_pthread
+else
+ THREAD_MODULE = thread_fork
endif
-LIBLDFLAGS += $(LADD)
-INCLUDES = -I$(SRCDIR) -I$(SRCDIR)/include -I$(SRCDIR)/lib/util/include
+TARGET_MODS = \
+ channel \
+ chanswitch \
+ conf \
+ conn \
+ data \
+ date \
+ file \
+ handler \
+ http \
+ init \
+ response \
+ server \
+ session \
+ socket \
+ socket_unix \
+ token \
+ $(THREAD_MODULE) \
+ trace \
+
+OMIT_ABYSS_LIB_RULE = Y
+MAJ=3
+ # Major number of shared libraries in this directory
+
+include $(SRCDIR)/common.mk
+
+CFLAGS = $(CFLAGS_COMMON) -D_UNIX $(CFLAGS_PERSONAL) $(CADD)
+
+INCLUDES = -Iblddir -Isrcdir -Isrcdir/include -Isrcdir/lib/util/include
+
+ABYSS_SHLIB = $(call shlibfn,libxmlrpc_abyss)
+#ABYSS_SHLIB is e.g. libxmlrpc_abyss.so.3.1
+ABYSS_SHLIBLE = $(call shliblefn,libxmlrpc_abyss)
+#ABYSS_SHLIBLE is e.g. libxmlrpc_abyss.so
+
+# LIBDEP is the shared libraries on which libxmlrpc_abyss depends.
+# The runtime loader should load these libraries when it loads libxmlrpc_abyss.
+
+LIBDEP = $(LIBXMLRPC_UTIL)
+
+ifneq ($(SHARED_LIB_TYPE),NONE)
+ TARGET_SHARED_LIBS := $(ABYSS_SHLIB) $(ABYSS_SHLIBLE)
+ endif
-LTLIBRARIES_TO_INSTALL = libxmlrpc_abyss.la
+# This 'common.mk' dependency makes sure the symlinks get built before
+# this make file is used for anything.
-default: all
+$(SRCDIR)/common.mk: srcdir blddir
.PHONY: all
-all: libxmlrpc_abyss.la
+all: libxmlrpc_abyss.a $(TARGET_SHARED_LIBS) $(TARGET_SHARED_LE_LIBS)
-ABYSS_OBJS = \
- conf.lo \
- data.lo \
- token.lo \
- trace.lo \
- file.lo \
- thread.lo \
- http.lo \
- socket.lo \
- server.lo \
- conn.lo \
-
-
-libxmlrpc_abyss.la: $(ABYSS_OBJS)
- $(LIBTOOL) --mode=link $(CCLD) -o $@ $(LIBLDFLAGS) $^
-
-$(ABYSS_OBJS):%.lo:%.c
- $(LIBTOOL) --mode=compile $(CC) -c $(INCLUDES) \
- $(CFLAGS) $<
+# Rule for this is in common.mk, courtesy of TARGET_SHARED_LIBRARIES:
+$(ABYSS_SHLIB): $(TARGET_MODS:%=%.osh) $(LIBDEP)
+$(ABYSS_SHLIB): LIBOBJECTS = $(TARGET_MODS:%=%.osh) $(LIBDEP)
+
+# Rule for this is in common.mk, courtesy of TARGET_STATIC_LIBRARIES:
+
+libxmlrpc_abyss.a: $(TARGET_MODS:%=%.o)
+libxmlrpc_abyss.a: LIBOBJECTS = $(TARGET_MODS:%=%.o)
+
+#-----------------------------------------------------------------------------
+# RULES TO COMPILE OBJECT MODULES FOR LIBRARIES
+#-----------------------------------------------------------------------------
+
+# Rules to compile object modules from which to build the static and shared
+# Abyss library are in common.mk, courtesy of TARGET_MODS.
+
+
+# Need this dependency for those who don't use Makefile.depend.
+# Without it, version.h doesn't get created.
+response.o response.osh handler.o handler.osh: version.h
.PHONY: clean
clean: clean-common
@@ -66,6 +116,4 @@
.PHONY: dep
dep: dep-common
-include $(SRCDIR)/Makefile.common
-
include Makefile.depend
Added: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/abyss_info.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/abyss_info.h Fri May 23 16:56:24 2008
@@ -0,0 +1,18 @@
+#ifndef ABYSS_INFO_H_INCLUDED
+#define ABYSS_INFO_H_INCLUDED
+
+#include "version.h" /* defines XMLRPC_C_VERSION */
+
+#define SERVER_HTML_INFO \
+ "<p><HR><b><i><a href=\"http:\057\057xmlrpc-c.sourceforge.net\">" \
+ "ABYSS Web Server for XML-RPC For C/C++</a></i></b> " \
+ "version " XMLRPC_C_VERSION "<br>" \
+ "</p>"
+
+#define SERVER_PLAIN_INFO \
+ CRLF "----------------------------------------" \
+ "----------------------------------------" \
+ CRLF "ABYSS Web Server for XML-RPC For C/C++ " \
+ "version " XMLRPC_C_VERSION CRLF "See xmlrpc-c.sourceforge.net"
+
+#endif
Added: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/channel.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/channel.c Fri May 23 16:56:24 2008
@@ -0,0 +1,196 @@
+/*============================================================================
+ socket.c
+==============================================================================
+ Implementation of TChannel class: A generic channel over which one can
+ transport a bidirectional stream of bytes.
+
+ A TChannel is a lot like a POSIX stream socket in "connected" state.
+============================================================================*/
+
+#include <sys/types.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "bool.h"
+#include "mallocvar.h"
+#include "xmlrpc-c/util_int.h"
+#include "xmlrpc-c/abyss.h"
+#ifdef WIN32
+ #include "socket_win.h"
+#else
+ #include "socket_unix.h"
+#endif
+#include "channel.h"
+
+
+
+static void
+socketOsInit(const char ** const errorP) {
+
+#ifdef WIN32
+ SocketWinInit(errorP);
+#else
+ SocketUnixInit(errorP);
+#endif
+}
+
+
+
+static void
+socketOsTerm(void) {
+
+#ifdef WIN32
+ SocketWinTerm();
+#else
+ SocketUnixTerm();
+#endif
+}
+
+
+
+bool ChannelTraceIsActive;
+
+void
+ChannelInit(const char ** const errorP) {
+
+ socketOsInit(errorP);
+
+ if (!*errorP) {
+ ChannelTraceIsActive = (getenv("ABYSS_TRACE_CHANNEL") != NULL);
+ if (ChannelTraceIsActive)
+ fprintf(stderr, "Abyss channel layer will trace channel traffic "
+ "due to ABYSS_TRACE_CHANNEL environment variable\n");
+ }
+}
+
+
+
+void
+ChannelTerm(void) {
+
+ socketOsTerm();
+}
+
+
+
+/* ChannelCreate() is not exported to the Abyss user. It is meant to
+ be used by an implementation-specific TChannel generator which is
+ exported to the Abyss user, e.g. ChannelCreateUnix() in
+ socket_unix.c
+
+ The TChannel generator functions are the _only_ user-accessible
+ functions that are particular to an implementation.
+*/
+
+static uint const channelSignature = 0x06060B;
+
+void
+ChannelCreate(const struct TChannelVtbl * const vtblP,
+ void * const implP,
+ TChannel ** const channelPP) {
+
+ TChannel * channelP;
+
+ MALLOCVAR(channelP);
+
+ if (channelP) {
+ channelP->implP = implP;
+ channelP->vtbl = *vtblP;
+ channelP->signature = channelSignature;
+ *channelPP = channelP;
+
+ if (ChannelTraceIsActive)
+ fprintf(stderr, "Created channel %p\n", channelP);
+ }
+}
+
+
+
+void
+ChannelDestroy(TChannel * const channelP) {
+
+ if (ChannelTraceIsActive)
+ fprintf(stderr, "Destroying channel %p\n", channelP);
+
+ assert(channelP->signature == channelSignature);
+
+ channelP->vtbl.destroy(channelP);
+
+ channelP->signature = 0; /* For debuggability */
+
+ free(channelP);
+}
+
+
+
+void
+ChannelWrite(TChannel * const channelP,
+ const unsigned char * const buffer,
+ uint32_t const len,
+ bool * const failedP) {
+
+ if (ChannelTraceIsActive)
+ fprintf(stderr, "Writing %u bytes to channel %p\n", len, channelP);
+
+ (*channelP->vtbl.write)(channelP, buffer, len, failedP);
+}
+
+
+
+void
+ChannelRead(TChannel * const channelP,
+ unsigned char * const buffer,
+ uint32_t const len,
+ uint32_t * const bytesReceivedP,
+ bool * const failedP) {
+
+ if (ChannelTraceIsActive)
+ fprintf(stderr, "Reading %u bytes from channel %p\n", len, channelP);
+
+ (*channelP->vtbl.read)(channelP, buffer, len, bytesReceivedP, failedP);
+}
+
+
+
+void
+ChannelWait(TChannel * const channelP,
+ bool const waitForRead,
+ bool const waitForWrite,
+ uint32_t const timems,
+ bool * const readyToReadP,
+ bool * const readyToWriteP,
+ bool * const failedP) {
+
+ if (ChannelTraceIsActive) {
+ if (waitForRead)
+ fprintf(stderr, "Waiting %u milliseconds for data from "
+ "channel %p\n", timems, channelP);
+ if (waitForWrite)
+ fprintf(stderr, "Waiting %u milliseconds for channel %p "
+ "to be writable\n", timems, channelP);
+ }
+ (*channelP->vtbl.wait)(channelP, waitForRead, waitForWrite, timems,
+ readyToReadP, readyToWriteP, failedP);
+}
+
+
+
+void
+ChannelInterrupt(TChannel * const channelP) {
+
+ if (ChannelTraceIsActive)
+ fprintf(stderr, "Interrupting channel waits");
+
+ (*channelP->vtbl.interrupt)(channelP);
+}
+
+
+
+void
+ChannelFormatPeerInfo(TChannel * const channelP,
+ const char ** const peerStringP) {
+
+ (*channelP->vtbl.formatPeerInfo)(channelP, peerStringP);
+}
+
Added: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/channel.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/channel.h Fri May 23 16:56:24 2008
@@ -0,0 +1,112 @@
+#ifndef CHANNEL_H_INCLUDED
+#define CHANNEL_H_INCLUDED
+
+/*============================================================================
+ This is the generic channel interface for Abyss. It includes both
+ the generic interface to a channel from above and the interface
+ between generic channel code and a particular channel
+ implementation (e.g. POSIX socket) below.
+
+ Abyss uses a channel to converse with an HTTP client. A channel is
+ oblivious to HTTP -- it just transports a byte stream in each direction.
+============================================================================*/
+
+#include "bool.h"
+#include "int.h"
+#include "xmlrpc-c/abyss.h"
+
+struct TChannelVtbl;
+
+void
+ChannelCreate(const struct TChannelVtbl * const vtblP,
+ void * const implP,
+ TChannel ** const channelPP);
+
+typedef void ChannelDestroyImpl(TChannel * const channelP);
+
+typedef void ChannelWriteImpl(TChannel * const channelP,
+ const unsigned char * const buffer,
+ uint32_t const len,
+ bool * const failedP);
+
+typedef void ChannelReadImpl(TChannel * const channelP,
+ unsigned char * const buffer,
+ uint32_t const len,
+ uint32_t * const bytesReceivedP,
+ bool * const failedP);
+
+typedef uint32_t ChannelErrorImpl(TChannel * const channelP);
+
+typedef void ChannelWaitImpl(TChannel * const channelP,
+ bool const waitForRead,
+ bool const waitForWrite,
+ uint32_t const timems,
+ bool * const readyToReadP,
+ bool * const readyToWriteP,
+ bool * const failedP);
+
+typedef void ChannelInterruptImpl(TChannel * const channelP);
+
+typedef void ChannelFormatPeerInfoImpl(TChannel * const channelP,
+ const char ** const peerStringP);
+
+struct TChannelVtbl {
+ ChannelDestroyImpl * destroy;
+ ChannelWriteImpl * write;
+ ChannelReadImpl * read;
+ ChannelWaitImpl * wait;
+ ChannelInterruptImpl * interrupt;
+ ChannelFormatPeerInfoImpl * formatPeerInfo;
+};
+
+struct _TChannel {
+ uint signature;
+ /* With both background and foreground use of sockets, and
+ background being both fork and pthread, it is very easy to
+ screw up socket lifetime and try to destroy twice. We use
+ this signature to help catch such bugs.
+ */
+ void * implP;
+ struct TChannelVtbl vtbl;
+};
+
+#define TIME_INFINITE 0xffffffff
+
+extern bool ChannelTraceIsActive;
+
+void
+ChannelInit(const char ** const errorP);
+
+void
+ChannelTerm(void);
+
+void
+ChannelWrite(TChannel * const channelP,
+ const unsigned char * const buffer,
+ uint32_t const len,
+ bool * const failedP);
+
+void
+ChannelRead(TChannel * const channelP,
+ unsigned char * const buffer,
+ uint32_t const len,
+ uint32_t * const bytesReceivedP,
+ bool * const failedP);
+
+void
+ChannelWait(TChannel * const channelP,
+ bool const waitForRead,
+ bool const waitForWrite,
+ uint32_t const timems,
+ bool * const readyToReadP,
+ bool * const readyToWriteP,
+ bool * const failedP);
+
+void
+ChannelInterrupt(TChannel * const channelP);
+
+void
+ChannelFormatPeerInfo(TChannel * const channelP,
+ const char ** const peerStringP);
+
+#endif
Added: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/chanswitch.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/chanswitch.c Fri May 23 16:56:24 2008
@@ -0,0 +1,167 @@
+/*============================================================================
+ socket.c
+==============================================================================
+ Implementation of TChanSwitch class: A generic channel switch -- an object
+ that brokers a connection between an HTTP client and server.
+============================================================================*/
+
+#include <sys/types.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "bool.h"
+#include "mallocvar.h"
+#include "xmlrpc-c/util_int.h"
+#include "xmlrpc-c/abyss.h"
+#ifdef WIN32
+ #include "socket_win.h"
+#else
+ #include "socket_unix.h"
+#endif
+#include "chanswitch.h"
+
+
+static void
+socketOsInit(const char ** const errorP) {
+
+#ifdef WIN32
+ SocketWinInit(errorP);
+#else
+ SocketUnixInit(errorP);
+#endif
+}
+
+
+
+static void
+socketOsTerm(void) {
+
+#ifdef WIN32
+ SocketWinTerm();
+#else
+ SocketUnixTerm();
+#endif
+}
+
+
+
+bool SwitchTraceIsActive;
+
+void
+ChanSwitchInit(const char ** const errorP) {
+
+ socketOsInit(errorP);
+
+ if (!*errorP) {
+ SwitchTraceIsActive = (getenv("ABYSS_TRACE_SWITCH") != NULL);
+ if (SwitchTraceIsActive)
+ fprintf(stderr, "Abyss channel switch layer will trace "
+ "channel connection activity "
+ "due to ABYSS_TRACE_SWITCH environment variable\n");
+ }
+}
+
+
+
+void
+ChanSwitchTerm(void) {
+
+ socketOsTerm();
+}
+
+
+
+/* ChanSwitchCreate() is not exported to the Abyss user. It is meant to
+ be used by an implementation-specific TChanSwitch generator which is
+ exported to the Abyss user, e.g. SwitchCreateUnix() in
+ socket_unix.c
+
+ The TChanSwitch generator functions are the _only_ user-accessible
+ functions that are particular to an implementation.
+*/
+
+static uint const switchSignature = 0x06060A;
+
+void
+ChanSwitchCreate(const struct TChanSwitchVtbl * const vtblP,
+ void * const implP,
+ TChanSwitch ** const chanSwitchPP) {
+
+ TChanSwitch * chanSwitchP;
+
+ MALLOCVAR(chanSwitchP);
+
+ if (chanSwitchP) {
+ chanSwitchP->implP = implP;
+ chanSwitchP->vtbl = *vtblP;
+ chanSwitchP->signature = switchSignature;
+
+ if (SwitchTraceIsActive)
+ fprintf(stderr, "Created channel switch %p\n", chanSwitchP);
+
+ *chanSwitchPP = chanSwitchP;
+ }
+}
+
+
+
+void
+ChanSwitchDestroy(TChanSwitch * const chanSwitchP) {
+
+ if (SwitchTraceIsActive)
+ fprintf(stderr, "Destroying channel switch %p\n", chanSwitchP);
+
+ assert(chanSwitchP->signature == switchSignature);
+
+ chanSwitchP->vtbl.destroy(chanSwitchP);
+
+ chanSwitchP->signature = 0; /* For debuggability */
+
+ free(chanSwitchP);
+}
+
+
+
+void
+ChanSwitchListen(TChanSwitch * const chanSwitchP,
+ uint32_t const backlog,
+ const char ** const errorP) {
+
+ if (SwitchTraceIsActive)
+ fprintf(stderr, "Channel switch %p listening.\n", chanSwitchP);
+
+ (*chanSwitchP->vtbl.listen)(chanSwitchP, backlog, errorP);
+}
+
+
+
+void
+ChanSwitchAccept(TChanSwitch * const chanSwitchP,
+ TChannel ** const channelPP,
+ void ** const channelInfoPP,
+ const char ** const errorP) {
+
+ if (SwitchTraceIsActive)
+ fprintf(stderr, "Getting a connection from Channel switch %p...\n",
+ chanSwitchP);
+
+ (*chanSwitchP->vtbl.accept)(chanSwitchP, channelPP, channelInfoPP, errorP);
+
+ if (SwitchTraceIsActive)
+ fprintf(stderr, "Got connection from channel switch. "
+ "Channel = %p\n", *channelPP);
+}
+
+
+
+void
+ChanSwitchInterrupt(TChanSwitch * const chanSwitchP) {
+
+ if (SwitchTraceIsActive)
+ fprintf(stderr, "Interrupting wait for a connection "
+ "by Channel switch %p...\n",
+ chanSwitchP);
+
+ (*chanSwitchP->vtbl.interrupt)(chanSwitchP);
+}
Added: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/chanswitch.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/chanswitch.h Fri May 23 16:56:24 2008
@@ -0,0 +1,78 @@
+#ifndef CHANSWITCH_H_INCLUDED
+#define CHANSWITCH_H_INCLUDED
+
+/*============================================================================
+ This is the generic channel switch interface for Abyss. It
+ includes both the generic interface to a channel switch from above
+ and the interface between generic channel switch code and a
+ particular channel implementation (e.g. POSIX) below.
+
+ A channel switch is what creates a channel -- it brokers a connection
+ between an HTTP client and server.
+============================================================================*/
+
+#include "bool.h"
+#include "int.h"
+#include "xmlrpc-c/abyss.h"
+
+typedef void SwitchDestroyImpl(TChanSwitch * const socketP);
+
+typedef void SwitchListenImpl(TChanSwitch * const chanSwitchP,
+ uint32_t const backlog,
+ const char ** const errorP);
+
+typedef void SwitchAcceptImpl(TChanSwitch * const chanSwitchP,
+ TChannel ** const channelPP,
+ void ** const channelInfoP,
+ const char ** const errorP);
+
+typedef void SwitchInterruptImpl(TChanSwitch * const chanSwitchP);
+
+struct TChanSwitchVtbl {
+ SwitchDestroyImpl * destroy;
+ SwitchListenImpl * listen;
+ SwitchAcceptImpl * accept;
+ SwitchInterruptImpl * interrupt;
+};
+
+struct _TChanSwitch {
+ uint signature;
+ /* With both background and foreground use of switches, and
+ background being both fork and pthread, it is very easy to
+ screw up switch lifetime and try to destroy twice. We use
+ this signature to help catch such bugs.
+ */
+ void * implP;
+ struct TChanSwitchVtbl vtbl;
+};
+
+extern bool SwitchTraceIsActive;
+
+void
+ChanSwitchInit(const char ** const errorP);
+
+void
+ChanSwitchTerm(void);
+
+void
+ChanSwitchCreate(const struct TChanSwitchVtbl * const vtblP,
+ void * const implP,
+ TChanSwitch ** const chanSwitchPP);
+
+void
+ChanSwitchListen(TChanSwitch * const chanSwitchP,
+ uint32_t const backlog,
+ const char ** const errorP);
+
+void
+ChanSwitchAccept(TChanSwitch * const chanSwitchP,
+ TChannel ** const channelPP,
+ void ** const channelInfoPP,
+ const char ** const errorP);
+
+void
+ChanSwitchInterrupt(TChanSwitch * const chanSwitchP);
+
+#endif
+
+
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/conf.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/conf.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/conf.c Fri May 23 16:56:24 2008
@@ -36,7 +36,7 @@
#include <stdio.h>
#include <string.h>
-#if defined(ABYSS_WIN32) && !defined(__BORLANDC__)
+#if defined(WIN32) && !defined(__BORLANDC__)
#include <direct.h>
#endif
@@ -44,7 +44,15 @@
#include <pwd.h>
#endif
+#include "xmlrpc_config.h"
+#include "bool.h"
+#include "xmlrpc-c/string_int.h"
#include "xmlrpc-c/abyss.h"
+#include "trace.h"
+#include "file.h"
+#include "server.h"
+#include "http.h"
+#include "handler.h"
/*********************************************************************
** Configuration Files Parsing Functions
@@ -52,46 +60,59 @@
-static abyss_bool
-ConfReadLine(TFile *f,char *buffer,uint32_t len) {
- abyss_bool r=TRUE;
- char c,*p,*z=buffer;
-
- while ((--len)>0)
- {
- if (FileRead(f,buffer,1)<1)
- {
- if (z==buffer)
- r=FALSE;
+static bool
+ConfReadLine(TFile * const fileP,
+ char * const buffer,
+ uint32_t const lenArg) {
+
+ bool r;
+ char c;
+ char * p;
+ char * z;
+ uint32_t len;
+
+ len = lenArg; /* initial value */
+ r = TRUE; /* initial value */
+ z = buffer; /* initial value */
+
+ while (--len > 0) {
+ int32_t bytesRead;
+
+ bytesRead = FileRead(fileP, z, 1);
+ if (bytesRead < 1) {
+ if (z == buffer)
+ r = FALSE;
break;
};
- if ((*buffer==CR) || (*buffer==LF) )
+ if (*z == CR || *z == LF)
break;
- buffer++;
- };
+ ++z;
+ }
- if (len==0)
- while (FileRead(f,&c,1)==1)
- if ((c==CR) || (c==LF))
+ if (len == 0)
+ while (FileRead(fileP, &c, 1) == 1)
+ if (c == CR || c == LF)
break;
- *buffer='\0';
+ *buffer = '\0';
/* Discard comments */
- p=strchr(z,'#');
+ p = strchr(z, '#');
if (p)
- *p='\0';
+ *p = '\0';
return r;
}
-static abyss_bool
-ConfNextToken(char **p) {
+
+
+static bool
+ConfNextToken(char ** const p) {
+
while (1)
- switch (**p)
- {
+ switch (**p) {
case '\t':
case ' ':
(*p)++;
@@ -130,213 +151,251 @@
};
}
-static abyss_bool
-ConfReadInt(char *p,int32_t *n,int32_t min,int32_t max) {
- char *e;
+static bool
+ConfReadInt(const char * const p,
+ int32_t * const n,
+ int32_t const min,
+ int32_t const max) {
+/*----------------------------------------------------------------------------
+ Convert string 'p' to integer *n.
+
+ If it isn't a valid integer or is not with the bounds [min, max],
+ return FALSE. Otherwise, return TRUE.
+-----------------------------------------------------------------------------*/
+ char * e;
- *n=strtol(p,&e,10);
+ *n = strtol(p, &e, 10);
- if (min!=max)
- return ((e!=p) && (*n>=min) && (*n<=max));
+ if (min != max)
+ return ((e != p) && (*n >= min) && (*n <= max));
else
- return (e!=p);
+ return (e != p);
}
-static abyss_bool
-ConfReadBool(char *p, abyss_bool *b) {
- if (strcasecmp(p,"yes")==0)
- {
- *b=TRUE;
- return TRUE;
- };
- if (strcasecmp(p,"no")==0)
- {
- *b=FALSE;
- return TRUE;
- };
- return FALSE;
+static bool
+ConfReadBool(const char * const token,
+ bool * const bP) {
+
+ bool succeeded;
+
+ if (xmlrpc_strcaseeq(token, "yes")) {
+ *bP = TRUE;
+ succeeded = TRUE;
+ } else if (xmlrpc_strcaseeq(token, "no")) {
+ *bP = FALSE;
+ succeeded = TRUE;
+ } else
+ succeeded = FALSE;
+
+ return succeeded;
}
/*********************************************************************
** MIME Types File
*********************************************************************/
-abyss_bool ConfReadMIMETypes(char *filename)
-{
- TFile f;
- char z[512],*p;
- char *mimetype,*ext;
-
- if (!FileOpen(&f,filename,O_RDONLY))
- return FALSE;
-
- while (ConfReadLine(&f,z,512))
- {
- p=z;
-
- if (ConfNextToken(&p)) {
- mimetype=ConfGetToken(&p);
- if (mimetype) {
- while (ConfNextToken(&p)) {
- ext=ConfGetToken(&p);
- if (ext)
- MIMETypeAdd(mimetype,ext);
- else
- break;
+static void
+readMIMETypesFile(const char * const filename,
+ MIMEType ** const MIMETypePP) {
+
+ bool success;
+ MIMEType * MIMETypeP;
+
+ MIMETypeP = MIMETypeCreate();
+ if (MIMETypeP) {
+ TFile * fileP;
+ bool fileOpened;
+
+ fileOpened = FileOpen(&fileP, filename, O_RDONLY);
+ if (fileOpened) {
+ char z[512];
+ while (ConfReadLine(fileP, z, 512)) {
+ char * p;
+ p = &z[0];
+
+ if (ConfNextToken(&p)) {
+ const char * mimetype = ConfGetToken(&p);
+ if (mimetype) {
+ while (ConfNextToken(&p)) {
+ const char * const ext = ConfGetToken(&p);
+ if (ext)
+ MIMETypeAdd2(MIMETypeP, mimetype, ext);
+ else
+ break;
+ }
+ }
}
}
- }
- };
+ FileClose(fileP);
+ success = TRUE;
+ } else
+ success = FALSE;
+ if (!success)
+ MIMETypeDestroy(MIMETypeP);
+ } else
+ success = FALSE;
- FileClose(&f);
- return TRUE;
+ if (success)
+ *MIMETypePP = MIMETypeP;
+ else
+ *MIMETypePP = NULL;
}
/*********************************************************************
** Server Configuration File
*********************************************************************/
-abyss_bool ConfReadServerFile(const char *filename,TServer *srv)
-{
- TFile f;
- char z[512],*p;
- char *option;
- int32_t n,line=0;
+static void
+chdirx(const char * const newdir,
+ bool * const successP) {
+
+#if defined(WIN32) && !defined(__BORLANDC__)
+ *successP = _chdir(newdir) == 0;
+#else
+ *successP = chdir(newdir) == 0;
+#endif
+}
+
+
+
+static void
+parseUser(const char * const p,
+ struct _TServer * const srvP) {
+#ifdef _UNIX
+ if (p[0] == '#') {
+ int32_t n;
+
+ if (!ConfReadInt(&p[1], &n, 0, 0))
+ TraceExit("Bad user number '%s'", p);
+ else
+ srvP->uid = n;
+ } else {
+ struct passwd * pwd;
+
+ if (!(pwd = getpwnam(p)))
+ TraceExit("Unknown user '%s'", p);
+
+ srvP->uid = pwd->pw_uid;
+ if ((int)srvP->gid==(-1))
+ srvP->gid = pwd->pw_gid;
+ };
+#else
+ TraceMsg("User option ignored");
+#endif /* _UNIX */
+}
+
+
+
+static void
+parsePidfile(const char * const p,
+ struct _TServer * const srvP) {
+#ifdef _UNIX
+ bool succeeded;
+ succeeded = FileOpenCreate(&srvP->pidfileP, p, O_TRUNC | O_WRONLY);
+ if (!succeeded) {
+ srvP->pidfileP = NULL;
+ TraceMsg("Bad PidFile value '%s'", p);
+ };
+#else
+ TraceMsg("PidFile option ignored");
+#endif /* _UNIX */
+}
+
+
+
+abyss_bool
+ConfReadServerFile(const char * const filename,
+ TServer * const serverP) {
+
+ struct _TServer * const srvP = serverP->srvP;
+ BIHandler * const handlerP = srvP->builtinHandlerP;
+
+ TFile * fileP;
+ char z[512];
+ char * p;
+ unsigned int lineNum;
TFileStat fs;
- if (!FileOpen(&f,filename,O_RDONLY))
+ if (!FileOpen(&fileP, filename, O_RDONLY))
return FALSE;
- while (ConfReadLine(&f,z,512))
- {
- line++;
- p=z;
+ lineNum = 0;
+
+ while (ConfReadLine(fileP, z, 512)) {
+ ++lineNum;
+ p = z;
if (ConfNextToken(&p)) {
- option=ConfGetToken(&p);
- if (option)
- {
+ const char * const option = ConfGetToken(&p);
+ if (option) {
ConfNextToken(&p);
- if (strcasecmp(option,"port")==0)
- {
- if (ConfReadInt(p,&n,1,65535))
- srv->port=n;
+ if (xmlrpc_strcaseeq(option, "port")) {
+ int32_t n;
+ if (ConfReadInt(p, &n, 1, 65535))
+ srvP->port = n;
else
- TraceExit("Invalid port '%s'",p);
- }
- else if (strcasecmp(option,"serverroot")==0)
- {
-#if defined( ABYSS_WIN32 ) && !defined( __BORLANDC__ )
- if (_chdir(p))
-#else
- if (chdir(p))
-#endif
+ TraceExit("Invalid port '%s'", p);
+ } else if (xmlrpc_strcaseeq(option, "serverroot")) {
+ bool success;
+ chdirx(p, &success);
+ if (!success)
TraceExit("Invalid server root '%s'",p);
- }
- else if (strcasecmp(option,"path")==0)
- {
- if (FileStat(p,&fs))
- if (fs.st_mode & S_IFDIR)
- {
- free(srv->filespath);
- srv->filespath=strdup(p);
+ } else if (xmlrpc_strcaseeq(option, "path")) {
+ if (FileStat(p, &fs))
+ if (fs.st_mode & S_IFDIR) {
+ HandlerSetFilesPath(handlerP, p);
continue;
- };
-
- TraceExit("Invalid path '%s'",p);
- }
- else if (strcasecmp(option,"default")==0)
- {
- char *filename;
+ }
+ TraceExit("Invalid path '%s'", p);
+ } else if (xmlrpc_strcaseeq(option, "default")) {
+ const char * filename;
- while ((filename=ConfGetToken(&p)))
- {
- ListAdd(&srv->defaultfilenames,strdup(filename));
+ while ((filename = ConfGetToken(&p))) {
+ HandlerAddDefaultFN(handlerP, filename);
if (!ConfNextToken(&p))
break;
- };
- }
- else if (strcasecmp(option,"keepalive")==0)
- {
- if (ConfReadInt(p,&n,1,65535))
- srv->keepalivemaxconn=n;
- else
- TraceExit("Invalid KeepAlive value '%s'",p);
- }
- else if (strcasecmp(option,"timeout")==0)
- {
- if (ConfReadInt(p,&n,1,3600))
- {
- srv->keepalivetimeout=n;
- /* Must see what to do with that */
- srv->timeout=n;
}
+ } else if (xmlrpc_strcaseeq(option, "keepalive")) {
+ int32_t n;
+ if (ConfReadInt(p, &n, 1, 65535))
+ srvP->keepalivemaxconn = n;
else
- TraceExit("Invalid TimeOut value '%s'",p);
- }
- else if (strcasecmp(option,"mimetypes")==0)
- {
- if (!ConfReadMIMETypes(p))
- TraceExit("Can't read MIME Types file '%s'",p);
- }
- else if (strcasecmp(option,"logfile")==0)
- {
- LogOpen(srv,p);
- }
- else if (strcasecmp(option,"user")==0)
- {
-#ifdef _UNIX
- if (*p=='#')
- {
- int32_t n;
-
- if (!ConfReadInt(p+1,&n,0,0))
- TraceExit("Bad user number '%s'",p);
- else
- srv->uid=n;
- }
+ TraceExit("Invalid KeepAlive value '%s'", p);
+ } else if (xmlrpc_strcaseeq(option, "timeout")) {
+ int32_t n;
+ if (ConfReadInt(p, &n, 1, 3600)) {
+ srvP->keepalivetimeout = n;
+ /* Must see what to do with that */
+ srvP->timeout = n;
+ } else
+ TraceExit("Invalid TimeOut value '%s'", p);
+ } else if (xmlrpc_strcaseeq(option, "mimetypes")) {
+ MIMEType * mimeTypeP;
+ readMIMETypesFile(p, &mimeTypeP);
+ if (!mimeTypeP)
+ TraceExit("Can't read MIME Types file '%s'", p);
else
- {
- struct passwd *pwd;
-
- if (!(pwd=getpwnam(p)))
- TraceExit("Unknown user '%s'",p);
-
- srv->uid=pwd->pw_uid;
- if ((int)srv->gid==(-1))
- srv->gid=pwd->pw_gid;
- };
-#else
- TraceMsg("User option ignored");
-#endif /* _UNIX */
- }
- else if (strcasecmp(option,"pidfile")==0)
- {
-#ifdef _UNIX
- if (!FileOpenCreate(&srv->pidfile,p,O_TRUNC | O_WRONLY))
- {
- srv->pidfile=-1;
- TraceMsg("Bad PidFile value '%s'",p);
- };
-#else
- TraceMsg("PidFile option ignored");
-#endif /* _UNIX */
- }
- else if (strcasecmp(option,"advertiseserver")==0)
- {
- if (!ConfReadBool(p,&srv->advertise))
+ HandlerSetMimeType(handlerP, mimeTypeP);
+ } else if (xmlrpc_strcaseeq(option,"logfile")) {
+ srvP->logfilename = strdup(p);
+ } else if (xmlrpc_strcaseeq(option,"user")) {
+ parseUser(p, srvP);
+ } else if (xmlrpc_strcaseeq(option, "pidfile")) {
+ parsePidfile(p, srvP);
+ } else if (xmlrpc_strcaseeq(option, "advertiseserver")) {
+ if (!ConfReadBool(p, &srvP->advertise))
TraceExit("Invalid boolean value "
"for AdvertiseServer option");
- }
- else
- TraceExit("Invalid option '%s' at line %d",option,line);
- };
+ } else
+ TraceExit("Invalid option '%s' at line %u",
+ option, lineNum);
+ }
}
- };
+ }
- FileClose(&f);
+ FileClose(fileP);
return TRUE;
}
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/conn.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/conn.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/conn.c Fri May 23 16:56:24 2008
@@ -1,343 +1,525 @@
-/*******************************************************************************
-**
-** conn.c
-**
-** This file is part of the ABYSS Web server project.
-**
-** Copyright (C) 2000 by Moez Mahfoudh <mmoez at bigfoot.com>.
-** All rights reserved.
-**
-** Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions
-** are met:
-** 1. Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** 2. Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in the
-** documentation and/or other materials provided with the distribution.
-** 3. The name of the author may not be used to endorse or promote products
-** derived from this software without specific prior written permission.
-**
-** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR 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.
-**
-*******************************************************************************/
+/* Copyright information is at the end of the file. */
#include <time.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
+#include <assert.h>
+#include "bool.h"
+#include "mallocvar.h"
+#include "xmlrpc-c/util_int.h"
+#include "xmlrpc-c/string_int.h"
+#include "xmlrpc-c/sleep_int.h"
#include "xmlrpc-c/abyss.h"
+#include "channel.h"
+#include "server.h"
+#include "thread.h"
+#include "file.h"
+
+#include "conn.h"
/*********************************************************************
** Conn
*********************************************************************/
-TConn *ConnAlloc()
-{
- return (TConn *)malloc(sizeof(TConn));
+static TThreadProc connJob;
+
+static void
+connJob(void * const userHandle) {
+/*----------------------------------------------------------------------------
+ This is the root function for a thread that processes a connection
+ (performs HTTP transactions).
+-----------------------------------------------------------------------------*/
+ TConn * const connectionP = userHandle;
+
+ (connectionP->job)(connectionP);
+
+ connectionP->finished = TRUE;
+ /* Note that if we are running in a forked process, setting
+ connectionP->finished has no effect, because it's just our own
+ copy of *connectionP. In this case, Parent must update his own
+ copy based on a SIGCHLD signal that the OS will generate right
+ after we exit.
+ */
+
+ ThreadExit(0);
}
-void ConnFree(TConn *c)
-{
- free(c);
+
+
+static void
+connDone(TConn * const connectionP) {
+
+ /* In the forked case, this is designed to run in the parent
+ process after the child has terminated.
+ */
+ connectionP->finished = TRUE;
+
+ if (connectionP->done)
+ connectionP->done(connectionP);
}
-static uint32_t
-THREAD_ENTRYTYPE ConnJob(TConn *c) {
- c->connected=TRUE;
- (c->job)(c);
- c->connected=FALSE;
- ThreadExit( &c->thread, 0 );
- return 0;
-}
-
-abyss_bool ConnCreate2(TConn * const connectionP,
- TServer * const serverP,
- TSocket const connectedSocket,
- TIPAddr const peerIpAddr,
- void ( * func)(TConn *),
- enum abyss_foreback const foregroundBackground)
-{
- abyss_bool retval;
-
- connectionP->server = serverP;
- connectionP->socket = connectedSocket;
- connectionP->peerip = peerIpAddr;
- connectionP->buffersize = 0;
- connectionP->bufferpos = 0;
- connectionP->connected = TRUE;
- connectionP->job = func;
- connectionP->inbytes = 0;
- connectionP->outbytes = 0;
- connectionP->trace = getenv("ABYSS_TRACE_CONN");
+
+
+static TThreadDoneFn threadDone;
+
+static void
+threadDone(void * const userHandle) {
+
+ TConn * const connectionP = userHandle;
- switch (foregroundBackground)
- {
+ connDone(connectionP);
+}
+
+
+
+static void
+makeThread(TConn * const connectionP,
+ enum abyss_foreback const foregroundBackground,
+ bool const useSigchld,
+ const char ** const errorP) {
+
+ switch (foregroundBackground) {
case ABYSS_FOREGROUND:
connectionP->hasOwnThread = FALSE;
- retval = TRUE;
+ *errorP = NULL;
break;
- case ABYSS_BACKGROUND:
+ case ABYSS_BACKGROUND: {
+ const char * error;
connectionP->hasOwnThread = TRUE;
- retval = ThreadCreate(&connectionP->thread,
- (TThreadProc)ConnJob,
- connectionP);
- break;
- }
- return retval;
+ ThreadCreate(&connectionP->threadP, connectionP,
+ &connJob, &threadDone, useSigchld,
+ &error);
+ if (error) {
+ xmlrpc_asprintf(errorP, "Unable to create thread to "
+ "process connection. %s", error);
+ xmlrpc_strfree(error);
+ } else
+ *errorP = NULL;
+ } break;
+ } /* switch */
}
-abyss_bool ConnCreate(TConn *c, TSocket *s, void (*func)(TConn *))
-{
- return ConnCreate2(c, c->server, *s, c->peerip, func, ABYSS_BACKGROUND);
+
+
+void
+ConnCreate(TConn ** const connectionPP,
+ TServer * const serverP,
+ TChannel * const channelP,
+ void * const channelInfoP,
+ TThreadProc * const job,
+ TThreadDoneFn * const done,
+ enum abyss_foreback const foregroundBackground,
+ bool const useSigchld,
+ const char ** const errorP) {
+/*----------------------------------------------------------------------------
+ Create an HTTP connection.
+
+ A connection carries one or more HTTP transactions (request/response).
+
+ *channelP transports the requests and responses.
+
+ The connection handles those HTTP requests.
+
+ The connection handles the requests primarily by running the
+ function 'job' once. Some connections can do that autonomously, as
+ soon as the connection is created. Others don't until Caller
+ subsequently calls ConnProcess. Some connections complete the
+ processing before ConnProcess return, while others may run the
+ connection asynchronously to the creator, in the background, via a
+ TThread thread. 'foregroundBackground' determines which.
+
+ 'job' calls methods of the connection to get requests and send
+ responses.
+
+ Some time after the HTTP transactions are all done, 'done' gets
+ called in some context.
+
+ 'channelInfoP' == NULL means no channel info supplied.
+-----------------------------------------------------------------------------*/
+ TConn * connectionP;
+
+ MALLOCVAR(connectionP);
+
+ if (connectionP == NULL)
+ xmlrpc_asprintf(errorP, "Unable to allocate memory for a connection "
+ "descriptor.");
+ else {
+ connectionP->server = serverP;
+ connectionP->channelP = channelP;
+ connectionP->channelInfoP = channelInfoP;
+ connectionP->buffer[0] = '\0';
+ connectionP->buffersize = 0;
+ connectionP->bufferpos = 0;
+ connectionP->finished = FALSE;
+ connectionP->job = job;
+ connectionP->done = done;
+ connectionP->inbytes = 0;
+ connectionP->outbytes = 0;
+ connectionP->trace = getenv("ABYSS_TRACE_CONN");
+
+ makeThread(connectionP, foregroundBackground, useSigchld, errorP);
+ }
+ *connectionPP = connectionP;
}
-abyss_bool ConnProcess(TConn *c)
-{
- abyss_bool retval;
- if (c->hasOwnThread) {
+
+bool
+ConnProcess(TConn * const connectionP) {
+/*----------------------------------------------------------------------------
+ Drive the main processing of a connection -- run the connection's
+ "job" function, which should read HTTP requests from the connection
+ and send HTTP responses.
+
+ If we succeed, we guarantee the connection's "done" function will get
+ called some time after all processing is complete. It might be before
+ we return or some time after. If we fail, we guarantee the "done"
+ function will not be called.
+-----------------------------------------------------------------------------*/
+ bool retval;
+
+ if (connectionP->hasOwnThread) {
/* There's a background thread to handle this connection. Set
it running.
*/
- retval = ThreadRun(&(c->thread));
+ retval = ThreadRun(connectionP->threadP);
} else {
/* No background thread. We just handle it here while Caller waits. */
- (c->job)(c);
- c->connected=FALSE;
+ (connectionP->job)(connectionP);
+ connDone(connectionP);
retval = TRUE;
}
return retval;
}
-void ConnClose(TConn *c)
-{
- if (c->hasOwnThread)
- ThreadClose(&c->thread);
-}
-
-abyss_bool ConnKill(TConn *c)
-{
- c->connected=FALSE;
- return ThreadKill(&(c->thread));
-}
-
-void ConnReadInit(TConn *c)
-{
- if (c->buffersize>c->bufferpos)
- {
- c->buffersize-=c->bufferpos;
- memmove(c->buffer,c->buffer+c->bufferpos,c->buffersize);
- c->bufferpos=0;
- }
- else
- c->buffersize=c->bufferpos=0;
- c->inbytes=c->outbytes=0;
+
+void
+ConnWaitAndRelease(TConn * const connectionP) {
+ if (connectionP->hasOwnThread)
+ ThreadWaitAndRelease(connectionP->threadP);
+
+ free(connectionP);
+}
+
+
+
+bool
+ConnKill(TConn * const connectionP) {
+ connectionP->finished = TRUE;
+ return ThreadKill(connectionP->threadP);
+}
+
+
+
+void
+ConnReadInit(TConn * const connectionP) {
+
+ if (connectionP->buffersize > connectionP->bufferpos) {
+ connectionP->buffersize -= connectionP->bufferpos;
+ memmove(connectionP->buffer,
+ connectionP->buffer + connectionP->bufferpos,
+ connectionP->buffersize);
+ connectionP->bufferpos = 0;
+ } else
+ connectionP->buffersize = connectionP->bufferpos = 0;
+
+ connectionP->buffer[connectionP->buffersize] = '\0';
+
+ connectionP->inbytes = connectionP->outbytes = 0;
+}
+
+
+
+static size_t
+nextLineSize(const char * const string,
+ size_t const startPos,
+ size_t const stringSize) {
+/*----------------------------------------------------------------------------
+ Return the length of the line that starts at offset 'startPos' in the
+ string 'string', which is 'stringSize' characters long.
+
+ 'string' in not NUL-terminated.
+
+ A line begins at beginning of string or after a newline character and
+ runs through the next newline character or end of string. The line
+ includes the newline character at the end, if any.
+-----------------------------------------------------------------------------*/
+ size_t i;
+
+ for (i = startPos; i < stringSize && string[i] != '\n'; ++i);
+
+ if (i < stringSize)
+ ++i; /* Include the newline */
+
+ return i - startPos;
}
static void
-traceSocketRead(const char * const label,
- const char * const buffer,
- unsigned int const size) {
+traceBuffer(const char * const label,
+ const char * const buffer,
+ unsigned int const size) {
- unsigned int nonPrintableCount;
- unsigned int i;
-
- nonPrintableCount = 0; /* Initial value */
-
- for (i = 0; i < size; ++i) {
- if (!isprint(buffer[i]) && buffer[i] != '\n' && buffer[i] != '\r')
- ++nonPrintableCount;
+ size_t cursor; /* Index into buffer[] */
+
+ fprintf(stderr, "%s:\n\n", label);
+
+ for (cursor = 0; cursor < size; ) {
+ /* Print one line of buffer */
+
+ size_t const lineSize = nextLineSize(buffer, cursor, size);
+ const char * const printableLine =
+ xmlrpc_makePrintable_lp(&buffer[cursor], lineSize);
+
+ fprintf(stderr, "%s\n", printableLine);
+
+ cursor += lineSize;
+
+ xmlrpc_strfree(printableLine);
}
- if (nonPrintableCount > 0)
- fprintf(stderr, "%s contains %u nonprintable characters.\n",
- label, nonPrintableCount);
+ fprintf(stderr, "\n");
+}
+
+
+
+static void
+traceChannelRead(TConn * const connectionP,
+ unsigned int const size) {
+
+ if (connectionP->trace)
+ traceBuffer("READ FROM CHANNEL",
+ connectionP->buffer + connectionP->buffersize, size);
+}
+
+
+
+static void
+traceChannelWrite(TConn * const connectionP,
+ const char * const buffer,
+ unsigned int const size,
+ bool const failed) {
- fprintf(stderr, "%s:\n", label);
- fprintf(stderr, "%.*s\n", (int)size, buffer);
+ if (connectionP->trace) {
+ const char * const label =
+ failed ? "FAILED TO WRITE TO CHANNEL" : "WROTE TO CHANNEL";
+ traceBuffer(label, buffer, size);
+ }
}
-abyss_bool
-ConnRead(TConn * const c,
+static uint32_t
+bufferSpace(TConn * const connectionP) {
+
+ return BUFFER_SIZE - connectionP->buffersize;
+}
+
+
+
+bool
+ConnRead(TConn * const connectionP,
uint32_t const timeout) {
+/*----------------------------------------------------------------------------
+ Read some stuff on connection *connectionP from the channel.
- while (SocketWait(&(c->socket),TRUE,FALSE,timeout*1000) == 1) {
- uint32_t x;
- uint32_t y;
-
- x = SocketAvailableReadBytes(&c->socket);
+ Don't wait more than 'timeout' seconds for data to arrive. Fail if
+ nothing arrives within that time.
- /* Avoid lost connections */
- if (x <= 0)
- break;
-
- /* Avoid Buffer overflow and lost Connections */
- if (x + c->buffersize >= BUFFER_SIZE)
- x = BUFFER_SIZE-c->buffersize - 1;
-
- y = SocketRead(&c->socket, c->buffer + c->buffersize, x);
- if (y > 0) {
- if (c->trace)
- traceSocketRead("READ FROM SOCKET:",
- c->buffer + c->buffersize, y);
-
- c->inbytes += y;
- c->buffersize += y;
- c->buffer[c->buffersize] = '\0';
- return TRUE;
+ 'timeout' must be before the end of time.
+-----------------------------------------------------------------------------*/
+ time_t const deadline = time(NULL) + timeout;
+
+ bool cantGetData;
+ bool gotData;
+
+ cantGetData = FALSE;
+ gotData = FALSE;
+
+ while (!gotData && !cantGetData) {
+ int const timeLeft = (int)(deadline - time(NULL));
+
+ if (timeLeft <= 0)
+ cantGetData = TRUE;
+ else {
+ bool const waitForRead = TRUE;
+ bool const waitForWrite = FALSE;
+
+ bool readyForRead;
+ bool failed;
+
+ ChannelWait(connectionP->channelP, waitForRead, waitForWrite,
+ timeLeft * 1000, &readyForRead, NULL, &failed);
+
+ if (failed)
+ cantGetData = TRUE;
+ else {
+ uint32_t bytesRead;
+ bool readFailed;
+
+ ChannelRead(connectionP->channelP,
+ connectionP->buffer + connectionP->buffersize,
+ bufferSpace(connectionP) - 1,
+ &bytesRead, &readFailed);
+
+ if (readFailed)
+ cantGetData = TRUE;
+ else {
+ if (bytesRead > 0) {
+ traceChannelRead(connectionP, bytesRead);
+ connectionP->inbytes += bytesRead;
+ connectionP->buffersize += bytesRead;
+ connectionP->buffer[connectionP->buffersize] = '\0';
+ gotData = TRUE;
+ } else
+ /* Other end has disconnected */
+ cantGetData = TRUE;
+ }
+ }
}
- break;
}
- return FALSE;
+ if (gotData)
+ return TRUE;
+ else
+ return FALSE;
}
-abyss_bool ConnWrite(TConn *c,void *buffer,uint32_t size)
-{
- char *buf = buffer;
- int rc, off = 0;
-
- while (TRUE) {
- /* try sending data */
- if ((rc = SocketWrite(&(c->socket),&buf[off],size - off)) <= 0)
- return FALSE;
-
- /* increase count */
- off += rc;
-
- /* check we're not finished writing */
- if (off >= size)
- break;
- }
+bool
+ConnWrite(TConn * const connectionP,
+ const void * const buffer,
+ uint32_t const size) {
+
+ bool failed;
+
+ ChannelWrite(connectionP->channelP, buffer, size, &failed);
- c->outbytes+=size;
- return TRUE;
+ traceChannelWrite(connectionP, buffer, size, failed);
+
+ if (!failed)
+ connectionP->outbytes += size;
+
+ return !failed;
}
-abyss_bool ConnWriteFromFile(TConn *c,TFile *file,uint64_t start,uint64_t end,
- void *buffer,uint32_t buffersize,uint32_t rate)
-{
- uint64_t y,bytesread=0;
- uint32_t waittime;
- if (rate>0)
- {
- if (buffersize>rate)
- buffersize=rate;
- waittime=(1000*buffersize)/rate;
+bool
+ConnWriteFromFile(TConn * const connectionP,
+ const TFile * const fileP,
+ uint64_t const start,
+ uint64_t const last,
+ void * const buffer,
+ uint32_t const buffersize,
+ uint32_t const rate) {
+/*----------------------------------------------------------------------------
+ Write the contents of the file stream *fileP, from offset 'start'
+ up through 'last', to the HTTP connection *connectionP.
+
+ Meter the reading so as not to read more than 'rate' bytes per second.
+
+ Use the 'bufferSize' bytes at 'buffer' as an internal buffer for this.
+-----------------------------------------------------------------------------*/
+ bool retval;
+ uint32_t waittime;
+ bool success;
+ uint32_t readChunkSize;
+
+ if (rate > 0) {
+ readChunkSize = MIN(buffersize, rate); /* One second's worth */
+ waittime = (1000 * buffersize) / rate;
+ } else {
+ readChunkSize = buffersize;
+ waittime = 0;
}
- else
- waittime=0;
- if (!FileSeek(file,start,SEEK_SET))
- return FALSE;
+ success = FileSeek(fileP, start, SEEK_SET);
+ if (!success)
+ retval = FALSE;
+ else {
+ uint64_t const totalBytesToRead = last - start + 1;
+ uint64_t bytesread;
+
+ bytesread = 0; /* initial value */
+
+ while (bytesread < totalBytesToRead) {
+ uint64_t const bytesLeft = totalBytesToRead - bytesread;
+ uint64_t const bytesToRead64 = MIN(readChunkSize, bytesLeft);
+ uint32_t const bytesToRead = (uint32_t)bytesToRead64;
+
+ uint32_t bytesReadThisTime;
- while (bytesread<=end-start)
- {
- y=(end-start+1)-bytesread;
-
- if (y>buffersize)
- y=buffersize;
-
- y=FileRead(file,buffer,y);
- bytesread+=y;
-
- if (y>0)
- ConnWrite(c,buffer,y);
- else
- break;
-
- if (waittime)
- ThreadWait(waittime);
- };
-
- return (bytesread>end-start);
-}
-
-abyss_bool ConnReadLine(TConn *c,char **z,uint32_t timeout)
-{
- char *p,*t;
- abyss_bool first=TRUE;
- clock_t to,start;
-
- p=*z=c->buffer+c->bufferpos;
- start=clock();
-
- for (;;)
- {
- to=(clock()-start)/CLOCKS_PER_SEC;
- if (to>timeout)
- break;
-
- if (first)
- {
- if (c->bufferpos>=c->buffersize)
- if (!ConnRead(c,timeout-to))
- break;
+ assert(bytesToRead == bytesToRead64); /* readChunkSize is uint32 */
- first=FALSE;
- }
- else
- {
- if (!ConnRead(c,timeout-to))
+ bytesReadThisTime = FileRead(fileP, buffer, bytesToRead);
+ bytesread += bytesReadThisTime;
+
+ if (bytesReadThisTime > 0)
+ ConnWrite(connectionP, buffer, bytesReadThisTime);
+ else
break;
- };
+
+ if (waittime > 0)
+ xmlrpc_millisecond_sleep(waittime);
+ }
+ retval = (bytesread >= totalBytesToRead);
+ }
+ return retval;
+}
+
- t=strchr(p,LF);
- if (t)
- {
- if ((*p!=LF) && (*p!=CR))
- {
- if (!*(t+1))
- continue;
-
- p=t;
-
- if ((*(p+1)==' ') || (*(p+1)=='\t'))
- {
- if (p>*z)
- if (*(p-1)==CR)
- *(p-1)=' ';
-
- *(p++)=' ';
- continue;
- };
- } else {
- /* emk - 04 Jan 2001 - Bug fix to leave buffer
- ** pointing at start of body after reading blank
- ** line following header. */
- p=t;
- }
- c->bufferpos+=p+1-*z;
+TServer *
+ConnServer(TConn * const connectionP) {
+ return connectionP->server;
+}
- if (p>*z)
- if (*(p-1)==CR)
- p--;
- *p='\0';
- return TRUE;
- }
- };
- return FALSE;
+void
+ConnFormatClientAddr(TConn * const connectionP,
+ const char ** const clientAddrPP) {
+
+ ChannelFormatPeerInfo(connectionP->channelP, clientAddrPP);
}
+
+
+
+/*******************************************************************************
+**
+** conn.c
+**
+** This file is part of the ABYSS Web server project.
+**
+** Copyright (C) 2000 by Moez Mahfoudh <mmoez at bigfoot.com>.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR 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.
+**
+******************************************************************************/
Added: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/conn.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/conn.h Fri May 23 16:56:24 2008
@@ -0,0 +1,108 @@
+#ifndef CONN_H_INCLUDED
+#define CONN_H_INCLUDED
+
+#include "bool.h"
+#include "xmlrpc-c/abyss.h"
+#include "thread.h"
+
+struct TFile;
+
+#define BUFFER_SIZE 4096
+
+struct _TConn {
+ struct _TConn * nextOutstandingP;
+ /* Link to the next connection in the list of outstanding
+ connections
+ */
+ TServer * server;
+ uint32_t buffersize;
+ /* Index into the connection buffer (buffer[], below) where
+ the next byte read on the connection will go.
+ */
+ uint32_t bufferpos;
+ /* Index into the connection buffer (buffer[], below) where
+ the next byte to be delivered to the user is.
+ */
+ uint32_t inbytes,outbytes;
+ TChannel * channelP;
+ void * channelInfoP;
+ /* Information about the channel, such as who is on the other end.
+ Format depends on the type of channel. The user of the connection
+ is expected to know that type, because he supplied the channel
+ when he created the channel.
+
+ NULL means no channel info is available.
+ */
+ bool hasOwnThread;
+ TThread * threadP;
+ bool finished;
+ /* We have done all the processing there is to do on this
+ connection, other than possibly notifying someone that we're
+ done. One thing this signifies is that any thread or process
+ that the connection spawned is dead or will be dead soon, so
+ one could reasonably wait for it to be dead, e.g. with
+ pthread_join(). Note that one can scan a bunch of processes
+ for 'finished' status, but sometimes can't scan a bunch of
+ threads for liveness.
+ */
+ const char * trace;
+ TThreadProc * job;
+ TThreadDoneFn * done;
+ char buffer[BUFFER_SIZE];
+};
+
+typedef struct _TConn TConn;
+
+TConn * ConnAlloc(void);
+
+void ConnFree(TConn * const connectionP);
+
+void
+ConnCreate(TConn ** const connectionPP,
+ TServer * const serverP,
+ TChannel * const channelP,
+ void * const channelInfoP,
+ TThreadProc * const job,
+ TThreadDoneFn * const done,
+ enum abyss_foreback const foregroundBackground,
+ bool const useSigchld,
+ const char ** const errorP);
+
+bool
+ConnProcess(TConn * const connectionP);
+
+bool
+ConnKill(TConn * const connectionP);
+
+void
+ConnWaitAndRelease(TConn * const connectionP);
+
+bool
+ConnWrite(TConn * const connectionP,
+ const void * const buffer,
+ uint32_t const size);
+
+bool
+ConnRead(TConn * const c,
+ uint32_t const timems);
+
+void
+ConnReadInit(TConn * const connectionP);
+
+bool
+ConnWriteFromFile(TConn * const connectionP,
+ const struct TFile * const fileP,
+ uint64_t const start,
+ uint64_t const last,
+ void * const buffer,
+ uint32_t const buffersize,
+ uint32_t const rate);
+
+TServer *
+ConnServer(TConn * const connectionP);
+
+void
+ConnFormatClientAddr(TConn * const connectionP,
+ const char ** const clientAddrPP);
+
+#endif
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/data.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/data.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/data.c Fri May 23 16:56:24 2008
@@ -36,25 +36,30 @@
#include <stdlib.h>
#include <string.h>
+#include "bool.h"
#include "mallocvar.h"
+#include "xmlrpc-c/util_int.h"
+#include "xmlrpc-c/string_int.h"
#include "xmlrpc-c/abyss.h"
#include "token.h"
+#include "thread.h"
+
+#include "data.h"
-#define safe_free(it) if (it) {free(it);it=NULL;}
/*********************************************************************
** List
*********************************************************************/
-void ListInit(TList *sl)
+void ListInit(TList * const sl)
{
sl->item=NULL;
sl->size=sl->maxsize=0;
sl->autofree=FALSE;
}
-void ListInitAutoFree(TList *sl)
+void ListInitAutoFree(TList * const sl)
{
sl->item=NULL;
sl->size=sl->maxsize=0;
@@ -70,10 +75,10 @@
if (sl->autofree) {
unsigned int i;
for (i = sl->size; i > 0; --i)
- safe_free(sl->item[i-1]);
+ free(sl->item[i-1]);
}
- safe_free(sl->item);
+ free(sl->item);
}
sl->item = NULL;
sl->size = 0;
@@ -88,19 +93,19 @@
if (sl->item) {
unsigned int i;
for (i = sl->size; i > 0; --i)
- safe_free(sl->item[i-1]);
+ free(sl->item[i-1]);
}
}
-abyss_bool
+bool
ListAdd(TList * const sl,
void * const str) {
/*----------------------------------------------------------------------------
Add an item to the end of the list.
-----------------------------------------------------------------------------*/
- abyss_bool success;
+ bool success;
if (sl->size >= sl->maxsize) {
uint16_t newSize = sl->maxsize + 16;
@@ -137,43 +142,65 @@
-abyss_bool
-ListAddFromString(TList * const list,
- char * const stringArg) {
-
- char *t,*p;
- char * c;
-
- c = stringArg;
-
- if (c)
- while (1)
- {
- NextToken(&c);
+bool
+ListAddFromString(TList * const list,
+ const char * const stringArg) {
- while (*c==',')
- c++;
-
- if (!(t=GetToken(&c)))
- break;
-
- p=c-2;
+ bool retval;
+
+ if (!stringArg)
+ retval = TRUE;
+ else {
+ char * buffer;
+
+ buffer = strdup(stringArg);
+ if (!buffer)
+ retval = FALSE;
+ else {
+ bool endOfString;
+ bool error;
+ char * c;
+
+ for (c = &buffer[0], endOfString = FALSE, error = FALSE;
+ !endOfString && !error;
+ ) {
+ const char * t;
+ NextToken((const char **)&c);
+
+ while (*c == ',')
+ ++c;
+
+ t = GetToken(&c);
+ if (!t)
+ endOfString = TRUE;
+ else {
+ char * p;
+
+ for (p = c - 2; *p == ','; --p)
+ *p = '\0';
+
+ if (t[0] != '\0') {
+ bool added;
+ added = ListAdd(list, (void*)t);
+
+ if (!added)
+ error = TRUE;
+ }
+ }
+ }
+ retval = !error;
+ xmlrpc_strfree(buffer);
+ }
+ }
+ return retval;
+}
- while (*p==',')
- *(p--)='\0';
- if (*t)
- if (!ListAdd(list,t))
- return FALSE;
- };
- return TRUE;
-}
-
-abyss_bool
-ListFindString(TList * const sl,
- char * const str,
- uint16_t * const indexP)
+bool
+ListFindString(TList * const sl,
+ const char * const str,
+ uint16_t * const indexP)
{
uint16_t i;
@@ -192,8 +219,10 @@
** Buffer
*********************************************************************/
-abyss_bool BufferAlloc(TBuffer *buf,uint32_t memsize)
-{
+bool
+BufferAlloc(TBuffer * const buf,
+ xmlrpc_uint32_t const memsize) {
+
/* ************** Implement the static buffers ***/
buf->staticid=0;
buf->data=(void *)malloc(memsize);
@@ -209,21 +238,28 @@
};
}
-void BufferFree(TBuffer *buf)
-{
+
+
+void
+BufferFree(TBuffer * const buf) {
+
if (buf->staticid)
{
/* ************** Implement the static buffers ***/
}
else
- safe_free(buf->data);
+ free(buf->data);
buf->size=0;
buf->staticid=0;
}
-abyss_bool BufferRealloc(TBuffer *buf,uint32_t memsize)
-{
+
+
+bool
+BufferRealloc(TBuffer * const buf,
+ xmlrpc_uint32_t const memsize) {
+
if (buf->staticid)
{
TBuffer b;
@@ -260,56 +296,83 @@
** String
*********************************************************************/
-abyss_bool StringAlloc(TString *s)
-{
- s->size=0;
- if (BufferAlloc(&(s->buffer),256))
- {
- *(char *)(s->buffer.data)='\0';
+bool
+StringAlloc(TString * const stringP) {
+
+ bool succeeded;
+
+ stringP->size = 0;
+
+ succeeded = BufferAlloc(&stringP->buffer, 256);
+ if (succeeded) {
+ *(char *)(stringP->buffer.data) = '\0';
return TRUE;
- }
- else
+ } else
return FALSE;
}
-abyss_bool StringConcat(TString *s,char *s2)
-{
- uint32_t len=strlen(s2);
- if (len+s->size+1>s->buffer.size)
- if (!BufferRealloc(&(s->buffer),((len+s->size+1+256)/256)*256))
+
+bool
+StringConcat(TString * const stringP,
+ const char * const string2) {
+
+ uint32_t const len = strlen(string2);
+
+ if (len + stringP->size + 1 > stringP->buffer.size) {
+ bool succeeded;
+ succeeded = BufferRealloc(
+ &stringP->buffer,
+ ((len + stringP->size + 1 + 256) / 256) * 256);
+ if (!succeeded)
return FALSE;
-
- strcat((char *)(s->buffer.data),s2);
- s->size+=len;
+ }
+ strcat((char *)(stringP->buffer.data), string2);
+ stringP->size += len;
return TRUE;
}
-abyss_bool StringBlockConcat(TString *s,char *s2,char **ref)
-{
- uint32_t len=strlen(s2)+1;
- if (len+s->size>s->buffer.size)
- if (!BufferRealloc(&(s->buffer),((len+s->size+1+256)/256)*256))
+
+bool
+StringBlockConcat(TString * const stringP,
+ const char * const string2,
+ char ** const ref) {
+
+ uint32_t const len = strlen(string2) + 1;
+
+ if (len + stringP->size > stringP->buffer.size) {
+ bool succeeded;
+ succeeded = BufferRealloc(
+ &stringP->buffer,
+ ((len + stringP->size + 1 + 256) / 256) * 256);
+ if (!succeeded)
return FALSE;
-
- *ref=(char *)(s->buffer.data)+s->size;
- memcpy(*ref,s2,len);
- s->size+=len;
+ }
+ *ref = (char *)(stringP->buffer.data) + stringP->size;
+ memcpy(*ref, string2, len);
+ stringP->size += len;
+
return TRUE;
}
-void StringFree(TString *s)
-{
- s->size=0;
- BufferFree(&(s->buffer));
+
+
+void
+StringFree(TString * const stringP) {
+ stringP->size = 0;
+ BufferFree(&stringP->buffer);
}
-char *StringData(TString *s)
-{
- return (char *)(s->buffer.data);
+
+
+char *
+StringData(TString * const stringP) {
+ return (char *)stringP->buffer.data;
}
+
+
/*********************************************************************
** Hash
*********************************************************************/
@@ -334,13 +397,13 @@
** Table
*********************************************************************/
-void TableInit(TTable *t)
+void TableInit(TTable * const t)
{
t->item=NULL;
t->size=t->maxsize=0;
}
-void TableFree(TTable *t)
+void TableFree(TTable * const t)
{
uint16_t i;
@@ -349,18 +412,23 @@
if (t->size)
for (i=t->size;i>0;i--)
{
- safe_free(t->item[i-1].name);
- safe_free(t->item[i-1].value);
+ free(t->item[i-1].name);
+ free(t->item[i-1].value);
};
- safe_free(t->item);
+ free(t->item);
}
TableInit(t);
}
-abyss_bool TableFindIndex(TTable *t,char *name,uint16_t *index)
-{
+
+
+bool
+TableFindIndex(TTable * const t,
+ const char * const name,
+ uint16_t * const index) {
+
uint16_t i,hash=Hash16(name);
if ((t->item) && (t->size>0) && (*index<t->size))
@@ -377,18 +445,23 @@
return FALSE;
}
-abyss_bool TableAddReplace(TTable *t,char *name,char *value)
-{
+
+
+bool
+TableAddReplace(TTable * const t,
+ const char * const name,
+ const char * const value) {
+
uint16_t i=0;
if (TableFindIndex(t,name,&i))
{
- safe_free(t->item[i].value);
+ free(t->item[i].value);
if (value)
t->item[i].value=strdup(value);
else
{
- safe_free(t->item[i].name);
+ free(t->item[i].name);
if (--t->size>0)
t->item[i]=t->item[t->size];
};
@@ -401,8 +474,10 @@
-abyss_bool
-TableAdd(TTable *t,char *name,char *value) {
+bool
+TableAdd(TTable * const t,
+ const char * const name,
+ const char * const value) {
if (t->size>=t->maxsize) {
TTableItem *newitem;
@@ -427,8 +502,12 @@
return TRUE;
}
-char *TableFind(TTable *t,char *name)
-{
+
+
+char *
+TableFind(TTable * const t,
+ const char * const name) {
+
uint16_t i=0;
if (TableFindIndex(t,name,&i))
@@ -442,103 +521,159 @@
*********************************************************************/
static TPoolZone *
-PoolZoneAlloc(uint32_t zonesize) {
- TPoolZone *pz;
-
- pz=(TPoolZone *)malloc(zonesize+sizeof(TPoolZone));
- if (pz)
- {
- pz->pos=pz->data;
- pz->maxpos=pz->pos+zonesize;
- pz->next=pz->prev=NULL;
- };
+PoolZoneAlloc(uint32_t const zonesize) {
- return pz;
+ TPoolZone * poolZoneP;
+
+ MALLOCARRAY(poolZoneP, zonesize);
+ if (poolZoneP) {
+ poolZoneP->pos = &poolZoneP->data[0];
+ poolZoneP->maxpos = poolZoneP->pos + zonesize;
+ poolZoneP->next = NULL;
+ poolZoneP->prev = NULL;
+ }
+ return poolZoneP;
}
-abyss_bool PoolCreate(TPool *p,uint32_t zonesize)
-{
- p->zonesize=zonesize;
- if (MutexCreate(&p->mutex))
- if (!(p->firstzone=p->currentzone=PoolZoneAlloc(zonesize)))
- {
- MutexFree(&p->mutex);
- return FALSE;
- };
-
- return TRUE;
+
+
+static void
+PoolZoneFree(TPoolZone * const poolZoneP) {
+
+ free(poolZoneP);
}
-void *PoolAlloc(TPool *p,uint32_t size)
-{
- TPoolZone *pz,*npz;
- void *x;
- uint32_t zonesize;
- if (size==0)
- return NULL;
- if (!MutexLock(&p->mutex))
- return NULL;
+bool
+PoolCreate(TPool * const poolP,
+ uint32_t const zonesize) {
- pz=p->currentzone;
+ bool success;
+ bool mutexCreated;
- if (pz->pos+size<pz->maxpos)
- {
- x=pz->pos;
- pz->pos+=size;
- MutexUnlock(&p->mutex);
- return x;
- };
+ poolP->zonesize = zonesize;
- if (size>p->zonesize)
- zonesize=size;
- else
- zonesize=p->zonesize;
+ mutexCreated = MutexCreate(&poolP->mutexP);
+ if (mutexCreated) {
+ TPoolZone * const firstZoneP = PoolZoneAlloc(zonesize);
- npz=PoolZoneAlloc(zonesize);
- if (npz)
- {
- npz->prev=pz;
- npz->next=pz->next;
- pz->next=npz;
- p->currentzone=npz;
- x=npz->data;
- npz->pos=npz->data+size;
- }
- else
- x=NULL;
+ if (firstZoneP != NULL) {
+ poolP->firstzone = firstZoneP;
+ poolP->currentzone = firstZoneP;
+ success = TRUE;
+ } else
+ success = FALSE;
+ if (!success)
+ MutexDestroy(poolP->mutexP);
+ } else
+ success = FALSE;
- MutexUnlock(&p->mutex);
- return x;
+ return success;
}
-void PoolFree(TPool *p)
-{
- TPoolZone *pz,*npz;
- pz=p->firstzone;
- while (pz)
- {
- npz=pz->next;
- safe_free(pz);
- pz=npz;
- };
+void *
+PoolAlloc(TPool * const poolP,
+ uint32_t const size) {
+/*----------------------------------------------------------------------------
+ Allocate a block of size 'size' from pool 'poolP'.
+-----------------------------------------------------------------------------*/
+ void * retval;
+
+ if (size == 0)
+ retval = NULL;
+ else {
+ bool gotMutexLock;
+
+ gotMutexLock = MutexLock(poolP->mutexP);
+ if (!gotMutexLock)
+ retval = NULL;
+ else {
+ TPoolZone * const curPoolZoneP = poolP->currentzone;
+
+ if (curPoolZoneP->pos + size < curPoolZoneP->maxpos) {
+ retval = curPoolZoneP->pos;
+ curPoolZoneP->pos += size;
+ } else {
+ uint32_t const zonesize = MAX(size, poolP->zonesize);
+
+ TPoolZone * const newPoolZoneP = PoolZoneAlloc(zonesize);
+ if (newPoolZoneP) {
+ newPoolZoneP->prev = curPoolZoneP;
+ newPoolZoneP->next = curPoolZoneP->next;
+ curPoolZoneP->next = newPoolZoneP;
+ poolP->currentzone = newPoolZoneP;
+ retval= newPoolZoneP->data;
+ newPoolZoneP->pos = newPoolZoneP->data + size;
+ } else
+ retval = NULL;
+ }
+ MutexUnlock(poolP->mutexP);
+ }
+ }
+ return retval;
}
-char *PoolStrdup(TPool *p,char *s) {
+void
+PoolReturn(TPool * const poolP,
+ void * const blockP) {
+/*----------------------------------------------------------------------------
+ Return the block at 'blockP' to the pool 'poolP'. WE ASSUME THAT IS
+ THE MOST RECENTLY ALLOCATED AND NOT RETURNED BLOCK IN THE POOL.
+-----------------------------------------------------------------------------*/
+ TPoolZone * const curPoolZoneP = poolP->currentzone;
+
+ assert((char*)curPoolZoneP->data < (char*)blockP &&
+ (char*)blockP < (char*)curPoolZoneP->pos);
+
+ curPoolZoneP->pos = blockP;
+
+ if (curPoolZoneP->pos == curPoolZoneP->data) {
+ /* That emptied out the current zone. Free it and make the previous
+ zone current.
+ */
+
+ assert(curPoolZoneP->prev); /* entry condition */
+
+ curPoolZoneP->prev->next = NULL;
+
+ PoolZoneFree(curPoolZoneP);
+ }
+}
+
+
+
+void
+PoolFree(TPool * const poolP) {
+
+ TPoolZone * poolZoneP;
+ TPoolZone * nextPoolZoneP;
+
+ for (poolZoneP = poolP->firstzone; poolZoneP; poolZoneP = nextPoolZoneP) {
+ nextPoolZoneP = poolZoneP->next;
+ free(poolZoneP);
+ }
+ MutexDestroy(poolP->mutexP);
+}
- char *ns;
- if (s) {
- ns = PoolAlloc(p, strlen(s) + 1);
- if (ns)
- strcpy(ns, s);
- } else
- ns = NULL;
- return ns;
+const char *
+PoolStrdup(TPool * const poolP,
+ const char * const origString) {
+
+ char * newString;
+
+ if (origString == NULL)
+ newString = NULL;
+ else {
+ newString = PoolAlloc(poolP, strlen(origString) + 1);
+ if (newString != NULL)
+ strcpy(newString, origString);
+ }
+ return newString;
}
Added: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/data.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/data.h Fri May 23 16:56:24 2008
@@ -0,0 +1,179 @@
+#ifndef DATA_H_INCLUDED
+#define DATA_H_INCLUDED
+
+#include "bool.h"
+#include "int.h"
+
+struct abyss_mutex;
+
+/*********************************************************************
+** Buffer
+*********************************************************************/
+
+typedef struct
+{
+ void *data;
+ xmlrpc_uint32_t size;
+ xmlrpc_uint32_t staticid;
+} TBuffer;
+
+bool
+BufferAlloc(TBuffer * const buf,
+ xmlrpc_uint32_t const memsize);
+
+bool
+BufferRealloc(TBuffer * const buf,
+ xmlrpc_uint32_t const memsize);
+
+void
+BufferFree(TBuffer * const buf);
+
+
+/*********************************************************************
+** String
+*********************************************************************/
+
+typedef struct
+{
+ TBuffer buffer;
+ xmlrpc_uint32_t size;
+} TString;
+
+bool
+StringAlloc(TString * const stringP);
+
+bool
+StringConcat(TString * const stringP,
+ const char * const string2);
+
+bool
+StringBlockConcat(TString * const stringP,
+ const char * const string2,
+ char ** const ref);
+
+void
+StringFree(TString * const stringP);
+
+char *
+StringData(TString * const stringP);
+
+
+/*********************************************************************
+** List
+*********************************************************************/
+
+typedef struct {
+ void **item;
+ uint16_t size;
+ uint16_t maxsize;
+ bool autofree;
+} TList;
+
+void
+ListInit(TList * const listP);
+
+void
+ListInitAutoFree(TList * const listP);
+
+void
+ListFree(TList * const listP);
+
+void
+ListFreeItems(TList * const listP);
+
+bool
+ListAdd(TList * const listP,
+ void * const str);
+
+void
+ListRemove(TList * const listP);
+
+bool
+ListAddFromString(TList * const listP,
+ const char * const c);
+
+bool
+ListFindString(TList * const listP,
+ const char * const str,
+ uint16_t * const indexP);
+
+
+typedef struct
+{
+ char *name,*value;
+ uint16_t hash;
+} TTableItem;
+
+typedef struct
+{
+ TTableItem *item;
+ uint16_t size,maxsize;
+} TTable;
+
+void
+TableInit(TTable * const t);
+
+void
+TableFree(TTable * const t);
+
+bool
+TableAdd(TTable * const t,
+ const char * const name,
+ const char * const value);
+
+bool
+TableAddReplace(TTable * const t,
+ const char * const name,
+ const char * const value);
+
+bool
+TableFindIndex(TTable * const t,
+ const char * const name,
+ uint16_t * const index);
+
+char *
+TableFind(TTable * const t,
+ const char * const name);
+
+
+/*********************************************************************
+** Pool
+*********************************************************************/
+
+typedef struct _TPoolZone {
+ char * pos;
+ char * maxpos;
+ struct _TPoolZone * next;
+ struct _TPoolZone * prev;
+/* char data[0]; Some compilers don't accept this */
+ char data[1];
+} TPoolZone;
+
+typedef struct {
+ TPoolZone * firstzone;
+ TPoolZone * currentzone;
+ uint32_t zonesize;
+ struct abyss_mutex * mutexP;
+} TPool;
+
+bool
+PoolCreate(TPool * const poolP,
+ uint32_t const zonesize);
+
+void
+PoolFree(TPool * const poolP);
+
+void *
+PoolAlloc(TPool * const poolP,
+ uint32_t const size);
+
+void
+PoolReturn(TPool * const poolP,
+ void * const blockP);
+
+const char *
+PoolStrdup(TPool * const poolP,
+ const char * const origString);
+
+
+#endif
Added: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/date.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/date.c Fri May 23 16:56:24 2008
@@ -0,0 +1,206 @@
+#include <stdlib.h>
+#include <assert.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdio.h>
+#include <time.h>
+
+#include "bool.h"
+#include "int.h"
+#include "xmlrpc-c/string_int.h"
+#include "xmlrpc-c/time_int.h"
+#include "xmlrpc-c/abyss.h"
+
+#include "date.h"
+
+/*********************************************************************
+** Date
+*********************************************************************/
+
+static char *_DateDay[7]=
+{
+ "Sun","Mon","Tue","Wed","Thu","Fri","Sat"
+};
+
+static char *_DateMonth[12]=
+{
+ "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"
+};
+
+
+
+void
+DateToString(time_t const datetime,
+ const char ** const dateStringP) {
+
+ struct tm brokenTime;
+
+ xmlrpc_gmtime(datetime, &brokenTime);
+
+ if (mktime(&brokenTime) == (time_t)-1)
+ *dateStringP = NULL;
+ else
+ xmlrpc_asprintf(dateStringP, "%s, %02u %s %04u %02u:%02u:%02u UTC",
+ _DateDay[brokenTime.tm_wday],
+ brokenTime.tm_mday,
+ _DateMonth[brokenTime.tm_mon],
+ 1900 + brokenTime.tm_year,
+ brokenTime.tm_hour,
+ brokenTime.tm_min,
+ brokenTime.tm_sec);
+}
+
+
+
+static const char *
+tzOffsetStr(struct tm const tm,
+ time_t const datetime) {
+
+ const char * retval;
+ time_t timeIfUtc;
+ const char * error;
+
+ xmlrpc_timegm(&tm, &timeIfUtc, &error);
+
+ if (error) {
+ xmlrpc_strfree(error);
+ xmlrpc_asprintf(&retval, "%s", "+????");
+ } else {
+ int const tzOffset = (int)(datetime - timeIfUtc);
+
+ assert(tzOffset == datetime - timeIfUtc);
+
+ xmlrpc_asprintf(&retval, "%+03d%02d",
+ tzOffset/3600, abs(tzOffset % 3600)/60);
+ }
+ return retval;
+}
+
+
+
+void
+DateToLogString(time_t const datetime,
+ const char ** const dateStringP) {
+
+ const char * tzo;
+ struct tm tm;
+
+ xmlrpc_localtime(datetime, &tm);
+
+ tzo = tzOffsetStr(tm, datetime);
+
+ xmlrpc_asprintf(dateStringP, "%02d/%s/%04d:%02d:%02d:%02d %s",
+ tm.tm_mday, _DateMonth[tm.tm_mon],
+ 1900 + tm.tm_year, tm.tm_hour, tm.tm_min, tm.tm_sec,
+ tzo);
+
+ xmlrpc_strfree(tzo);
+}
+
+
+
+void
+DateDecode(const char * const dateString,
+ bool * const validP,
+ time_t * const datetimeP) {
+/*----------------------------------------------------------------------------
+ Return the datetime represented by 'dateString', which is in the
+ format used in an HTTP header.
+
+ We assume that format is always UTC-based; I don't know if HTTP
+ actually requires that -- maybe it could be some local time.
+-----------------------------------------------------------------------------*/
+ int rc;
+ const char * s;
+ unsigned int monthOff;
+ struct tm tm;
+ bool error;
+
+ s = &dateString[0];
+
+ /* Ignore spaces, day name and spaces */
+ while ((*s==' ') || (*s=='\t'))
+ ++s;
+
+ while ((*s!=' ') && (*s!='\t'))
+ ++s;
+
+ while ((*s==' ') || (*s=='\t'))
+ ++s;
+
+ error = false; /* initial value */
+
+ /* try to recognize the date format */
+ rc = sscanf(s, "%*s %d %d:%d:%d %d%*s",
+ &tm.tm_mday, &tm.tm_hour,
+ &tm.tm_min, &tm.tm_sec, &tm.tm_year);
+ if (rc == 5)
+ monthOff = 0;
+ else {
+ int rc;
+ rc = sscanf(s, "%d %n%*s %d %d:%d:%d GMT%*s",
+ &tm.tm_mday, &monthOff, &tm.tm_year,
+ &tm.tm_hour, &tm.tm_min, &tm.tm_sec);
+ if (rc != 5) {
+ int rc;
+ rc = sscanf(s, "%d-%n%*[A-Za-z]-%d %d:%d:%d GMT%*s",
+ &tm.tm_mday, &monthOff, &tm.tm_year,
+ &tm.tm_hour, &tm.tm_min, &tm.tm_sec);
+ if (rc != 5)
+ error = true;
+ }
+ }
+ if (!error) {
+ const char * monthName = s + monthOff;
+ /* This is actually just the point in 'dateString' where
+ the month name begins -- it's not a nul-terminated string
+ */
+
+ unsigned int i;
+ bool gotMonth;
+
+ for (i = 0, gotMonth = false; i < 12; ++i) {
+ const char * p;
+
+ p =_DateMonth[i];
+
+ if (tolower(*p++) == tolower(monthName[0]))
+ if (*p++ == tolower(monthName[1]))
+ if (*p == tolower(monthName[2])) {
+ gotMonth = true;
+ tm.tm_mon = i;
+ }
+ }
+
+ if (!gotMonth)
+ error = true;
+ else {
+ if (tm.tm_year > 1900)
+ tm.tm_year -= 1900;
+ else {
+ if (tm.tm_year < 70)
+ tm.tm_year += 100;
+ }
+ tm.tm_isdst = 0;
+
+ {
+ const char * timeError;
+ xmlrpc_timegm(&tm, datetimeP, &timeError);
+
+ if (timeError) {
+ error = TRUE;
+ xmlrpc_strfree(timeError);
+ }
+ }
+ }
+ }
+ *validP = !error;
+}
+
+
+
+abyss_bool
+DateInit(void) {
+
+ return true;
+}
Added: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/date.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/date.h Fri May 23 16:56:24 2008
@@ -0,0 +1,21 @@
+#ifndef DATE_H_INCLUDED
+#define DATE_H_INCLUDED
+
+#include <time.h>
+
+#include "bool.h"
+
+void
+DateToString(time_t const datetime,
+ const char ** const dateStringP);
+
+void
+DateToLogString(time_t const datetime,
+ const char ** const dateStringP);
+
+void
+DateDecode(const char * const dateString,
+ bool * const validP,
+ time_t * const datetimeP);
+
+#endif
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/file.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/file.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/file.c Fri May 23 16:56:24 2008
@@ -32,204 +32,382 @@
**
******************************************************************************/
+#include "xmlrpc_config.h"
+#include "mallocvar.h"
+
+#define _CRT_SECURE_NO_WARNINGS
+ /* Tell msvcrt not to warn about functions that are often misused and
+ cause security exposures.
+ */
+
+#define _FILE_OFFSET_BITS 64
+ /* Tell GNU libc to make off_t 64 bits and all the POSIX file functions
+ the versions that handle 64 bit file offsets.
+ */
+#define _LARGE_FILES
+ /* Same as above, but for AIX */
+
#include <string.h>
-#ifdef ABYSS_WIN32
-#include <io.h>
-#else
-/* Must check this
-#include <sys/io.h>
-*/
-#endif /* ABYSS_WIN32 */
-
-#ifndef ABYSS_WIN32
-#include <dirent.h>
-#endif /* ABYSS_WIN32 */
+#if MSVCRT
+ #include <io.h>
+ typedef __int64 readwriterc_t;
+#else
+ #include <unistd.h>
+ #include <fcntl.h>
+ #include <dirent.h>
+ #include <sys/stat.h>
+ typedef ssize_t readwriterc_t;
+#endif
+#include "bool.h"
+#include "xmlrpc-c/string_int.h"
#include "xmlrpc-c/abyss.h"
+#include "file.h"
+
+bool const win32 =
+#ifdef WIN32
+TRUE;
+#else
+FALSE;
+#endif
+
+struct TFileFind {
+#ifdef WIN32
+ #if MSVCRT
+ intptr_t handle;
+ #else
+ HANDLE handle;
+ #endif
+#else
+ char path[NAME_MAX+1];
+ DIR * handle;
+#endif
+};
+
+
/*********************************************************************
** File
*********************************************************************/
-abyss_bool FileOpen(TFile *f, const char *name,uint32_t attrib)
-{
-#if defined( ABYSS_WIN32 ) && !defined( __BORLANDC__ )
- return ((*f=_open(name,attrib))!=(-1));
-#else
- return ((*f=open(name,attrib))!=(-1));
-#endif
+static void
+createFileImage(TFile ** const filePP,
+ const char * const name,
+ uint32_t const attrib,
+ bool const createFile,
+ bool * const succeededP) {
+
+ TFile * fileP;
+
+ MALLOCVAR(fileP);
+ if (fileP == NULL)
+ *succeededP = FALSE;
+ else {
+ int rc;
+
+ if (createFile)
+ rc = open(name, attrib | O_CREAT, S_IWRITE | S_IREAD);
+ else
+ rc = open(name, attrib);
+
+ if (rc < 0)
+ *succeededP = FALSE;
+ else {
+ fileP->fd = rc;
+ *succeededP = TRUE;
+ }
+ if (!*succeededP)
+ free(fileP);
+ }
+ *filePP = fileP;
}
-abyss_bool FileOpenCreate(TFile *f, const char *name, uint32_t attrib)
-{
-#if defined( ABYSS_WIN32 ) && !defined( __BORLANDC__ )
- return ((*f=_open(name,attrib | O_CREAT,_S_IWRITE | _S_IREAD))!=(-1));
-#else
- return ((*f=open(name,attrib | O_CREAT,S_IWRITE | S_IREAD))!=(-1));
-#endif
+
+
+bool
+FileOpen(TFile ** const filePP,
+ const char * const name,
+ uint32_t const attrib) {
+
+ bool succeeded;
+
+ createFileImage(filePP, name, attrib, FALSE, &succeeded);
+
+ return succeeded;
}
-abyss_bool FileWrite(TFile *f, void *buffer, uint32_t len)
-{
-#if defined( ABYSS_WIN32 ) && !defined( __BORLANDC__ )
- return (_write(*f,buffer,len)==(int32_t)len);
-#else
- return (write(*f,buffer,len)==(int32_t)len);
-#endif
+
+
+bool
+FileOpenCreate(TFile ** const filePP,
+ const char * const name,
+ uint32_t const attrib) {
+
+ bool succeeded;
+
+ createFileImage(filePP, name, attrib, TRUE, &succeeded);
+
+ return succeeded;
}
-int32_t FileRead(TFile *f, void *buffer, uint32_t len)
-{
-#if defined( ABYSS_WIN32 ) && !defined( __BORLANDC__ )
- return (_read(*f,buffer,len));
-#else
- return (read(*f,buffer,len));
-#endif
+
+
+bool
+FileWrite(const TFile * const fileP,
+ const void * const buffer,
+ uint32_t const len) {
+
+ readwriterc_t rc;
+
+ rc = write(fileP->fd, buffer, len);
+
+ return (rc > 0 && (uint32_t)rc == len);
+}
+
+
+
+int32_t
+FileRead(const TFile * const fileP,
+ void * const buffer,
+ uint32_t const len) {
+
+ return read(fileP->fd, buffer, len);
}
-abyss_bool FileSeek(TFile *f, uint64_t pos, uint32_t attrib)
-{
-#if defined( ABYSS_WIN32 ) && !defined( __BORLANDC__ )
- return (_lseek(*f,pos,attrib)!=(-1));
+
+
+bool
+FileSeek(const TFile * const fileP,
+ uint64_t const pos,
+ uint32_t const attrib) {
+
+ int64_t rc;
+#if MSVCRT
+ rc = _lseeki64(fileP->fd, pos, attrib);
#else
- return (lseek(*f,pos,attrib)!=(-1));
+ rc = lseek(fileP->fd, pos, attrib);
#endif
+ return (rc >= 0);
}
-uint64_t FileSize(TFile *f)
-{
-#if defined( ABYSS_WIN32 ) && !defined( __BORLANDC__ )
- return (_filelength(*f));
+
+
+uint64_t
+FileSize(const TFile * const fileP) {
+
+#if MSVCRT
+ return (_filelength(fileP->fd));
#else
struct stat fs;
- fstat(*f,&fs);
+ fstat(fileP->fd, &fs);
return (fs.st_size);
#endif
}
-abyss_bool FileClose(TFile *f)
-{
-#if defined( ABYSS_WIN32 ) && !defined( __BORLANDC__ )
- return (_close(*f)!=(-1));
-#else
- return (close(*f)!=(-1));
-#endif
+
+
+bool
+FileClose(TFile * const fileP) {
+
+ int rc;
+
+ rc = close(fileP->fd);
+
+ if (rc >= 0)
+ free(fileP);
+
+ return (rc >= 0);
}
-abyss_bool FileStat(char *filename,TFileStat *filestat)
-{
-#if defined( ABYSS_WIN32 ) && !defined( __BORLANDC__ )
- return (_stati64(filename,filestat)!=(-1));
+
+
+bool
+FileStat(const char * const filename,
+ TFileStat * const filestat) {
+
+ int rc;
+
+#if MSVCRT
+ rc = _stati64(filename,filestat);
#else
- return (stat(filename,filestat)!=(-1));
+ rc = stat(filename,filestat);
#endif
+ return (rc >= 0);
}
-abyss_bool FileFindFirst(TFileFind *filefind,char *path,TFileInfo *fileinfo)
-{
-#ifdef ABYSS_WIN32
- abyss_bool ret;
- char *p=path+strlen(path);
- *p='\\';
- *(p+1)='*';
- *(p+2)='\0';
-#ifndef __BORLANDC__
- ret=(((*filefind)=_findfirst(path,fileinfo))!=(-1));
+
+static void
+fileFindFirstWin(TFileFind * const filefindP ATTR_UNUSED,
+ const char * const path,
+ TFileInfo * const fileinfo ATTR_UNUSED,
+ bool * const retP ATTR_UNUSED) {
+ const char * search;
+
+ xmlrpc_asprintf(&search, "%s\\*", path);
+
+#if MSVCRT
+ filefindP->handle = _findfirsti64(search, fileinfo);
+ *retP = filefindP->handle != -1;
#else
- *filefind = FindFirstFile( path, &fileinfo->data );
- ret = *filefind != NULL;
- if( ret )
- {
- LARGE_INTEGER li;
- li.LowPart = fileinfo->data.nFileSizeLow;
- li.HighPart = fileinfo->data.nFileSizeHigh;
- strcpy( fileinfo->name, fileinfo->data.cFileName );
- fileinfo->attrib = fileinfo->data.dwFileAttributes;
- fileinfo->size = li.QuadPart;
- fileinfo->time_write = fileinfo->data.ftLastWriteTime.dwLowDateTime;
- }
+#ifdef WIN32
+ filefindP->handle = FindFirstFile(search, &fileinfo->data);
+ *retP = filefindP->handle != INVALID_HANDLE_VALUE;
+ if (*retP) {
+ LARGE_INTEGER li;
+ li.LowPart = fileinfo->data.nFileSizeLow;
+ li.HighPart = fileinfo->data.nFileSizeHigh;
+ strcpy( fileinfo->name, fileinfo->data.cFileName );
+ fileinfo->attrib = fileinfo->data.dwFileAttributes;
+ fileinfo->size = li.QuadPart;
+ fileinfo->time_write = fileinfo->data.ftLastWriteTime.dwLowDateTime;
+ }
#endif
- *p='\0';
- return ret;
-#else
- strncpy(filefind->path,path,NAME_MAX);
- filefind->path[NAME_MAX]='\0';
- filefind->handle=opendir(path);
- if (filefind->handle)
- return FileFindNext(filefind,fileinfo);
+#endif
+ xmlrpc_strfree(search);
+}
- return FALSE;
+
+
+static void
+fileFindFirstPosix(TFileFind * const filefindP,
+ const char * const path,
+ TFileInfo * const fileinfo,
+ bool * const retP) {
+
+#if !MSVCRT
+ strncpy(filefindP->path, path, NAME_MAX);
+ filefindP->path[NAME_MAX] = '\0';
+ filefindP->handle = opendir(path);
+ if (filefindP->handle)
+ *retP = FileFindNext(filefindP, fileinfo);
+ else
+ *retP = FALSE;
#endif
}
+
+
+
+bool
+FileFindFirst(TFileFind ** const filefindPP,
+ const char * const path,
+ TFileInfo * const fileinfo) {
+
+ bool succeeded;
+
+ TFileFind * filefindP;
-abyss_bool FileFindNext(TFileFind *filefind,TFileInfo *fileinfo)
-{
-#ifdef ABYSS_WIN32
+ MALLOCVAR(filefindP);
-#ifndef __BORLANDC__
- return (_findnext(*filefind,fileinfo)!=(-1));
+ if (filefindP == NULL)
+ succeeded = FALSE;
+ else {
+ if (win32)
+ fileFindFirstWin(filefindP, path, fileinfo, &succeeded);
+ else
+ fileFindFirstPosix(filefindP, path, fileinfo, &succeeded);
+ if (!succeeded)
+ free(filefindP);
+ }
+ *filefindPP = filefindP;
+
+ return succeeded;
+}
+
+
+
+static void
+fileFindNextWin(TFileFind * const filefindP ATTR_UNUSED,
+ TFileInfo * const fileinfo ATTR_UNUSED,
+ bool * const retvalP ATTR_UNUSED) {
+
+#if MSVCRT
+ *retvalP = _findnexti64(filefindP->handle, fileinfo) != -1;
#else
- abyss_bool ret = FindNextFile( *filefind, &fileinfo->data );
- if( ret )
- {
- LARGE_INTEGER li;
- li.LowPart = fileinfo->data.nFileSizeLow;
- li.HighPart = fileinfo->data.nFileSizeHigh;
- strcpy( fileinfo->name, fileinfo->data.cFileName );
- fileinfo->attrib = fileinfo->data.dwFileAttributes;
- fileinfo->size = li.QuadPart;
- fileinfo->time_write = fileinfo->data.ftLastWriteTime.dwLowDateTime;
- }
- return ret;
+#ifdef WIN32
+ bool found;
+ found = FindNextFile(filefindP->handle, &fileinfo->data);
+ if (found) {
+ LARGE_INTEGER li;
+ li.LowPart = fileinfo->data.nFileSizeLow;
+ li.HighPart = fileinfo->data.nFileSizeHigh;
+ strcpy(fileinfo->name, fileinfo->data.cFileName);
+ fileinfo->attrib = fileinfo->data.dwFileAttributes;
+ fileinfo->size = li.QuadPart;
+ fileinfo->time_write = fileinfo->data.ftLastWriteTime.dwLowDateTime;
+ }
+ *retvalP = found;
+#endif
#endif
+}
-#else
- struct dirent *de;
- /****** Must be changed ***/
- char z[NAME_MAX+1];
- de=readdir(filefind->handle);
- if (de)
- {
+
+static void
+fileFindNextPosix(TFileFind * const filefindP,
+ TFileInfo * const fileinfoP,
+ bool * const retvalP) {
+
+#ifndef WIN32
+ struct dirent * deP;
+
+ deP = readdir(filefindP->handle);
+ if (deP) {
+ char z[NAME_MAX+1];
struct stat fs;
- strcpy(fileinfo->name,de->d_name);
- strcpy(z,filefind->path);
- strncat(z,"/",NAME_MAX);
- strncat(z,fileinfo->name,NAME_MAX);
- z[NAME_MAX]='\0';
+ strcpy(fileinfoP->name, deP->d_name);
+ strcpy(z, filefindP->path);
+ strncat(z, "/",NAME_MAX);
+ strncat(z, fileinfoP->name, NAME_MAX);
+ z[NAME_MAX] = '\0';
- stat(z,&fs);
+ stat(z, &fs);
if (fs.st_mode & S_IFDIR)
- fileinfo->attrib=A_SUBDIR;
+ fileinfoP->attrib = A_SUBDIR;
else
- fileinfo->attrib=0;
+ fileinfoP->attrib = 0;
- fileinfo->size=fs.st_size;
- fileinfo->time_write=fs.st_mtime;
+ fileinfoP->size = fs.st_size;
+ fileinfoP->time_write = fs.st_mtime;
- return TRUE;
- };
-
- return FALSE;
+ *retvalP = TRUE;
+ } else
+ *retvalP = FALSE;
#endif
}
-void FileFindClose(TFileFind *filefind)
-{
-#ifdef ABYSS_WIN32
-#ifndef __BORLANDC__
- _findclose(*filefind);
+
+bool
+FileFindNext(TFileFind * const filefindP,
+ TFileInfo * const fileinfo) {
+
+ bool retval;
+
+ if (win32)
+ fileFindNextWin(filefindP, fileinfo, &retval);
+ else
+ fileFindNextPosix(filefindP, fileinfo, &retval);
+
+ return retval;
+}
+
+
+
+void
+FileFindClose(TFileFind * const filefindP) {
+#ifdef WIN32
+#if MSVCRT
+ _findclose(filefindP->handle);
#else
- FindClose( *filefind );
+ FindClose(filefindP->handle);
#endif
-
#else
- closedir(filefind->handle);
+ closedir(filefindP->handle);
#endif
+ free(filefindP);
}
Added: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/file.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/file.h Fri May 23 16:56:24 2008
@@ -0,0 +1,128 @@
+#ifndef FILE_H_INCLUDED
+#define FILE_H_INCLUDED
+
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <limits.h>
+
+#include "bool.h"
+#include "int.h"
+#include "xmlrpc-c/abyss.h"
+
+#ifndef NAME_MAX
+#define NAME_MAX 1024
+#endif
+
+#ifdef WIN32
+#ifndef __BORLANDC__
+#define O_APPEND _O_APPEND
+#define O_CREAT _O_CREAT
+#define O_EXCL _O_EXCL
+#define O_RDONLY _O_RDONLY
+#define O_RDWR _O_RDWR
+#define O_TRUNC _O_TRUNC
+#define O_WRONLY _O_WRONLY
+#define O_TEXT _O_TEXT
+#define O_BINARY _O_BINARY
+#endif
+
+#define A_HIDDEN _A_HIDDEN
+#define A_NORMAL _A_NORMAL
+#define A_RDONLY _A_RDONLY
+#define A_SUBDIR _A_SUBDIR
+#else
+#define A_SUBDIR 1
+#define O_BINARY 0
+#define O_TEXT 0
+#endif /* WIN32 */
+
+#ifdef WIN32
+
+#if MSVCRT
+typedef struct _stati64 TFileStat;
+typedef struct _finddatai64_t TFileInfo;
+
+#else /* MSVCRT */
+
+typedef struct stat TFileStat;
+typedef struct finddata_t {
+ char name[NAME_MAX+1];
+ int attrib;
+ uint64_t size;
+ time_t time_write;
+ WIN32_FIND_DATA data;
+} TFileInfo;
+
+#endif /* MSVCRT */
+
+#else /* WIN32 */
+
+#include <unistd.h>
+#include <dirent.h>
+
+typedef struct stat TFileStat;
+
+typedef struct finddata_t {
+ char name[NAME_MAX+1];
+ int attrib;
+ uint64_t size;
+ time_t time_write;
+} TFileInfo;
+
+#endif
+
+typedef struct TFileFind TFileFind;
+
+typedef struct TFile {
+ int fd;
+} TFile;
+
+bool
+FileOpen(TFile ** const filePP,
+ const char * const name,
+ uint32_t const attrib);
+
+bool
+FileOpenCreate(TFile ** const filePP,
+ const char * const name,
+ uint32_t const attrib);
+
+bool
+FileClose(TFile * const fileP);
+
+bool
+FileWrite(const TFile * const fileP,
+ const void * const buffer,
+ uint32_t const len);
+
+int32_t
+FileRead(const TFile * const fileP,
+ void * const buffer,
+ uint32_t const len);
+
+bool
+FileSeek(const TFile * const fileP,
+ uint64_t const pos,
+ uint32_t const attrib);
+
+uint64_t
+FileSize(const TFile * const fileP);
+
+bool
+FileStat(const char * const filename,
+ TFileStat * const filestat);
+
+bool
+FileFindFirst(TFileFind ** const filefind,
+ const char * const path,
+ TFileInfo * const fileinfo);
+
+bool
+FileFindNext(TFileFind * const filefind,
+ TFileInfo * const fileinfo);
+
+void
+FileFindClose(TFileFind * const filefind);
+
+#endif
Added: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/handler.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/handler.c Fri May 23 16:56:24 2008
@@ -0,0 +1,784 @@
+/*=============================================================================
+ handler.c
+===============================================================================
+ This file contains built-in HTTP request handlers.
+
+ Copyright information is at end of file
+=============================================================================*/
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+#ifdef WIN32
+ #include <io.h>
+#else
+ #include <unistd.h>
+#endif
+#include <fcntl.h>
+
+#include "xmlrpc_config.h"
+#include "bool.h"
+#include "int.h"
+#include "girmath.h"
+#include "mallocvar.h"
+#include "xmlrpc-c/string_int.h"
+#include "xmlrpc-c/time_int.h"
+
+#include "xmlrpc-c/abyss.h"
+#include "trace.h"
+#include "session.h"
+#include "file.h"
+#include "conn.h"
+#include "http.h"
+#include "date.h"
+#include "abyss_info.h"
+
+#include "handler.h"
+
+
+
+struct BIHandler {
+ const char * filesPath;
+ TList defaultFileNames;
+ MIMEType * mimeTypeP;
+ /* NULL means to use the global MIMEType object */
+};
+
+
+
+BIHandler *
+HandlerCreate(void) {
+
+ struct BIHandler * handlerP;
+
+ MALLOCVAR(handlerP);
+
+ if (handlerP) {
+ handlerP->filesPath = strdup(DEFAULT_DOCS);
+ ListInitAutoFree(&handlerP->defaultFileNames);
+ handlerP->mimeTypeP = NULL;
+ }
+ return handlerP;
+}
+
+
+
+void
+HandlerDestroy(BIHandler * const handlerP) {
+
+ ListFree(&handlerP->defaultFileNames);
+
+ xmlrpc_strfree(handlerP->filesPath);
+
+ free(handlerP);
+}
+
+
+
+void
+HandlerSetMimeType(BIHandler * const handlerP,
+ MIMEType * const mimeTypeP) {
+
+ handlerP->mimeTypeP = mimeTypeP;
+}
+
+
+
+void
+HandlerSetFilesPath(BIHandler * const handlerP,
+ const char * const filesPath) {
+
+ xmlrpc_strfree(handlerP->filesPath);
+ handlerP->filesPath = strdup(filesPath);
+}
+
+
+
+void
+HandlerAddDefaultFN(BIHandler * const handlerP,
+ const char * const fileName) {
+
+ ListAdd(&handlerP->defaultFileNames, strdup(fileName));
+}
+
+
+
+typedef int (*TQSortProc)(const void *, const void *);
+
+static int
+cmpfilenames(const TFileInfo **f1,const TFileInfo **f2) {
+ if (((*f1)->attrib & A_SUBDIR) && !((*f2)->attrib & A_SUBDIR))
+ return (-1);
+ if (!((*f1)->attrib & A_SUBDIR) && ((*f2)->attrib & A_SUBDIR))
+ return 1;
+
+ return strcmp((*f1)->name,(*f2)->name);
+}
+
+
+
+static int
+cmpfiledates(const TFileInfo ** const f1PP,
+ const TFileInfo ** const f2PP) {
+
+ const TFileInfo * const f1P = *f1PP;
+ const TFileInfo * const f2P = *f2PP;
+
+ int retval;
+
+ if ((f1P->attrib & A_SUBDIR) && !(f2P->attrib & A_SUBDIR))
+ retval = -1;
+ else if (!(f1P->attrib & A_SUBDIR) && (f2P->attrib & A_SUBDIR))
+ retval = 1;
+ else {
+ assert((int)(f1P->time_write - f2P->time_write) ==
+ (f1P->time_write - f2P->time_write));
+ retval = (int)(f1P->time_write - f2P->time_write);
+ }
+ return retval;
+}
+
+
+
+static void
+determineSortType(const char * const query,
+ bool * const ascendingP,
+ uint16_t * const sortP,
+ bool * const textP,
+ const char ** const errorP) {
+
+ *ascendingP = TRUE;
+ *sortP = 1;
+ *textP = FALSE;
+ *errorP = NULL;
+
+ if (query) {
+ if (xmlrpc_streq(query, "plain"))
+ *textP = TRUE;
+ else if (xmlrpc_streq(query, "name-up")) {
+ *sortP = 1;
+ *ascendingP = TRUE;
+ } else if (xmlrpc_streq(query, "name-down")) {
+ *sortP = 1;
+ *ascendingP = FALSE;
+ } else if (xmlrpc_streq(query, "date-up")) {
+ *sortP = 2;
+ *ascendingP = TRUE;
+ } else if (xmlrpc_streq(query, "date-down")) {
+ *sortP = 2;
+ *ascendingP = FALSE;
+ } else {
+ xmlrpc_asprintf(errorP, "invalid query value '%s'", query);
+ }
+ }
+}
+
+
+
+static void
+generateListing(TList * const listP,
+ const char * const dirName,
+ const char * const uri,
+ TPool * const poolP,
+ const char ** const errorP,
+ uint16_t * const responseStatusP) {
+
+ TFileInfo fileinfo;
+ TFileFind * findhandleP;
+
+ *errorP = NULL;
+
+ if (!FileFindFirst(&findhandleP, dirName, &fileinfo)) {
+ *responseStatusP = ResponseStatusFromErrno(errno);
+ xmlrpc_asprintf(errorP, "Can't read first entry in directory");
+ } else {
+ ListInit(listP);
+
+ do {
+ TFileInfo * fi;
+ /* Files whose names start with a dot are ignored */
+ /* This includes implicitly the ./ and ../ */
+ if (*fileinfo.name == '.') {
+ if (xmlrpc_streq(fileinfo.name, "..")) {
+ if (xmlrpc_streq(uri, "/"))
+ continue;
+ } else
+ continue;
+ }
+ fi = (TFileInfo *)PoolAlloc(poolP, sizeof(fileinfo));
+ if (fi) {
+ bool success;
+ memcpy(fi, &fileinfo, sizeof(fileinfo));
+ success = ListAdd(listP, fi);
+ if (!success)
+ xmlrpc_asprintf(errorP, "ListAdd() failed");
+ } else
+ xmlrpc_asprintf(errorP, "PoolAlloc() failed.");
+ } while (!*errorP && FileFindNext(findhandleP, &fileinfo));
+
+ if (*errorP) {
+ *responseStatusP = 500;
+ ListFree(listP);
+ }
+ FileFindClose(findhandleP);
+ }
+}
+
+
+
+static void
+sendDirectoryDocument(TList * const listP,
+ bool const ascending,
+ uint16_t const sort,
+ bool const text,
+ const char * const uri,
+ MIMEType * const mimeTypeP,
+ TSession * const sessionP) {
+
+ char z[4096];
+ char *p,z1[26],z2[20],z3[9],u;
+ const char * z4;
+ int16_t i;
+ uint32_t k;
+
+ if (text) {
+ sprintf(z, "Index of %s" CRLF, uri);
+ i = strlen(z)-2;
+ p = z + i + 2;
+
+ while (i > 0) {
+ *(p++) = '-';
+ --i;
+ }
+
+ *p = '\0';
+ strcat(z, CRLF CRLF
+ "Name Size "
+ "Date-Time Type" CRLF
+ "------------------------------------"
+ "--------------------------------------------"CRLF);
+ } else {
+ sprintf(z, "<HTML><HEAD><TITLE>Index of %s</TITLE></HEAD><BODY>"
+ "<H1>Index of %s</H1><PRE>",
+ uri, uri);
+ strcat(z, "Name Size "
+ "Date-Time Type<HR WIDTH=100%>"CRLF);
+ }
+
+ HTTPWriteBodyChunk(sessionP, z, strlen(z));
+
+ /* Sort the files */
+ qsort(listP->item, listP->size, sizeof(void *),
+ (TQSortProc)(sort == 1 ? cmpfilenames : cmpfiledates));
+
+ /* Write the listing */
+ if (ascending)
+ i = 0;
+ else
+ i = listP->size - 1;
+
+ while ((i < listP->size) && (i >= 0)) {
+ TFileInfo * fi;
+ struct tm ftm;
+
+ fi = listP->item[i];
+
+ if (ascending)
+ ++i;
+ else
+ --i;
+
+ strcpy(z, fi->name);
+
+ k = strlen(z);
+
+ if (fi->attrib & A_SUBDIR) {
+ z[k++] = '/';
+ z[k] = '\0';
+ }
+
+ if (k > 24) {
+ z[10] = '\0';
+ strcpy(z1, z);
+ strcat(z1, "...");
+ strcat(z1, z + k - 11);
+ k = 24;
+ p = z1 + 24;
+ } else {
+ strcpy(z1, z);
+
+ ++k;
+ p = z1 + k;
+ while (k < 25)
+ z1[k++] = ' ';
+
+ z1[25] = '\0';
+ }
+
+ xmlrpc_gmtime(fi->time_write, &ftm);
+ sprintf(z2, "%02u/%02u/%04u %02u:%02u:%02u",ftm.tm_mday,ftm.tm_mon+1,
+ ftm.tm_year+1900,ftm.tm_hour,ftm.tm_min,ftm.tm_sec);
+
+ if (fi->attrib & A_SUBDIR) {
+ strcpy(z3, " -- ");
+ z4 = "Directory";
+ } else {
+ if (fi->size < 9999)
+ u = 'b';
+ else {
+ fi->size /= 1024;
+ if (fi->size < 9999)
+ u = 'K';
+ else {
+ fi->size /= 1024;
+ if (fi->size < 9999)
+ u = 'M';
+ else
+ u = 'G';
+ }
+ }
+
+ sprintf(z3, "%5" PRIu64 " %c", fi->size, u);
+
+ if (xmlrpc_streq(fi->name, ".."))
+ z4 = "";
+ else
+ z4 = MIMETypeFromFileName2(mimeTypeP, fi->name);
+
+ if (!z4)
+ z4 = "Unknown";
+ }
+
+ if (text)
+ sprintf(z, "%s%s %s %s %s"CRLF, z1, p, z3, z2, z4);
+ else
+ sprintf(z, "<A HREF=\"%s%s\">%s</A>%s %s %s %s"CRLF,
+ fi->name, fi->attrib & A_SUBDIR ? "/" : "",
+ z1, p, z3, z2, z4);
+
+ HTTPWriteBodyChunk(sessionP, z, strlen(z));
+ }
+
+ /* Write the tail of the file */
+ if (text)
+ strcpy(z, SERVER_PLAIN_INFO);
+ else
+ strcpy(z, "</PRE>" SERVER_HTML_INFO "</BODY></HTML>" CRLF CRLF);
+
+ HTTPWriteBodyChunk(sessionP, z, strlen(z));
+}
+
+
+
+static bool
+notRecentlyModified(TSession * const sessionP,
+ time_t const fileModTime) {
+
+ bool retval;
+ const char * imsHdr;
+
+ imsHdr = RequestHeaderValue(sessionP, "if-modified-since");
+ if (imsHdr) {
+ bool valid;
+ time_t datetime;
+ DateDecode(imsHdr, &valid, &datetime);
+ if (valid) {
+ if (MIN(fileModTime, sessionP->date) <= datetime)
+ retval = TRUE;
+ else
+ retval = FALSE;
+ } else
+ retval = FALSE;
+ } else
+ retval = FALSE;
+
+ return retval;
+}
+
+
+
+static void
+addLastModifiedHeader(TSession * const sessionP,
+ time_t const fileModTime) {
+
+ const char * lastModifiedValue;
+
+ DateToString(MIN(fileModTime, sessionP->date), &lastModifiedValue);
+
+ if (lastModifiedValue) {
+ ResponseAddField(sessionP, "Last-Modified", lastModifiedValue);
+ xmlrpc_strfree(lastModifiedValue);
+ }
+}
+
+
+
+static void
+handleDirectory(TSession * const sessionP,
+ const char * const dirName,
+ time_t const fileModTime,
+ MIMEType * const mimeTypeP) {
+
+ bool text;
+ bool ascending;
+ uint16_t sort; /* 1=by name, 2=by date */
+ const char * error;
+
+ determineSortType(sessionP->requestInfo.query,
+ &ascending, &sort, &text, &error);
+
+ if (error) {
+ ResponseStatus(sessionP, 400);
+ xmlrpc_strfree(error);
+ } else if (notRecentlyModified(sessionP, fileModTime)) {
+ ResponseStatus(sessionP, 304);
+ ResponseWriteStart(sessionP);
+ } else {
+ TPool pool;
+ bool succeeded;
+ succeeded = PoolCreate(&pool, 1024);
+ if (!succeeded)
+ ResponseStatus(sessionP, 500);
+ else {
+ TList list;
+ uint16_t responseStatus;
+ const char * error;
+ generateListing(&list, dirName, sessionP->requestInfo.uri,
+ &pool, &error, &responseStatus);
+ if (error) {
+ ResponseStatus(sessionP, responseStatus);
+ xmlrpc_strfree(error);
+ } else {
+ ResponseStatus(sessionP, 200);
+ ResponseContentType(sessionP,
+ text ? "text/plain" : "text/html");
+
+ addLastModifiedHeader(sessionP, fileModTime);
+
+ ResponseChunked(sessionP);
+ ResponseWriteStart(sessionP);
+
+ if (sessionP->requestInfo.method!=m_head)
+ sendDirectoryDocument(&list, ascending, sort, text,
+ sessionP->requestInfo.uri, mimeTypeP,
+ sessionP);
+
+ HTTPWriteEndChunk(sessionP);
+
+ ListFree(&list);
+ }
+ PoolFree(&pool);
+ }
+ }
+}
+
+
+
+static void
+composeEntityHeader(const char ** const entityHeaderP,
+ const char * const mediatype,
+ uint64_t const start,
+ uint64_t const end,
+ uint64_t const filesize) {
+
+ xmlrpc_asprintf(entityHeaderP, "Content-type: %s" CRLF
+ "Content-range: "
+ "bytes %" PRIu64 "-%" PRIu64 "/%" PRIu64 CRLF
+ "Content-length: %" PRIu64 CRLF CRLF,
+ mediatype, start, end, filesize, end-start+1);
+}
+
+
+
+#define BOUNDARY "##123456789###BOUNDARY"
+
+static void
+sendBody(TSession * const sessionP,
+ const TFile * const fileP,
+ uint64_t const filesize,
+ const char * const mediatype,
+ uint64_t const start0,
+ uint64_t const end0) {
+/*----------------------------------------------------------------------------
+ 'start0' and 'end0' are meaningful only if the session has ranges.
+-----------------------------------------------------------------------------*/
+ char buffer[4096];
+
+ if (sessionP->ranges.size == 0)
+ ConnWriteFromFile(sessionP->conn, fileP, 0, filesize - 1,
+ buffer, sizeof(buffer), 0);
+ else if (sessionP->ranges.size == 1)
+ ConnWriteFromFile(sessionP->conn, fileP, start0, end0,
+ buffer, sizeof(buffer), 0);
+ else {
+ uint64_t i;
+ for (i = 0; i <= sessionP->ranges.size; ++i) {
+ ConnWrite(sessionP->conn, "--", 2);
+ ConnWrite(sessionP->conn, BOUNDARY, strlen(BOUNDARY));
+ ConnWrite(sessionP->conn, CRLF, 2);
+
+ if (i < sessionP->ranges.size) {
+ uint64_t start;
+ uint64_t end;
+ bool decoded;
+
+ decoded = RangeDecode((char *)(sessionP->ranges.item[i]),
+ filesize,
+ &start, &end);
+ if (decoded) {
+ /* Entity header, not response header */
+ const char * entityHeader;
+
+ composeEntityHeader(&entityHeader, mediatype,
+ start, end, filesize);
+
+ ConnWrite(sessionP->conn,
+ entityHeader, strlen(entityHeader));
+
+ xmlrpc_strfree(entityHeader);
+
+ ConnWriteFromFile(sessionP->conn, fileP, start, end,
+ buffer, sizeof(buffer), 0);
+ }
+ }
+ }
+ }
+}
+
+
+
+static void
+sendFileAsResponse(TSession * const sessionP,
+ TFile * const fileP,
+ const char * const fileName,
+ time_t const fileModTime,
+ MIMEType * const mimeTypeP) {
+
+ uint64_t const filesize = FileSize(fileP);
+ const char * const mediatype = MIMETypeGuessFromFile2(mimeTypeP, fileName);
+
+ uint64_t start; /* Defined only if session has one range */
+ uint64_t end; /* Defined only if session has one range */
+
+ switch (sessionP->ranges.size) {
+ case 0:
+ ResponseStatus(sessionP, 200);
+ break;
+
+ case 1: {
+ bool decoded;
+ decoded = RangeDecode((char *)(sessionP->ranges.item[0]), filesize,
+ &start, &end);
+ if (!decoded) {
+ ListFree(&sessionP->ranges);
+ ResponseStatus(sessionP, 200);
+ } else {
+ const char * contentRange;
+ xmlrpc_asprintf(&contentRange,
+ "bytes %" PRIu64 "-%" PRIu64 "/%" PRIu64,
+ start, end, filesize);
+ ResponseAddField(sessionP, "Content-range", contentRange);
+ xmlrpc_strfree(contentRange);
+
+ ResponseContentLength(sessionP, end - start + 1);
+ ResponseStatus(sessionP, 206);
+ }
+ } break;
+
+ default:
+ ResponseContentType(sessionP,
+ "multipart/ranges; boundary=" BOUNDARY);
+ ResponseStatus(sessionP, 206);
+ break;
+ }
+
+ if (sessionP->ranges.size == 0) {
+ ResponseContentLength(sessionP, filesize);
+ ResponseContentType(sessionP, mediatype);
+ }
+
+ addLastModifiedHeader(sessionP, fileModTime);
+
+ ResponseWriteStart(sessionP);
+
+ if (sessionP->requestInfo.method != m_head)
+ sendBody(sessionP, fileP, filesize, mediatype, start, end);
+}
+
+
+
+static void
+handleFile(TSession * const sessionP,
+ const char * const fileName,
+ time_t const fileModTime,
+ MIMEType * const mimeTypeP) {
+/*----------------------------------------------------------------------------
+ This is an HTTP request handler for a GET. It does the classic
+ web server thing: send the file named in the URL to the client.
+-----------------------------------------------------------------------------*/
+ TFile * fileP;
+ bool success;
+
+ success = FileOpen(&fileP, fileName, O_BINARY | O_RDONLY);
+ if (!success)
+ ResponseStatusErrno(sessionP);
+ else {
+ if (notRecentlyModified(sessionP, fileModTime)) {
+ ResponseStatus(sessionP, 304);
+ ResponseWriteStart(sessionP);
+ } else
+ sendFileAsResponse(sessionP, fileP,
+ fileName, fileModTime, mimeTypeP);
+
+ FileClose(fileP);
+ }
+}
+
+
+
+static void
+convertToNativeFileName(char * const fileName ATTR_UNUSED) {
+
+#ifdef WIN32
+ char * p;
+ p = &fileName[0];
+ while (*p) {
+ if ((*p) == '/')
+ *p= '\\';
+
+ ++p;
+ }
+#endif /* WIN32 */
+}
+
+
+
+abyss_bool
+HandlerDefaultBuiltin(TSession * const sessionP) {
+
+ BIHandler * const handlerP = SessionGetDefaultHandlerCtx(sessionP);
+
+ char * p;
+ char z[4096];
+ TFileStat fs;
+ bool endingslash;
+
+ endingslash = FALSE; /* initial value */
+
+ if (!RequestValidURIPath(sessionP)) {
+ ResponseStatus(sessionP, 400);
+ return TRUE;
+ }
+
+ /* Must check for * (asterisk uri) in the future */
+ if (sessionP->requestInfo.method == m_options) {
+ ResponseAddField(sessionP, "Allow", "GET, HEAD");
+ ResponseContentLength(sessionP, 0);
+ ResponseStatus(sessionP, 200);
+ return TRUE;
+ }
+
+ if ((sessionP->requestInfo.method != m_get) &&
+ (sessionP->requestInfo.method != m_head)) {
+ ResponseAddField(sessionP, "Allow", "GET, HEAD");
+ ResponseStatus(sessionP, 405);
+ return TRUE;
+ }
+
+ strcpy(z, handlerP->filesPath);
+ strcat(z, sessionP->requestInfo.uri);
+
+ p = z + strlen(z) - 1;
+ if (*p == '/') {
+ endingslash = TRUE;
+ *p = '\0';
+ }
+
+ convertToNativeFileName(z);
+
+ if (!FileStat(z, &fs)) {
+ ResponseStatusErrno(sessionP);
+ return TRUE;
+ }
+
+ if (fs.st_mode & S_IFDIR) {
+ /* Redirect to the same directory but with the ending slash
+ ** to avoid problems with some browsers (IE for examples) when
+ ** they generate relative urls */
+ if (!endingslash) {
+ strcpy(z, sessionP->requestInfo.uri);
+ p = z+strlen(z);
+ *p = '/';
+ *(p+1) = '\0';
+ ResponseAddField(sessionP, "Location", z);
+ ResponseStatus(sessionP, 302);
+ ResponseWriteStart(sessionP);
+ return TRUE;
+ }
+
+ *p = DIRECTORY_SEPARATOR[0];
+ ++p;
+ {
+ unsigned int i;
+ i = handlerP->defaultFileNames.size;
+ while (i-- > 0) {
+ *p = '\0';
+ strcat(z, (handlerP->defaultFileNames.item[i]));
+ if (FileStat(z, &fs)) {
+ if (!(fs.st_mode & S_IFDIR))
+ handleFile(sessionP, z, fs.st_mtime,
+ handlerP->mimeTypeP);
+ }
+ }
+ }
+
+ *(p-1) = '\0';
+
+ if (!FileStat(z, &fs)) {
+ ResponseStatusErrno(sessionP);
+ return TRUE;
+ }
+ handleDirectory(sessionP, z, fs.st_mtime, handlerP->mimeTypeP);
+ } else
+ handleFile(sessionP, z, fs.st_mtime, handlerP->mimeTypeP);
+
+ return TRUE;
+}
+
+
+
+/******************************************************************************
+**
+** server.c
+**
+** This file is part of the ABYSS Web server project.
+**
+** Copyright (C) 2000 by Moez Mahfoudh <mmoez at bigfoot.com>.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR 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.
+**
+******************************************************************************/
Added: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/handler.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/handler.h Fri May 23 16:56:24 2008
@@ -0,0 +1,31 @@
+#ifndef HANDLER_H_INCLUDED
+#define HANDLER_H_INCLUDED
+
+#include "bool.h"
+#include "xmlrpc-c/abyss.h"
+
+typedef struct BIHandler BIHandler;
+
+BIHandler *
+HandlerCreate(void);
+
+void
+HandlerDestroy(BIHandler * const handlerP);
+
+
+void
+HandlerSetMimeType(BIHandler * const handlerP,
+ MIMEType * const mimeTypeP);
+
+void
+HandlerSetFilesPath(BIHandler * const handlerP,
+ const char * const filesPath);
+
+void
+HandlerAddDefaultFN(BIHandler * const handlerP,
+ const char * const fileName);
+
+abyss_bool
+HandlerDefaultBuiltin(TSession * const sessionP);
+
+#endif
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/http.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/http.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/http.c Fri May 23 16:56:24 2008
@@ -1,38 +1,7 @@
-/*******************************************************************************
-**
-** http.c
-**
-** This file is part of the ABYSS Web server project.
-**
-** Copyright (C) 2000 by Moez Mahfoudh <mmoez at bigfoot.com>.
-** All rights reserved.
-**
-** Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions
-** are met:
-** 1. Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** 2. Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in the
-** documentation and/or other materials provided with the distribution.
-** 3. The name of the author may not be used to endorse or promote products
-** derived from this software without specific prior written permission.
-**
-** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR 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.
-**
-*******************************************************************************/
+/* Copyright information is at the end of the file */
#include <ctype.h>
+#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -40,8 +9,20 @@
#include <time.h>
#include "xmlrpc_config.h"
+#include "bool.h"
+#include "mallocvar.h"
+#include "xmlrpc-c/util.h"
+#include "xmlrpc-c/string_int.h"
#include "xmlrpc-c/abyss.h"
+
+#include "server.h"
+#include "session.h"
+#include "conn.h"
#include "token.h"
+#include "date.h"
+#include "data.h"
+
+#include "http.h"
/*********************************************************************
** Request Parser
@@ -51,446 +32,1057 @@
** Request
*********************************************************************/
-void RequestInit(TSession *r,TConn *c)
-{
- time_t t;
-
- time(&t);
- r->date=*gmtime(&t);
-
- r->keepalive=r->cankeepalive=FALSE;
- r->query=NULL;
- r->host=NULL;
- r->from=NULL;
- r->useragent=NULL;
- r->referer=NULL;
- r->user=NULL;
- r->port=80;
- r->versionmajor=0;
- r->versionminor=9;
- r->server=c->server;
- r->conn=c;
-
- r->done=FALSE;
-
- r->chunkedwrite=r->chunkedwritemode=FALSE;
-
- r->requestline=NULL;
-
- ListInit(&r->cookies);
- ListInit(&r->ranges);
- TableInit(&r->request_headers);
- TableInit(&r->response_headers);
-
- r->status=0;
-
- StringAlloc(&(r->header));
-}
-
-void RequestFree(TSession *r)
-{
- if (r->requestline)
- free(r->requestline);
-
- if (r->user)
- free(r->user);
-
- ListFree(&r->cookies);
- ListFree(&r->ranges);
- TableFree(&r->request_headers);
- TableFree(&r->response_headers);
- StringFree(&(r->header));
+static void
+initRequestInfo(TRequestInfo * const requestInfoP,
+ httpVersion const httpVersion,
+ const char * const requestLine,
+ TMethod const httpMethod,
+ const char * const host,
+ unsigned int const port,
+ const char * const path,
+ const char * const query) {
+/*----------------------------------------------------------------------------
+ Set up the request info structure. For information that is
+ controlled by headers, use the defaults -- I.e. the value that
+ applies if the request contains no applicable header.
+-----------------------------------------------------------------------------*/
+ XMLRPC_ASSERT_PTR_OK(requestLine);
+ XMLRPC_ASSERT_PTR_OK(path);
+
+ requestInfoP->requestline = strdup(requestLine);
+ requestInfoP->method = httpMethod;
+ requestInfoP->host = xmlrpc_strdupnull(host);
+ requestInfoP->port = port;
+ requestInfoP->uri = strdup(path);
+ requestInfoP->query = xmlrpc_strdupnull(query);
+ requestInfoP->from = NULL;
+ requestInfoP->useragent = NULL;
+ requestInfoP->referer = NULL;
+ requestInfoP->user = NULL;
+
+ if (httpVersion.major > 1 ||
+ (httpVersion.major == 1 && httpVersion.minor >= 1))
+ requestInfoP->keepalive = TRUE;
+ else
+ requestInfoP->keepalive = FALSE;
}
static void
-readFirstLineOfRequest(TSession * const r,
- char ** const lineP,
- abyss_bool * const errorP) {
+freeRequestInfo(TRequestInfo * const requestInfoP) {
- *errorP = FALSE;
+ xmlrpc_strfreenull(requestInfoP->host);
- /* Ignore CRLFs in the beginning of the request (RFC2068-P30) */
- do {
- abyss_bool success;
- success = ConnReadLine(r->conn, lineP, r->server->timeout);
- if (!success) {
- /* Request Timeout */
- ResponseStatus(r, 408);
- *errorP = TRUE;
- }
- } while ((*lineP)[0] == '\0' && !*errorP);
+ xmlrpc_strfreenull(requestInfoP->user);
+
+ xmlrpc_strfree(requestInfoP->uri);
+
+ xmlrpc_strfree(requestInfoP->requestline);
}
-static void
-processFirstLineOfRequest(TSession * const r,
- char * const line1,
- abyss_bool * const moreLinesP,
- abyss_bool * const errorP) {
-
+void
+RequestInit(TSession * const sessionP,
+ TConn * const connectionP) {
+
+ sessionP->validRequest = false; /* Don't have valid request yet */
+
+ time(&sessionP->date);
+
+ sessionP->conn = connectionP;
+
+ sessionP->responseStarted = FALSE;
+
+ sessionP->chunkedwrite = FALSE;
+ sessionP->chunkedwritemode = FALSE;
+
+ sessionP->continueRequired = FALSE;
+
+ ListInit(&sessionP->cookies);
+ ListInit(&sessionP->ranges);
+ TableInit(&sessionP->request_headers);
+ TableInit(&sessionP->response_headers);
+
+ sessionP->status = 0; /* No status from handler yet */
+
+ StringAlloc(&(sessionP->header));
+}
+
+
+
+void
+RequestFree(TSession * const sessionP) {
+
+ if (sessionP->validRequest)
+ freeRequestInfo(&sessionP->requestInfo);
+
+ ListFree(&sessionP->cookies);
+ ListFree(&sessionP->ranges);
+ TableFree(&sessionP->request_headers);
+ TableFree(&sessionP->response_headers);
+ StringFree(&(sessionP->header));
+}
+
+
+
+static char *
+firstLfPos(TConn * const connectionP,
+ char * const lineStart) {
+/*----------------------------------------------------------------------------
+ Return a pointer in the connection's receive buffer to the first
+ LF (linefeed aka newline) character in the buffer at or after 'lineStart'.
+
+ If there is no LF in the buffer at or after 'lineStart', return NULL.
+-----------------------------------------------------------------------------*/
+ const char * const bufferEnd =
+ connectionP->buffer + connectionP->buffersize;
+
char * p;
- char * t;
- p = line1;
+ for (p = lineStart; p < bufferEnd && *p != LF; ++p);
- /* Jump over spaces */
- NextToken(&p);
+ if (p < bufferEnd)
+ return p;
+ else
+ return NULL;
+}
- r->requestline = strdup(p);
-
- t = GetToken(&p);
- if (!t) {
- /* Bad request */
- ResponseStatus(r,400);
- *errorP = TRUE;
- } else {
- if (strcmp(t, "GET") == 0)
- r->method = m_get;
- else if (strcmp(p, "PUT") == 0)
- r->method = m_put;
- else if (strcmp(t, "OPTIONS") == 0)
- r->method = m_options;
- else if (strcmp(p, "DELETE") == 0)
- r->method = m_delete;
- else if (strcmp(t, "POST") == 0)
- r->method = m_post;
- else if (strcmp(p, "TRACE") == 0)
- r->method = m_trace;
- else if (strcmp(t, "HEAD") == 0)
- r->method = m_head;
- else
- r->method = m_unknown;
-
- /* URI and Query Decoding */
- NextToken(&p);
-
- t=GetToken(&p);
- if (!t)
- *errorP = TRUE;
+
+
+static void
+getLineInBuffer(TConn * const connectionP,
+ char * const lineStart,
+ time_t const deadline,
+ char ** const lineEndP,
+ bool * const errorP) {
+/*----------------------------------------------------------------------------
+ Get a line into the connection's read buffer, starting at position
+ 'lineStart', if there isn't one already there. 'lineStart' is either
+ within the buffer or just after it.
+
+ Read the channel until we get a full line, except fail if we don't get
+ one by 'deadline'.
+-----------------------------------------------------------------------------*/
+ bool error;
+ char * lfPos;
+
+ assert(lineStart <= connectionP->buffer + connectionP->buffersize);
+
+ error = FALSE; /* initial value */
+ lfPos = NULL; /* initial value */
+
+ while (!error && !lfPos) {
+ int const timeLeft = (int)(deadline - time(NULL));
+ assert(timeLeft == deadline - time(NULL));
+ if (timeLeft <= 0)
+ error = TRUE;
else {
- r->uri=t;
-
- RequestUnescapeURI(r);
-
- t=strchr(t,'?');
- if (t) {
- *t = '\0';
- r->query = t+1;
- }
-
- NextToken(&p);
-
- /* HTTP Version Decoding */
+ lfPos = firstLfPos(connectionP, lineStart);
+ if (!lfPos)
+ error = !ConnRead(connectionP, timeLeft);
+ }
+ }
+ *errorP = error;
+ *lineEndP = lfPos + 1;
+}
+
+
+
+static bool
+isContinuationLine(const char * const line) {
+
+ return (line[0] == ' ' || line[0] == '\t');
+}
+
+
+
+static bool
+isEmptyLine(const char * const line) {
+
+ return (line[0] == '\n' || (line[0] == '\r' && line[1] == '\n'));
+}
+
+
+
+static void
+convertLineEnd(char * const lineStart,
+ char * const prevLineStart,
+ char const newVal) {
+/*----------------------------------------------------------------------------
+ Assuming a line begins at 'lineStart' and the line before it (the
+ "previous line") begins at 'prevLineStart', replace the line
+ delimiter at the end of the previous line with the character 'newVal'.
+
+ The line delimiter is either CRLF or LF. In the CRLF case, we replace
+ both CR and LF with 'newVal'.
+-----------------------------------------------------------------------------*/
+ assert(lineStart >= prevLineStart + 1);
+ *(lineStart-1) = newVal;
+ if (prevLineStart + 1 < lineStart &&
+ *(lineStart-2) == CR)
+ *(lineStart-2) = newVal;
+}
+
+
+
+static void
+getRestOfHeader(TConn * const connectionP,
+ char * const lineEnd,
+ time_t const deadline,
+ const char ** const headerEndP,
+ bool * const errorP) {
+/*----------------------------------------------------------------------------
+ Given that the read buffer for connection *connectionP contains (at
+ its current read position) the first line of an HTTP header, which
+ ends at position 'lineEnd', find the rest of it.
+
+ Some or all of the rest of the header may be in the buffer already;
+ we read more from the connection as necessary, but not if it takes past
+ 'deadline'. In the latter case, we fail.
+
+ We return the location of the end of the whole header as *headerEndP.
+ We do not remove the header from the buffer, but we do modify the
+ buffer so as to join the multiple lines of the header into a single
+ line, and to NUL-terminate the header.
+-----------------------------------------------------------------------------*/
+ char * const headerStart = connectionP->buffer + connectionP->bufferpos;
+
+ char * headerEnd;
+ /* End of the header lines we've seen at so far */
+ bool gotWholeHeader;
+ bool error;
+
+ headerEnd = lineEnd; /* initial value - end of 1st line */
- t = GetToken(&p);
- if (t) {
- uint32_t vmin, vmaj;
- if (sscanf(t, "HTTP/%d.%d", &vmaj, &vmin) != 2) {
- /* Bad request */
- ResponseStatus(r, 400);
- *errorP = TRUE;
- } else {
- r->versionmajor = vmaj;
- r->versionminor = vmin;
- *errorP = FALSE;
- }
- *moreLinesP = TRUE;
+ for (gotWholeHeader = FALSE, error = FALSE;
+ !gotWholeHeader && !error;) {
+
+ char * nextLineEnd;
+
+ /* Note that we are guaranteed, assuming the HTTP stream is
+ valid, that there is at least one more line in it. Worst
+ case, it's the empty line that marks the end of the headers.
+ */
+ getLineInBuffer(connectionP, headerEnd, deadline,
+ &nextLineEnd, &error);
+ if (!error) {
+ if (isContinuationLine(headerEnd)) {
+ /* Join previous line to this one */
+ convertLineEnd(headerEnd, headerStart, ' ');
+ /* Add this line to the header */
+ headerEnd = nextLineEnd;
} else {
- /* There is not HTTP version, so this is a single
- line request.
- */
- *errorP = FALSE;
- *moreLinesP = FALSE;
+ gotWholeHeader = TRUE;
+ *headerEndP = headerEnd;
+
+ /* NUL-terminate the whole header */
+ convertLineEnd(headerEnd, headerStart, '\0');
}
}
}
+ *errorP = error;
}
-abyss_bool
-RequestRead(TSession * const r) {
- char *n,*t,*p;
- abyss_bool ret;
- abyss_bool error;
- char * line1;
- abyss_bool moreLines;
+static void
+readHeader(TConn * const connectionP,
+ time_t const deadline,
+ bool * const endOfHeadersP,
+ char ** const headerP,
+ bool * const errorP) {
+/*----------------------------------------------------------------------------
+ Read an HTTP header, or the end of headers empty line, on connection
+ *connectionP.
+
+ An HTTP header is basically a line, except that if a line starts
+ with white space, it's a continuation of the previous line. A line
+ is delimited by either LF or CRLF.
+
+ The first line of an HTTP header is never empty; an empty line signals
+ the end of the HTTP headers and beginning of the HTTP body. We call
+ that empty line the EOH mark.
+
+ We assume the connection is positioned to a header or EOH mark.
+
+ In the course of reading, we read at least one character past the
+ line delimiter at the end of the header or EOH mark; we may read
+ much more. But we leave everything after the header or EOH (and
+ its line delimiter) in the internal buffer, with the buffer pointer
+ pointing to it.
+
+ We use stuff already in the internal buffer (perhaps left by a
+ previous call to this subroutine) before reading any more from from
+ the channel.
+
+ We return as *headerP the next header as an ASCIIZ string, with no
+ line delimiter. That string is stored in the "unused" portion of
+ the connection's internal buffer. Iff there is no next header, we
+ return *endOfHeadersP == true and nothing meaningful as *headerP.
+-----------------------------------------------------------------------------*/
+ char * const bufferStart = connectionP->buffer + connectionP->bufferpos;
+
+ bool error;
+ char * lineEnd;
+
+ getLineInBuffer(connectionP, bufferStart, deadline, &lineEnd, &error);
+
+ if (!error) {
+ if (isContinuationLine(bufferStart))
+ error = TRUE;
+ else if (isEmptyLine(bufferStart)) {
+ /* Consume the EOH mark from the buffer */
+ connectionP->bufferpos = lineEnd - connectionP->buffer;
+ *endOfHeadersP = TRUE;
+ } else {
+ /* We have the first line of a header; there may be more. */
+
+ const char * headerEnd;
+
+ *endOfHeadersP = FALSE;
+
+ getRestOfHeader(connectionP, lineEnd, deadline,
+ &headerEnd, &error);
+
+ if (!error) {
+ *headerP = bufferStart;
+
+ /* Consume the header from the buffer (but be careful --
+ you can't reuse that part of the buffer because the
+ string we will return is in it!
+ */
+ connectionP->bufferpos = headerEnd - connectionP->buffer;
+ }
+ }
+ }
+ *errorP = error;
+}
- readFirstLineOfRequest(r, &line1, &error);
- if (error)
- return FALSE;
+
+
+static void
+skipToNonemptyLine(TConn * const connectionP,
+ time_t const deadline,
+ bool * const errorP) {
+
+ char * const bufferStart = connectionP->buffer + connectionP->bufferpos;
+
+ bool gotNonEmptyLine;
+ bool error;
+ char * lineStart;
- processFirstLineOfRequest(r, line1, &moreLines, &error);
- if (error)
- return FALSE;
- if (!moreLines)
- return TRUE;
+ lineStart = bufferStart; /* initial value */
+ gotNonEmptyLine = FALSE; /* initial value */
+ error = FALSE; /* initial value */
+
+ while (!gotNonEmptyLine && !error) {
+ char * lineEnd;
+
+ getLineInBuffer(connectionP, lineStart, deadline, &lineEnd, &error);
+
+ if (!error) {
+ if (!isEmptyLine(lineStart))
+ gotNonEmptyLine = TRUE;
+ else
+ lineStart = lineEnd;
+ }
+ }
+ if (!error) {
+ /* Consume all the empty lines; advance buffer pointer to first
+ non-empty line.
+ */
+ connectionP->bufferpos = lineStart - connectionP->buffer;
+ }
+ *errorP = error;
+}
- /* Headers decoding */
- ret = TRUE;
- for (;;)
- {
- if (!ConnReadLine(r->conn,&p,r->server->timeout))
- {
- /* Request Timeout */
- ResponseStatus(r,408);
- return FALSE;
- };
-
- /* We have reached the empty line so all the request was read */
- if (!*p)
- return TRUE;
- NextToken(&p);
-
- if (!(n=GetToken(&p)))
- {
- /* Bad Request */
- ResponseStatus(r,400);
- return FALSE;
- };
+static void
+readRequestHeader(TSession * const sessionP,
+ time_t const deadline,
+ char ** const requestLineP,
+ uint16_t * const httpErrorCodeP) {
+/*----------------------------------------------------------------------------
+ Read the HTTP request header (aka request header field) from
+ session 'sessionP'. We read through the session's internal buffer;
+ i.e. we may get data that was previously read from the network, or
+ we may read more from the network.
+
+ We assume the connection is presently positioned to the beginning of
+ the HTTP document. We leave it positioned after the request header.
+
+ We ignore any empty lines at the beginning of the stream, per
+ RFC2616 Section 4.1.
+
+ Fail if we can't get the header before 'deadline'.
+
+ Return as *requestLineP the request header read. This ASCIIZ string is
+ in the session's internal buffer.
+
+ Return as *httpErrorCodeP the HTTP error code that describes how we
+ are not able to read the request header, or 0 if we can.
+ If we can't, *requestLineP is meaningless.
+-----------------------------------------------------------------------------*/
+ char * line;
+ bool error;
+ bool endOfHeaders;
- /* Valid Field name ? */
- if (n[strlen(n)-1]!=':')
- {
- /* Bad Request */
- ResponseStatus(r,400);
- return FALSE;
- };
+ skipToNonemptyLine(sessionP->conn, deadline, &error);
- n[strlen(n)-1]='\0';
+ if (!error)
+ readHeader(sessionP->conn, deadline, &endOfHeaders, &line, &error);
- NextToken(&p);
+ /* End of headers is delimited by an empty line, and we skipped all
+ the empty lines above, so we could not have encountered EOH:
+ */
+ assert(!endOfHeaders);
- t=n;
- while (*t)
- {
- *t=tolower(*t);
- t++;
- };
+ if (error)
+ *httpErrorCodeP = 408; /* Request Timeout */
+ else {
+ *httpErrorCodeP = 0;
+ *requestLineP = line;
+ }
+}
- t=p;
- TableAdd(&r->request_headers,n,t);
- if (strcmp(n,"connection")==0)
- {
- /* must handle the jigsaw TE,keepalive */
- if (strcasecmp(t,"keep-alive")==0)
- r->keepalive=TRUE;
+static void
+unescapeUri(char * const uri,
+ bool * const errorP) {
+
+ char * x;
+ char * y;
+
+ x = y = uri;
+
+ *errorP = FALSE;
+
+ while (*x && !*errorP) {
+ switch (*x) {
+ case '%': {
+ char c;
+ ++x;
+ c = tolower(*x++);
+ if ((c >= '0') && (c <= '9'))
+ c -= '0';
+ else if ((c >= 'a') && (c <= 'f'))
+ c -= 'a' - 10;
else
- r->keepalive=FALSE;
- }
- else if (strcmp(n,"host")==0)
- r->host=t;
- else if (strcmp(n,"from")==0)
- r->from=t;
- else if (strcmp(n,"user-agent")==0)
- r->useragent=t;
- else if (strcmp(n,"referer")==0)
- r->referer=t;
- else if (strcmp(n,"range")==0)
- {
- if (strncmp(t,"bytes=",6)==0)
- if (!ListAddFromString(&(r->ranges),t+6))
- {
- /* Bad Request */
- ResponseStatus(r,400);
- return FALSE;
- };
+ *errorP = TRUE;
+
+ if (!*errorP) {
+ char d;
+ d = tolower(*x++);
+ if ((d >= '0') && (d <= '9'))
+ d -= '0';
+ else if ((d >= 'a') && (d <= 'f'))
+ d -= 'a' - 10;
+ else
+ *errorP = TRUE;
+
+ if (!*errorP)
+ *y++ = ((c << 4) | d);
+ }
+ } break;
+
+ default:
+ *y++ = *x++;
+ break;
}
- else if (strcmp(n,"cookies")==0)
- {
- if (!ListAddFromString(&(r->cookies),t))
- {
- /* Bad Request */
- ResponseStatus(r,400);
- return FALSE;
- };
- };
- };
+ }
+ *y = '\0';
}
-char *RequestHeaderValue(TSession *r,char *name)
-{
- return (TableFind(&r->request_headers,name));
+
+
+static void
+parseHostPort(const char * const hostport,
+ const char ** const hostP,
+ unsigned short * const portP,
+ uint16_t * const httpErrorCodeP) {
+/*----------------------------------------------------------------------------
+ Parse a 'hostport', a string in the form www.acme.com:8080 .
+
+ Return the host name part (www.acme.com) as *hostP (in newly
+ malloced storage), and the port part (8080) as *portP.
+
+ Default the port to 80 if 'hostport' doesn't have the port part.
+-----------------------------------------------------------------------------*/
+ char * buffer;
+ char * colonPos;
+
+ buffer = strdup(hostport);
+
+ colonPos = strchr(buffer, ':');
+ if (colonPos) {
+ const char * p;
+ uint32_t port;
+
+ *colonPos = '\0'; /* Split hostport at the colon */
+
+ for (p = colonPos + 1, port = 0;
+ isdigit(*p) && port < 65535;
+ (port = port * 10 + (*p - '0')), ++p);
+
+ if (*p || port == 0)
+ *httpErrorCodeP = 400; /* Bad Request */
+ else {
+ *hostP = strdup(buffer);
+ *portP = port;
+ *httpErrorCodeP = 0;
+ }
+ } else {
+ *hostP = strdup(buffer);
+ *portP = 80;
+ *httpErrorCodeP = 0;
+ }
+ free(buffer);
}
-abyss_bool RequestUnescapeURI(TSession *r)
-{
- char *x,*y,c,d;
- x=y=r->uri;
- while (1)
- switch (*x)
+static void
+parseRequestUri(char * const requestUri,
+ const char ** const hostP,
+ unsigned short * const portP,
+ const char ** const pathP,
+ const char ** const queryP,
+ uint16_t * const httpErrorCodeP) {
+/*----------------------------------------------------------------------------
+ Parse the request URI (in the request line
+ "GET http://www.myserver.com:8080/myfile.cgi?parm HTTP/1.1",
+ "http://www.myserver.com:8080/myfile.cgi?parm" is the request URI).
+
+ Return as *hostP the "www.myserver.com" in the above example. If
+ that part of the URI doesn't exist, return *hostP == NULL.
+
+ Return as *portP the 8080 in the above example. If it doesn't exist,
+ return 80.
+
+ Return as *pathP the "/myfile.cgi" in the above example. If it
+ doesn't exist, return "*".
+
+ Return as *queryP the "parm" in the above example. If it doesn't
+ exist, return *queryP == NULL.
+
+ Return strings in newly malloc'ed storage.
+
+ Return as *httpErrorCodeP the HTTP error code that describes how the
+ URI is invalid, or 0 if it is valid. If it's invalid, other return
+ values are meaningless.
+
+ This destroys 'requestUri'. We should fix that.
+-----------------------------------------------------------------------------*/
+ bool error;
+
+ unescapeUri(requestUri, &error);
+
+ if (error)
+ *httpErrorCodeP = 400; /* Bad Request */
+ else {
+ char * requestUriNoQuery;
+ /* The request URI with any query (the stuff marked by a question
+ mark at the end of a request URI) chopped off.
+ */
{
- case '\0':
- *y='\0';
- return TRUE;
-
- case '%':
- x++;
- c=tolower(*x++);
- if ((c>='0') && (c<='9'))
- c-='0';
- else if ((c>='a') && (c<='f'))
- c-='a'-10;
- else
- return FALSE;
+ /* Split requestUri at the question mark */
+ char * const qmark = strchr(requestUri, '?');
+
+ if (qmark) {
+ *qmark = '\0';
+ *queryP = strdup(qmark + 1);
+ } else
+ *queryP = NULL;
- d=tolower(*x++);
- if ((d>='0') && (d<='9'))
- d-='0';
- else if ((d>='a') && (d<='f'))
- d-='a'-10;
- else
- return FALSE;
+ requestUriNoQuery = requestUri;
+ }
- *y++=((c << 4) | d);
- break;
+ if (requestUriNoQuery[0] == '/') {
+ *hostP = NULL;
+ *pathP = strdup(requestUriNoQuery);
+ *portP = 80;
+ *httpErrorCodeP = 0;
+ } else {
+ if (!xmlrpc_strneq(requestUriNoQuery, "http://", 7))
+ *httpErrorCodeP = 400; /* Bad Request */
+ else {
+ char * const hostportpath = &requestUriNoQuery[7];
+ char * const slashPos = strchr(hostportpath, '/');
+
+ const char * host;
+ const char * path;
+ unsigned short port;
+
+ char * hostport;
+
+ if (slashPos) {
+ char * p;
+ path = strdup(slashPos);
+
+ /* Nul-terminate the host name. To make space for
+ it, slide the whole name back one character.
+ This moves it into the space now occupied by
+ the end of "http://", which we don't need.
+ */
+ for (p = hostportpath; *p != '/'; ++p)
+ *(p-1) = *p;
+ *(p-1) = '\0';
+
+ hostport = hostportpath - 1;
+ *httpErrorCodeP = 0;
+ } else {
+ path = strdup("*");
+ hostport = hostportpath;
+ *httpErrorCodeP = 0;
+ }
+ if (!*httpErrorCodeP)
+ parseHostPort(hostport, &host, &port, httpErrorCodeP);
+ if (*httpErrorCodeP)
+ xmlrpc_strfree(path);
+
+ *hostP = host;
+ *portP = port;
+ *pathP = path;
+ }
+ }
+ }
+}
- default:
- *y++=*x++;
- break;
- };
-};
+static void
+parseRequestLine(char * const requestLine,
+ TMethod * const httpMethodP,
+ httpVersion * const httpVersionP,
+ const char ** const hostP,
+ unsigned short * const portP,
+ const char ** const pathP,
+ const char ** const queryP,
+ bool * const moreLinesP,
+ uint16_t * const httpErrorCodeP) {
+/*----------------------------------------------------------------------------
+ Modifies *requestLine!
+-----------------------------------------------------------------------------*/
+ const char * httpMethodName;
+ char * p;
-abyss_bool
-RequestValidURI(TSession *r) {
+ p = requestLine;
- char *p;
+ /* Jump over spaces */
+ NextToken((const char **)&p);
- if (!r->uri)
- return FALSE;
+ httpMethodName = GetToken(&p);
+ if (!httpMethodName)
+ *httpErrorCodeP = 400; /* Bad Request */
+ else {
+ char * requestUri;
+
+ if (xmlrpc_streq(httpMethodName, "GET"))
+ *httpMethodP = m_get;
+ else if (xmlrpc_streq(httpMethodName, "PUT"))
+ *httpMethodP = m_put;
+ else if (xmlrpc_streq(httpMethodName, "OPTIONS"))
+ *httpMethodP = m_options;
+ else if (xmlrpc_streq(httpMethodName, "DELETE"))
+ *httpMethodP = m_delete;
+ else if (xmlrpc_streq(httpMethodName, "POST"))
+ *httpMethodP = m_post;
+ else if (xmlrpc_streq(httpMethodName, "TRACE"))
+ *httpMethodP = m_trace;
+ else if (xmlrpc_streq(httpMethodName, "HEAD"))
+ *httpMethodP = m_head;
+ else
+ *httpMethodP = m_unknown;
+
+ /* URI and Query Decoding */
+ NextToken((const char **)&p);
- if (*(r->uri)!='/') {
- if (strncmp(r->uri,"http://",7)!=0)
- return FALSE;
+ requestUri = GetToken(&p);
+ if (!requestUri)
+ *httpErrorCodeP = 400; /* Bad Request */
else {
- r->uri+=7;
- r->host=r->uri;
- p=strchr(r->uri,'/');
-
- if (!p) {
- r->uri="*";
- return TRUE;
- };
-
- r->uri=p;
- p=r->host;
-
- while (*p!='/') {
- *(p-1)=*p;
- p++;
- };
+ const char * host;
+ unsigned short port;
+ const char * path;
+ const char * query;
+
+ parseRequestUri(requestUri, &host, &port, &path, &query,
+ httpErrorCodeP);
- --p;
- *p='\0';
+ if (!*httpErrorCodeP) {
+ const char * httpVersion;
- --r->host;
- };
+ NextToken((const char **)&p);
+
+ /* HTTP Version Decoding */
+
+ httpVersion = GetToken(&p);
+ if (httpVersion) {
+ uint32_t vmin, vmaj;
+ if (sscanf(httpVersion, "HTTP/%d.%d", &vmaj, &vmin) != 2)
+ *httpErrorCodeP = 400; /* Bad Request */
+ else {
+ httpVersionP->major = vmaj;
+ httpVersionP->minor = vmin;
+ *httpErrorCodeP = 0; /* no error */
+ }
+ *moreLinesP = TRUE;
+ } else {
+ /* There is no HTTP version, so this is a single
+ line request.
+ */
+ *httpErrorCodeP = 0; /* no error */
+ *moreLinesP = FALSE;
+ }
+ if (*httpErrorCodeP) {
+ xmlrpc_strfree(host);
+ xmlrpc_strfree(path);
+ xmlrpc_strfree(query);
+ }
+ *hostP = host;
+ *portP = port;
+ *pathP = path;
+ *queryP = query;
+ }
+ }
+ }
+}
+
+
+
+static void
+strtolower(char * const s) {
+
+ char * t;
+
+ t = &s[0];
+ while (*t) {
+ *t = tolower(*t);
+ ++t;
}
+}
+
- /* Host and Port Decoding */
- if (r->host) {
- p=strchr(r->host,':');
- if (p) {
- uint32_t port=0;
-
- *p='\0';
- p++;
- while (isdigit(*p) && (port<65535)) {
- port=port*10+(*p)-'0';
- ++p;
- };
+
+static void
+getFieldNameToken(char ** const pP,
+ char ** const fieldNameP,
+ uint16_t * const httpErrorCodeP) {
+/*----------------------------------------------------------------------------
+ Assuming that *pP points to the place in an HTTP header where the field
+ name belongs, return the field name and advance *pP past that token.
+
+ The field name is the lower case representation of the value of the
+ field name token.
+-----------------------------------------------------------------------------*/
+ char * fieldName;
+
+ NextToken((const char **)pP);
+
+ fieldName = GetToken(pP);
+ if (!fieldName)
+ *httpErrorCodeP = 400; /* Bad Request */
+ else {
+ if (fieldName[strlen(fieldName)-1] != ':')
+ /* Not a valid field name */
+ *httpErrorCodeP = 400; /* Bad Request */
+ else {
+ fieldName[strlen(fieldName)-1] = '\0'; /* remove trailing colon */
+
+ strtolower(fieldName);
- r->port=port;
+ *httpErrorCodeP = 0; /* no error */
+ *fieldNameP = fieldName;
+ }
+ }
+}
+
+
+
+static void
+processHeader(const char * const fieldName,
+ char * const fieldValue,
+ TSession * const sessionP,
+ uint16_t * const httpErrorCodeP) {
+/*----------------------------------------------------------------------------
+ We may modify *fieldValue, and we put pointers to *fieldValue and
+ *fieldName into *sessionP.
+
+ We must fix this some day. *sessionP should point to individual
+ malloc'ed strings.
+-----------------------------------------------------------------------------*/
+ *httpErrorCodeP = 0; /* initial assumption */
+
+ if (xmlrpc_streq(fieldName, "connection")) {
+ if (xmlrpc_strcaseeq(fieldValue, "keep-alive"))
+ sessionP->requestInfo.keepalive = TRUE;
+ else
+ sessionP->requestInfo.keepalive = FALSE;
+ } else if (xmlrpc_streq(fieldName, "host")) {
+ if (sessionP->requestInfo.host) {
+ xmlrpc_strfree(sessionP->requestInfo.host);
+ sessionP->requestInfo.host = NULL;
+ }
+ parseHostPort(fieldValue, &sessionP->requestInfo.host,
+ &sessionP->requestInfo.port, httpErrorCodeP);
+ } else if (xmlrpc_streq(fieldName, "from"))
+ sessionP->requestInfo.from = fieldValue;
+ else if (xmlrpc_streq(fieldName, "user-agent"))
+ sessionP->requestInfo.useragent = fieldValue;
+ else if (xmlrpc_streq(fieldName, "referer"))
+ sessionP->requestInfo.referer = fieldValue;
+ else if (xmlrpc_streq(fieldName, "range")) {
+ if (xmlrpc_strneq(fieldValue, "bytes=", 6)) {
+ bool succeeded;
+ succeeded = ListAddFromString(&sessionP->ranges, &fieldValue[6]);
+ *httpErrorCodeP = succeeded ? 0 : 400;
+ }
+ } else if (xmlrpc_streq(fieldName, "cookies")) {
+ bool succeeded;
+ succeeded = ListAddFromString(&sessionP->cookies, fieldValue);
+ *httpErrorCodeP = succeeded ? 0 : 400;
+ } else if (xmlrpc_streq(fieldName, "expect")) {
+ if (xmlrpc_strcaseeq(fieldValue, "100-continue"))
+ sessionP->continueRequired = TRUE;
+ }
+}
+
- if (*p || port==0)
- return FALSE;
- };
+
+static void
+readAndProcessHeaders(TSession * const sessionP,
+ time_t const deadline,
+ uint16_t * const httpErrorCodeP) {
+/*----------------------------------------------------------------------------
+ Read all the HTTP headers from the session *sessionP, which has at
+ least one header coming. Update *sessionP to reflect the
+ information in the headers.
+
+ If we find an error in the headers or while trying to read them, we
+ return an appropriate HTTP error code as *httpErrorCodeP. Otherwise,
+ we return *httpErrorCodeP = 0.
+-----------------------------------------------------------------------------*/
+ bool endOfHeaders;
+
+ assert(!sessionP->validRequest);
+ /* Calling us doesn't make sense if there is already a valid request */
+
+ *httpErrorCodeP = 0; /* initial assumption */
+ endOfHeaders = false; /* Caller assures us there is at least one header */
+
+ while (!endOfHeaders && !*httpErrorCodeP) {
+ char * header;
+ bool error;
+ readHeader(sessionP->conn, deadline, &endOfHeaders, &header, &error);
+ if (error)
+ *httpErrorCodeP = 408; /* Request Timeout */
+ else {
+ if (!endOfHeaders) {
+ char * p;
+ char * fieldName;
+
+ p = &header[0];
+ getFieldNameToken(&p, &fieldName, httpErrorCodeP);
+ if (!*httpErrorCodeP) {
+ char * fieldValue;
+
+ NextToken((const char **)&p);
+
+ fieldValue = p;
+
+ TableAdd(&sessionP->request_headers,
+ fieldName, fieldValue);
+
+ processHeader(fieldName, fieldValue, sessionP,
+ httpErrorCodeP);
+ }
+ }
+ }
}
- if (strcmp(r->uri,"*")==0)
- return (r->method!=m_options);
+}
+
+
+
+void
+RequestRead(TSession * const sessionP,
+ uint32_t const timeout) {
+/*----------------------------------------------------------------------------
+ Read the headers of a new HTTP request (assuming nothing has yet been
+ read on the session).
+
+ Update *sessionP with the information from the headers.
+
+ Leave the connection positioned to the body of the request, ready
+ to be read by an HTTP request handler (via SessionRefillBuffer() and
+ SessionGetReadData()).
+-----------------------------------------------------------------------------*/
+ time_t const deadline = time(NULL) + timeout;
+
+ uint16_t httpErrorCode; /* zero for no error */
+ char * requestLine; /* In connection;s internal buffer */
+
+ readRequestHeader(sessionP, deadline, &requestLine, &httpErrorCode);
+ if (!httpErrorCode) {
+ TMethod httpMethod;
+ const char * host;
+ const char * path;
+ const char * query;
+ unsigned short port;
+ bool moreHeaders;
+
+ parseRequestLine(requestLine, &httpMethod, &sessionP->version,
+ &host, &port, &path, &query,
+ &moreHeaders, &httpErrorCode);
+
+ if (!httpErrorCode) {
+ initRequestInfo(&sessionP->requestInfo, sessionP->version,
+ requestLine,
+ httpMethod, host, port, path, query);
+
+ if (moreHeaders)
+ readAndProcessHeaders(sessionP, deadline, &httpErrorCode);
+
+ if (httpErrorCode == 0)
+ sessionP->validRequest = true;
+
+ xmlrpc_strfreenull(host);
+ xmlrpc_strfree(path);
+ xmlrpc_strfreenull(query);
+ }
+ }
+ if (httpErrorCode)
+ ResponseStatus(sessionP, httpErrorCode);
+}
+
+
+
+char *
+RequestHeaderValue(TSession * const sessionP,
+ const char * const name) {
+
+ return (TableFind(&sessionP->request_headers, name));
+}
+
+
+
+bool
+RequestValidURI(TSession * const sessionP) {
+
+ if (!sessionP->requestInfo.uri)
+ return FALSE;
+
+ if (xmlrpc_streq(sessionP->requestInfo.uri, "*"))
+ return (sessionP->requestInfo.method != m_options);
- if (strchr(r->uri,'*'))
+ if (strchr(sessionP->requestInfo.uri, '*'))
return FALSE;
return TRUE;
}
-abyss_bool RequestValidURIPath(TSession *r)
-{
- uint32_t i=0;
- char *p=r->uri;
- if (*p=='/')
- {
- i=1;
+bool
+RequestValidURIPath(TSession * const sessionP) {
+
+ uint32_t i;
+ const char * p;
+
+ p = sessionP->requestInfo.uri;
+
+ i = 0;
+
+ if (*p == '/') {
+ i = 1;
while (*p)
- if (*(p++)=='/')
- {
- if (*p=='/')
+ if (*(p++) == '/') {
+ if (*p == '/')
break;
- else if ((strncmp(p,"./",2)==0) || (strcmp(p,".")==0))
- p++;
- else if ((strncmp(p,"../",2)==0) || (strcmp(p,"..")==0))
- {
- p+=2;
- i--;
- if (i==0)
+ else if ((strncmp(p,"./",2) == 0) || (strcmp(p, ".") == 0))
+ ++p;
+ else if ((strncmp(p, "../", 2) == 0) ||
+ (strcmp(p, "..") == 0)) {
+ p += 2;
+ --i;
+ if (i == 0)
break;
}
/* Prevent accessing hidden files (starting with .) */
- else if (*p=='.')
+ else if (*p == '.')
return FALSE;
else
if (*p)
- i++;
- };
- };
-
- return ((*p==0) && (i>0));
+ ++i;
+ }
+ }
+ return (*p == 0 && i > 0);
}
-abyss_bool
-RequestAuth(TSession *r,char *credential,char *user,char *pass) {
+bool
+RequestAuth(TSession * const sessionP,
+ const char * const credential,
+ const char * const user,
+ const char * const pass) {
+/*----------------------------------------------------------------------------
+ Authenticate requester, in a very simplistic fashion.
+
+ If the request specifies basic authentication (via Authorization
+ header) with username 'user', password 'pass', then return TRUE.
+ Else, return FALSE and set up an authorization failure response
+ (HTTP response status 401) that says user must supply an identity
+ in the 'credential' domain.
+
+ When we return TRUE, we also set the username in the request info
+ to 'user' so that a future SessionGetRequestInfo can get it.
+-----------------------------------------------------------------------------*/
+ bool authorized;
+ char * authHdrPtr;
+
+ authHdrPtr = RequestHeaderValue(sessionP, "authorization");
+ if (authHdrPtr) {
+ const char * authType;
+ NextToken((const char **)&authHdrPtr);
+ GetTokenConst(&authHdrPtr, &authType);
+ authType = GetToken(&authHdrPtr);
+ if (authType) {
+ if (xmlrpc_strcaseeq(authType, "basic")) {
+ const char * userPass;
+ char userPassEncoded[80];
+
+ NextToken((const char **)&authHdrPtr);
+
+ xmlrpc_asprintf(&userPass, "%s:%s", user, pass);
+ Base64Encode(userPass, userPassEncoded);
+ xmlrpc_strfree(userPass);
+
+ if (xmlrpc_streq(authHdrPtr, userPassEncoded)) {
+ sessionP->requestInfo.user = strdup(user);
+ authorized = TRUE;
+ } else
+ authorized = FALSE;
+ } else
+ authorized = FALSE;
+ } else
+ authorized = FALSE;
+ } else
+ authorized = FALSE;
+
+ if (!authorized) {
+ const char * hdrValue;
+ xmlrpc_asprintf(&hdrValue, "Basic realm=\"%s\"", credential);
+ ResponseAddField(sessionP, "WWW-Authenticate", hdrValue);
- char *p,*x;
- char z[80],t[80];
+ xmlrpc_strfree(hdrValue);
- p=RequestHeaderValue(r,"authorization");
- if (p) {
- NextToken(&p);
- x=GetToken(&p);
- if (x) {
- if (strcasecmp(x,"basic")==0) {
- NextToken(&p);
- sprintf(z,"%s:%s",user,pass);
- Base64Encode(z,t);
-
- if (strcmp(p,t)==0) {
- r->user=strdup(user);
- return TRUE;
- };
- };
- }
- };
-
- sprintf(z,"Basic realm=\"%s\"",credential);
- ResponseAddField(r,"WWW-Authenticate",z);
- ResponseStatus(r,401);
- return FALSE;
+ ResponseStatus(sessionP, 401);
+ }
+ return authorized;
}
@@ -499,10 +1091,17 @@
** Range
*********************************************************************/
-abyss_bool RangeDecode(char *str,uint64_t filesize,uint64_t *start,uint64_t *end)
-{
+abyss_bool
+RangeDecode(char * const strArg,
+ xmlrpc_uint64_t const filesize,
+ xmlrpc_uint64_t * const start,
+ xmlrpc_uint64_t * const end) {
+
+ char *str;
char *ss;
+ str = strArg; /* initial value */
+
*start=0;
*end=filesize-1;
@@ -534,13 +1133,15 @@
** HTTP
*********************************************************************/
-char *HTTPReasonByStatus(uint16_t code)
-{
- static struct _HTTPReasons {
+const char *
+HTTPReasonByStatus(uint16_t const code) {
+
+ struct _HTTPReasons {
uint16_t status;
- char *reason;
- } *r,reasons[] =
- {
+ const char * reason;
+ };
+
+ static struct _HTTPReasons const reasons[] = {
{ 100,"Continue" },
{ 101,"Switching Protocols" },
{ 200,"OK" },
@@ -580,14 +1181,15 @@
{ 505,"HTTP Version Not Supported" },
{ 000, NULL }
};
+ const struct _HTTPReasons * reasonP;
- r=reasons;
+ reasonP = &reasons[0];
- while (r->status<=code)
- if (r->status==code)
- return (r->reason);
+ while (reasonP->status <= code)
+ if (reasonP->status == code)
+ return reasonP->reason;
else
- r++;
+ ++reasonP;
return "No Reason";
}
@@ -595,494 +1197,111 @@
int32_t
-HTTPRead(TSession * const s ATTR_UNUSED,
- char * const buffer ATTR_UNUSED,
- uint32_t const len ATTR_UNUSED) {
+HTTPRead(TSession * const s ATTR_UNUSED,
+ const char * const buffer ATTR_UNUSED,
+ uint32_t const len ATTR_UNUSED) {
return 0;
}
-abyss_bool HTTPWrite(TSession *s,char *buffer,uint32_t len)
-{
- if (s->chunkedwrite && s->chunkedwritemode)
- {
- char t[16];
-
- if (ConnWrite(s->conn,t,sprintf(t,"%x"CRLF,len)))
- if (ConnWrite(s->conn,buffer,len))
- return ConnWrite(s->conn,CRLF,2);
-
- return FALSE;
- }
-
- return ConnWrite(s->conn,buffer,len);
-}
-
-abyss_bool HTTPWriteEnd(TSession *s)
-{
- if (!s->chunkedwritemode)
- return TRUE;
-
- if (s->chunkedwrite)
- {
- /* May be one day trailer dumping will be added */
- s->chunkedwritemode=FALSE;
- return ConnWrite(s->conn,"0"CRLF CRLF,5);
- }
-
- s->keepalive=FALSE;
- return TRUE;
-}
-
-/*********************************************************************
-** Response
-*********************************************************************/
-
-void ResponseError(TSession *r)
-{
- char *reason=HTTPReasonByStatus(r->status);
- char z[500];
-
- ResponseAddField(r,"Content-type","text/html");
-
- ResponseWrite(r);
-
- sprintf(z,"<HTML><HEAD><TITLE>Error %d</TITLE></HEAD>"
- "<BODY><H1>Error %d</H1><P>%s</P>" SERVER_HTML_INFO
- "</BODY></HTML>",
- r->status,r->status,reason);
-
- ConnWrite(r->conn,z,strlen(z));
-}
-
-abyss_bool ResponseChunked(TSession *r)
-{
- /* This is only a hope, things will be real only after a call of
- ResponseWrite
- */
- r->chunkedwrite=(r->versionmajor>=1) && (r->versionminor>=1);
- r->chunkedwritemode=TRUE;
-
- return TRUE;
-}
-
-void ResponseStatus(TSession *r,uint16_t code)
-{
- r->status=code;
-}
-
-void ResponseStatusErrno(TSession *r)
-{
- uint16_t code;
-
- switch (errno)
- {
- case EACCES:
- code=403;
- break;
- case ENOENT:
- code=404;
- break;
- default:
- code=500;
- };
-
- ResponseStatus(r,code);
-}
-
-abyss_bool ResponseAddField(TSession *r,char *name,char *value)
-{
- return TableAdd(&r->response_headers,name,value);
-}
-
-void ResponseWrite(TSession *r)
-{
- abyss_bool connclose=TRUE;
- char z[64];
- TTableItem *ti;
- uint16_t i;
- char *reason;
-
- /* if status == 0 then this is an error */
- if (r->status==0)
- r->status=500;
-
- /* the request was treated */
- r->done=TRUE;
-
- reason=HTTPReasonByStatus(r->status);
- sprintf(z,"HTTP/1.1 %d ",r->status);
- ConnWrite(r->conn,z,strlen(z));
- ConnWrite(r->conn,reason,strlen(reason));
- ConnWrite(r->conn,CRLF,2);
-
- /* generation of the connection field */
- if ((r->status<400) && (r->keepalive) && (r->cankeepalive))
- connclose=FALSE;
-
- ResponseAddField(r,"Connection",
- (connclose?"close":"Keep-Alive"));
-
- if (!connclose)
- {
- sprintf(z,"timeout=%u, max=%u",r->server->keepalivetimeout
- ,r->server->keepalivemaxconn);
-
- ResponseAddField(r,"Keep-Alive",z);
-
- if (r->chunkedwrite && r->chunkedwritemode)
- {
- if (!ResponseAddField(r,"Transfer-Encoding","chunked"))
- {
- r->chunkedwrite=FALSE;
- r->keepalive=FALSE;
- };
- };
- }
- else
- {
- r->keepalive=FALSE;
- r->chunkedwrite=FALSE;
- };
-
- /* generation of the date field */
- if ((r->status>=200) && DateToString(&r->date,z))
- ResponseAddField(r,"Date",z);
-
- /* Generation of the server field */
- if (r->server->advertise)
- ResponseAddField(r,"Server",SERVER_HVERSION);
-
- /* send all the fields */
- for (i=0;i<r->response_headers.size;i++)
- {
- ti=&r->response_headers.item[i];
- ConnWrite(r->conn,ti->name,strlen(ti->name));
- ConnWrite(r->conn,": ",2);
- ConnWrite(r->conn,ti->value,strlen(ti->value));
- ConnWrite(r->conn,CRLF,2);
- };
-
- ConnWrite(r->conn,CRLF,2);
-}
-
-abyss_bool ResponseContentType(TSession *r,char *type)
-{
- return ResponseAddField(r,"Content-type",type);
-}
-
-abyss_bool ResponseContentLength(TSession *r,uint64_t len)
-{
- char z[32];
-
- sprintf(z,"%llu",len);
- return ResponseAddField(r,"Content-length",z);
-}
-
-
-/*********************************************************************
-** MIMEType
-*********************************************************************/
-
-TList _MIMETypes,_MIMEExt;
-TPool _MIMEPool;
-
-void MIMETypeInit()
-{
- ListInit(&_MIMETypes);
- ListInit(&_MIMEExt);
- PoolCreate(&_MIMEPool,1024);
-}
-
-abyss_bool MIMETypeAdd(char *type,char *ext)
-{
- uint16_t index;
-
- if (ListFindString(&_MIMETypes,type,&index))
- type=_MIMETypes.item[index];
- else
- if (!(type=PoolStrdup(&_MIMEPool,type)))
- return FALSE;
-
- if (ListFindString(&_MIMEExt,ext,&index))
- _MIMETypes.item[index]=type;
- else {
- ext=PoolStrdup(&_MIMEPool,ext);
- if (ext)
- return (ListAdd(&_MIMETypes,type) && ListAdd(&_MIMEExt,ext));
- else
- return FALSE;
- }
- return TRUE;
-}
-
-char *MIMETypeFromExt(char *ext)
-{
- uint16_t extindex;
-
- if (!ListFindString(&_MIMEExt,ext,&extindex))
- return NULL;
- else
- return _MIMETypes.item[extindex];
-}
-
-char *MIMETypeFromFileName(char *filename)
-{
- char *p=filename+strlen(filename),*z=NULL;
-
- while ((*p!='.') && (p>=filename) && ((*p)!='/'))
- p--;
-
- if (*p=='.')
- z=MIMETypeFromExt(p+1);
-
- if (z)
- return z;
- else
- return "application/octet-stream";
-}
-
-char *MIMETypeGuessFromFile(char *filename)
-{
- char *p=filename+strlen(filename),*z=NULL;
- TFile file;
-
- while ((*p!='.') && (p>=filename) && ((*p)!='/'))
- p--;
-
- if (*p=='.')
- z=MIMETypeFromExt(p+1);
-
- if (z)
- return z;
-
- if (FileOpen(&file,filename,O_BINARY | O_RDONLY))
- {
- uint8_t buffer[80],c;
- int32_t len,i,n=0;
-
- i=len=FileRead(&file,buffer,80);
-
- while (i>0)
- {
- i--;
- c=buffer[i];
- if ((c>=' ') || (isspace(c)) || (c==26))
- n++;
- };
-
- if (n==len)
- z="text/plain";
-
- FileClose(&file);
- };
-
- if (z)
- return z;
- else
- return "application/octet-stream";
-}
-
-/*********************************************************************
-** Date
-*********************************************************************/
-
-static char *_DateDay[7]=
-{
- "Sun","Mon","Tue","Wed","Thu","Fri","Sat"
-};
-
-static char *_DateMonth[12]=
-{
- "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"
-};
-
-static int32_t _DateTimeBias=0;
-static char _DateTimeBiasStr[6]="";
-
-abyss_bool DateToString(TDate *tm,char *s)
-{
- if (mktime(tm)==(time_t)(-1))
- {
- *s='\0';
- return FALSE;
- };
-
- sprintf(s,"%s, %02d %s %04d %02d:%02d:%02d GMT",_DateDay[tm->tm_wday],tm->tm_mday,
- _DateMonth[tm->tm_mon],tm->tm_year+1900,tm->tm_hour,tm->tm_min,tm->tm_sec);
+bool
+HTTPWriteBodyChunk(TSession * const sessionP,
+ const char * const buffer,
+ uint32_t const len) {
+
+ bool succeeded;
+
+ if (sessionP->chunkedwrite && sessionP->chunkedwritemode) {
+ char chunkHeader[16];
+
+ sprintf(chunkHeader, "%x\r\n", len);
+
+ succeeded =
+ ConnWrite(sessionP->conn, chunkHeader, strlen(chunkHeader));
+ if (succeeded) {
+ succeeded = ConnWrite(sessionP->conn, buffer, len);
+ if (succeeded)
+ succeeded = ConnWrite(sessionP->conn, "\r\n", 2);
+ }
+ } else
+ succeeded = ConnWrite(sessionP->conn, buffer, len);
- return TRUE;
+ return succeeded;
}
-abyss_bool DateToLogString(TDate *tm,char *s)
-{
- time_t t;
- TDate d;
-
- if ((t=mktime(tm))!=(time_t)(-1))
- if (DateFromLocal(&d,t))
- {
- sprintf(s,"%02d/%s/%04d:%02d:%02d:%02d %s",d.tm_mday,_DateMonth[d.tm_mon],
- d.tm_year+1900,d.tm_hour,d.tm_min,d.tm_sec,_DateTimeBiasStr);
-
- return TRUE;
- };
- *s='\0';
- return FALSE;
-}
-abyss_bool DateDecode(char *s,TDate *tm)
-{
- uint32_t n=0;
-
- /* Ignore spaces, day name and spaces */
- while ((*s==' ') || (*s=='\t'))
- s++;
-
- while ((*s!=' ') && (*s!='\t'))
- s++;
-
- while ((*s==' ') || (*s=='\t'))
- s++;
-
- /* try to recognize the date format */
- if (sscanf(s,"%*s %d %d:%d:%d %d%*s",&tm->tm_mday,&tm->tm_hour,&tm->tm_min,
- &tm->tm_sec,&tm->tm_year)!=5)
- if (sscanf(s,"%d %n%*s %d %d:%d:%d GMT%*s",&tm->tm_mday,&n,&tm->tm_year,
- &tm->tm_hour,&tm->tm_min,&tm->tm_sec)!=5)
- if (sscanf(s,"%d-%n%*[A-Za-z]-%d %d:%d:%d GMT%*s",&tm->tm_mday,&n,&tm->tm_year,
- &tm->tm_hour,&tm->tm_min,&tm->tm_sec)!=5)
- return FALSE;
-
- /* s points now to the month string */
- s+=n;
- for (n=0;n<12;n++)
- {
- char *p=_DateMonth[n];
+bool
+HTTPWriteEndChunk(TSession * const sessionP) {
- if (tolower(*p++)==tolower(*s))
- if (*p++==tolower(s[1]))
- if (*p==tolower(s[2]))
- break;
- };
+ bool retval;
- if (n==12)
- return FALSE;
-
- tm->tm_mon=n;
-
- /* finish the work */
- if (tm->tm_year>1900)
- tm->tm_year-=1900;
- else
- if (tm->tm_year<70)
- tm->tm_year+=100;
-
- tm->tm_isdst=0;
+ if (sessionP->chunkedwritemode && sessionP->chunkedwrite) {
+ /* May be one day trailer dumping will be added */
+ sessionP->chunkedwritemode = FALSE;
+ retval = ConnWrite(sessionP->conn, "0\r\n\r\n", 5);
+ } else
+ retval = TRUE;
- return (mktime(tm)!=(time_t)(-1));
+ return retval;
}
-int32_t DateCompare(TDate *d1,TDate *d2)
-{
- int32_t x;
- if ((x=d1->tm_year-d2->tm_year)==0)
- if ((x=d1->tm_mon-d2->tm_mon)==0)
- if ((x=d1->tm_mday-d2->tm_mday)==0)
- if ((x=d1->tm_hour-d2->tm_hour)==0)
- if ((x=d1->tm_min-d2->tm_min)==0)
- x=d1->tm_sec-d2->tm_sec;
- return x;
+bool
+HTTPKeepalive(TSession * const sessionP) {
+/*----------------------------------------------------------------------------
+ Return value: the connection should be kept alive after the session
+ *sessionP is over.
+-----------------------------------------------------------------------------*/
+ return (sessionP->requestInfo.keepalive &&
+ !sessionP->serverDeniesKeepalive &&
+ sessionP->status < 400);
}
-abyss_bool
-DateFromGMT(TDate *d,time_t t) {
- TDate *dx;
+bool
+HTTPWriteContinue(TSession * const sessionP) {
- dx=gmtime(&t);
- if (dx) {
- *d=*dx;
- return TRUE;
- };
+ char const continueStatus[] = "HTTP/1.1 100 continue\r\n\r\n";
+ /* This is a status line plus an end-of-headers empty line */
- return FALSE;
+ return ConnWrite(sessionP->conn, continueStatus, strlen(continueStatus));
}
-abyss_bool DateFromLocal(TDate *d,time_t t)
-{
- return DateFromGMT(d,t+_DateTimeBias*2);
-}
-
-
-
-abyss_bool
-DateInit() {
- time_t t;
- TDate gmt,local,*d;
-
- time(&t);
- if (DateFromGMT(&gmt,t)) {
- d=localtime(&t);
- if (d) {
- local=*d;
- _DateTimeBias =
- (local.tm_sec-gmt.tm_sec)+(local.tm_min-gmt.tm_min)*60
- +(local.tm_hour-gmt.tm_hour)*3600;
- sprintf(_DateTimeBiasStr, "%+03d%02d",
- _DateTimeBias/3600,(_DateTimeBias % 3600)/60);
- return TRUE;
- };
- }
- return FALSE;
-}
-
-/*********************************************************************
-** Base64
-*********************************************************************/
-
-void Base64Encode(char *s,char *d)
-{
- /* Conversion table. */
- static char tbl[64] = {
- 'A','B','C','D','E','F','G','H',
- 'I','J','K','L','M','N','O','P',
- 'Q','R','S','T','U','V','W','X',
- 'Y','Z','a','b','c','d','e','f',
- 'g','h','i','j','k','l','m','n',
- 'o','p','q','r','s','t','u','v',
- 'w','x','y','z','0','1','2','3',
- '4','5','6','7','8','9','+','/'
- };
-
- uint32_t i,length=strlen(s);
- char *p=d;
-
- /* Transform the 3x8 bits to 4x6 bits, as required by base64. */
- for (i = 0; i < length; i += 3)
- {
- *p++ = tbl[s[0] >> 2];
- *p++ = tbl[((s[0] & 3) << 4) + (s[1] >> 4)];
- *p++ = tbl[((s[1] & 0xf) << 2) + (s[2] >> 6)];
- *p++ = tbl[s[2] & 0x3f];
- s += 3;
- }
-
- /* Pad the result if necessary... */
- if (i == length + 1)
- *(p - 1) = '=';
- else if (i == length + 2)
- *(p - 1) = *(p - 2) = '=';
-
- /* ...and zero-terminate it. */
- *p = '\0';
-}
-
+/******************************************************************************
+**
+** http.c
+**
+** Copyright (C) 2000 by Moez Mahfoudh <mmoez at bigfoot.com>.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR 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.
+**
+******************************************************************************/
Added: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/http.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/http.h Fri May 23 16:56:24 2008
@@ -0,0 +1,54 @@
+#ifndef HTTP_H_INCLUDED
+#define HTTP_H_INCLUDED
+
+#include "bool.h"
+#include "conn.h"
+
+/*********************************************************************
+** Request
+*********************************************************************/
+
+bool RequestValidURI(TSession * const r);
+bool RequestValidURIPath(TSession * const r);
+bool RequestUnescapeURI(TSession *r);
+
+void
+RequestRead(TSession * const sessionP,
+ uint32_t const timeout);
+
+void RequestInit(TSession * const r,TConn * const c);
+void RequestFree(TSession * const r);
+
+bool
+RequestAuth(TSession * const sessionP,
+ const char * const credential,
+ const char * const user,
+ const char * const pass);
+
+/*********************************************************************
+** HTTP
+*********************************************************************/
+
+const char *
+HTTPReasonByStatus(uint16_t const code);
+
+int32_t
+HTTPRead(TSession * const sessionP,
+ const char * const buffer,
+ uint32_t const len);
+
+bool
+HTTPWriteBodyChunk(TSession * const sessionP,
+ const char * const buffer,
+ uint32_t const len);
+
+bool
+HTTPWriteEndChunk(TSession * const sessionP);
+
+bool
+HTTPKeepalive(TSession * const sessionP);
+
+bool
+HTTPWriteContinue(TSession * const sessionP);
+
+#endif
Added: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/init.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/init.c Fri May 23 16:56:24 2008
@@ -0,0 +1,101 @@
+/*=============================================================================
+ The functions handle static stuff -- the functions do not operate on
+ any particular Abyss object, but rather on the global environment of
+ the program that uses the Abyss library. abyssInit() is essentially
+ and extension of the program loader.
+
+ The intent is for any program that uses the Abyss library to call
+ AbyssInit() just as it starts up, and AbyssTerm() just as it exits.
+ It should do both when the program is only one thread, because they
+ are not thread-safe.
+
+ These functions do the bare minimum they can get away with; we prefer
+ context to be local to invidual objects.
+=============================================================================*/
+
+#include <assert.h>
+
+#include "xmlrpc-c/string_int.h"
+
+#include "chanswitch.h"
+#include "channel.h"
+
+#include "xmlrpc-c/abyss.h"
+
+
+static unsigned int AbyssInitCount = 0;
+
+static void
+initAbyss(const char ** const errorP) {
+
+ const char * error;
+
+ DateInit();
+ MIMETypeInit();
+
+ ChanSwitchInit(&error);
+
+ if (error) {
+ xmlrpc_asprintf(errorP,
+ "Could not initialize channel swtich class. %s",
+ error);
+
+ xmlrpc_strfree(error);
+ } else {
+ const char * error;
+ ChannelInit(&error);
+
+ if (error) {
+ xmlrpc_asprintf(errorP, "Could not initialize Channel class. %s",
+ error);
+
+ xmlrpc_strfree(error);
+ } else {
+ AbyssInitCount = 1;
+ *errorP = NULL;
+
+ if (*errorP)
+ ChannelTerm();
+ }
+ if (*errorP)
+ ChanSwitchTerm();
+ }
+}
+
+
+
+void
+AbyssInit(const char ** const errorP) {
+
+ if (AbyssInitCount > 0) {
+ *errorP = NULL;
+ ++AbyssInitCount;
+ } else {
+ initAbyss(errorP);
+ if (!*errorP)
+ AbyssInitCount = 1;
+ }
+}
+
+
+
+static void
+termAbyss(void) {
+
+ ChannelTerm();
+ ChanSwitchTerm();
+ MIMETypeTerm();
+}
+
+
+
+void
+AbyssTerm(void) {
+
+ assert(AbyssInitCount > 0);
+
+ --AbyssInitCount;
+
+ if (AbyssInitCount == 0)
+ termAbyss();
+}
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/main.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/main.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/main.c Fri May 23 16:56:24 2008
@@ -37,13 +37,9 @@
#include <time.h>
#include <fcntl.h>
-#ifdef ABYSS_WIN32
+#ifdef WIN32
#include <io.h>
-#else
-/* Must check this
-#include <sys/io.h>
-*/
-#endif /* ABYSS_WIN32 */
+#endif /* WIN32 */
#ifdef _UNIX
#include <sys/signal.h>
@@ -60,7 +56,7 @@
ResponseContentType(r,"text/html");
- ResponseWrite(r);
+ ResponseWriteStart(r);
HTTPWrite(r,"<HTML><BODY>",12);
@@ -76,6 +72,8 @@
char z[50];
time_t ltime;
TDate date;
+ const char * dateString;
+ const char * answer;
if (strcmp(r->uri,"/time")!=0)
return FALSE;
@@ -83,14 +81,17 @@
if (!RequestAuth(r,"Mot de passe","moez","hello"))
return TRUE;
- time( <ime );
- DateFromGMT(&date,ltime);
-
+ time(<ime);
+ DateFromGMT(&date, ltime);
- strcpy(z,"The time is ");
- DateToString(&date,z+strlen(z));
+ DateToString(&date, &dateString);
- Answer(r,200,z);
+ xmlrpc_asprintf(&answer, "The time is %s", dateString);
+
+ Answer(r, 200, answer);
+
+ xmlrpc_strfree(dateString);
+ xmlrpc_strfree(answer);
return TRUE;
}
@@ -142,49 +143,52 @@
TraceExit("Signal %d received. Exiting...\n",sig);
}
-static void sigchld(int sig)
-{
- pid_t pid;
- int status;
- /* Reap defunct children until there aren't any more. */
- for (;;)
- {
- pid = waitpid( (pid_t) -1, &status, WNOHANG );
- /* none left */
- if (pid==0)
- break;
+static void
+sigchld(int const signalClass) {
- if (pid<0)
- {
- /* because of ptrace */
- if (errno==EINTR)
- continue;
+ bool childrenLeft;
+ bool error;
- break;
+ childrenLeft = true;
+ error = false;
+
+ /* Reap defunct children until there aren't any more. */
+ while (childrenLeft && !error) {
+ int status;
+ pid_t rc;
+ rc = waitpid((pid_t) -1, &status, WNOHANG);
+
+ if (rc == 0)
+ childrenLeft = false;
+ else if (rc < 0) {
+ /* because of ptrace */
+ if (errno == EINTR) {
+ /* ptrace causes this */
+ } else
+ error = true;
+ } else {
+ /* We reaped a child. */
+ pid_t const pid = rc;
+ ThreadHandleSigchld(pid);
}
}
}
#endif _UNIX
-void copyright()
-{
- printf("ABYSS Web Server version "SERVER_VERSION"\n(C) Moez Mahfoudh - 2000\n\n");
-}
-void help(char *name)
-{
- copyright();
- printf("Usage: %s [-h] [-c configuration file]\n\n",name);
-}
int main(int argc,char **argv)
{
+ const char * const name = argv[0];
TServer srv;
- char *p,*conffile=DEFAULT_CONF_FILE;
- abyss_bool err=FALSE;
- char *name=argv[0];
+ char * p;
+ const char * conffile;
+ bool err;
+
+ conffile = DEFAULT_CONF_FILE; /* initial value */
+ err = FALSE; /* initial value */
while (p=*(++argv))
{
@@ -199,9 +203,6 @@
else
err=TRUE;
break;
- case 'h':
- help(name);
- exit(0);
default:
err=TRUE;
}
@@ -217,11 +218,6 @@
exit(1);
};
-#ifdef ABYSS_WIN32
- copyright();
- printf("\nPress Ctrl+C to stop the server\n");
-#endif
-
DateInit();
MIMETypeInit();
@@ -246,47 +242,9 @@
/* Catch defunct children. */
signal(SIGCHLD,sigchld);
- /* Become a daemon */
- switch (fork())
- {
- case 0:
- break;
- case -1:
- TraceExit("Unable to become a daemon");
- default:
- exit(0);
- };
-
-#if !defined( _NO_USERS ) && !defined( __CYGWIN32__ )
- setsid();
- /* Change the current user if we are root */
- if (getuid()==0)
- {
- if (srv.uid==(-1))
- TraceExit("Can't run under root privileges. Please add a User option in your configuration file.");
-
- if (setgroups(0,NULL)==(-1))
- TraceExit("Failed to setup the group.");
-
- if (srv.gid!=(-1))
- if (setgid(srv.gid)==(-1))
- TraceExit("Failed to change the group.");
-
- if (setuid(srv.uid)==(-1))
- TraceExit("Failed to change the user.");
- };
#endif
- if (srv.pidfile!=(-1))
- {
- char z[16];
-
- sprintf(z,"%d",getpid());
- FileWrite(&srv.pidfile,z,strlen(z));
- FileClose(&srv.pidfile);
- };
-
-#endif
+ ServerDaemonize(srv);
ServerRun(&srv);
Added: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/response.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/response.c Fri May 23 16:56:24 2008
@@ -0,0 +1,707 @@
+/*=============================================================================
+ response
+===============================================================================
+ This module contains callbacks from and services for a request handler.
+
+ Copyright information is at the end of the file
+=============================================================================*/
+
+#include <ctype.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+
+#include "xmlrpc_config.h"
+#include "bool.h"
+#include "version.h"
+#include "mallocvar.h"
+#include "xmlrpc-c/string_int.h"
+#include "xmlrpc-c/abyss.h"
+
+#include "server.h"
+#include "session.h"
+#include "file.h"
+#include "conn.h"
+#include "token.h"
+#include "date.h"
+#include "data.h"
+#include "abyss_info.h"
+#include "http.h"
+
+
+
+void
+ResponseError2(TSession * const sessionP,
+ const char * const explanation) {
+
+ const char * errorDocument;
+
+ ResponseAddField(sessionP, "Content-type", "text/html");
+
+ ResponseWriteStart(sessionP);
+
+ xmlrpc_asprintf(&errorDocument,
+ "<HTML><HEAD><TITLE>Error %d</TITLE></HEAD>"
+ "<BODY>"
+ "<H1>Error %d</H1>"
+ "<P>%s</P>" SERVER_HTML_INFO
+ "</BODY>"
+ "</HTML>",
+ sessionP->status, sessionP->status, explanation);
+
+ ConnWrite(sessionP->conn, errorDocument, strlen(errorDocument));
+
+ xmlrpc_strfree(errorDocument);
+}
+
+
+
+void
+ResponseError(TSession * const sessionP) {
+
+ ResponseError2(sessionP, HTTPReasonByStatus(sessionP->status));
+}
+
+
+
+
+abyss_bool
+ResponseChunked(TSession * const sessionP) {
+ /* This is only a hope, things will be real only after a call of
+ ResponseWriteStart()
+ */
+ assert(!sessionP->responseStarted);
+
+ sessionP->chunkedwrite =
+ (sessionP->version.major > 1) ||
+ (sessionP->version.major == 1 && (sessionP->version.minor >= 1));
+
+ sessionP->chunkedwritemode = TRUE;
+
+ return TRUE;
+}
+
+
+
+void
+ResponseStatus(TSession * const sessionP,
+ unsigned short const code) {
+
+ sessionP->status = code;
+}
+
+
+
+xmlrpc_uint16_t
+ResponseStatusFromErrno(int const errnoArg) {
+
+ uint16_t code;
+
+ switch (errnoArg) {
+ case EACCES:
+ code=403;
+ break;
+ case ENOENT:
+ code=404;
+ break;
+ default:
+ code=500;
+ }
+ return code;
+}
+
+
+
+void
+ResponseStatusErrno(TSession * const sessionP) {
+
+ ResponseStatus(sessionP, ResponseStatusFromErrno(errno));
+}
+
+
+
+abyss_bool
+ResponseAddField(TSession * const sessionP,
+ const char * const name,
+ const char * const value) {
+
+ return TableAdd(&sessionP->response_headers, name, value);
+}
+
+
+
+static void
+addConnectionHeader(TSession * const sessionP) {
+
+ struct _TServer * const srvP = ConnServer(sessionP->conn)->srvP;
+
+ if (HTTPKeepalive(sessionP)) {
+ const char * keepaliveValue;
+
+ ResponseAddField(sessionP, "Connection", "Keep-Alive");
+
+ xmlrpc_asprintf(&keepaliveValue, "timeout=%u, max=%u",
+ srvP->keepalivetimeout, srvP->keepalivemaxconn);
+
+ ResponseAddField(sessionP, "Keep-Alive", keepaliveValue);
+
+ xmlrpc_strfree(keepaliveValue);
+ } else
+ ResponseAddField(sessionP, "Connection", "close");
+}
+
+
+
+static void
+addDateHeader(TSession * const sessionP) {
+
+ if (sessionP->status >= 200) {
+ const char * dateValue;
+
+ DateToString(sessionP->date, &dateValue);
+
+ if (dateValue) {
+ ResponseAddField(sessionP, "Date", dateValue);
+ xmlrpc_strfree(dateValue);
+ }
+ }
+}
+
+
+
+static void
+addServerHeader(TSession * const sessionP) {
+
+ const char * serverValue;
+
+ xmlrpc_asprintf(&serverValue, "XMLRPC_ABYSS/%s", XMLRPC_C_VERSION);
+
+ ResponseAddField(sessionP, "Server", serverValue);
+
+ xmlrpc_strfree(serverValue);
+}
+
+
+
+void
+ResponseWriteStart(TSession * const sessionP) {
+
+ struct _TServer * const srvP = ConnServer(sessionP->conn)->srvP;
+
+ unsigned int i;
+
+ assert(!sessionP->responseStarted);
+
+ if (sessionP->status == 0) {
+ /* Handler hasn't set status. That's an error */
+ sessionP->status = 500;
+ }
+
+ sessionP->responseStarted = TRUE;
+
+ {
+ const char * const reason = HTTPReasonByStatus(sessionP->status);
+ const char * line;
+ xmlrpc_asprintf(&line,"HTTP/1.1 %u %s\r\n", sessionP->status, reason);
+ ConnWrite(sessionP->conn, line, strlen(line));
+ xmlrpc_strfree(line);
+ }
+
+ addConnectionHeader(sessionP);
+
+ if (sessionP->chunkedwrite && sessionP->chunkedwritemode)
+ ResponseAddField(sessionP, "Transfer-Encoding", "chunked");
+
+ addDateHeader(sessionP);
+
+ if (srvP->advertise)
+ addServerHeader(sessionP);
+
+ /* send all the fields */
+ for (i = 0; i < sessionP->response_headers.size; ++i) {
+ TTableItem * const ti = &sessionP->response_headers.item[i];
+ const char * line;
+ xmlrpc_asprintf(&line, "%s: %s\r\n", ti->name, ti->value);
+ ConnWrite(sessionP->conn, line, strlen(line));
+ xmlrpc_strfree(line);
+ }
+
+ ConnWrite(sessionP->conn, "\r\n", 2);
+}
+
+
+
+abyss_bool
+ResponseWriteBody(TSession * const sessionP,
+ const char * const data,
+ xmlrpc_uint32_t const len) {
+
+ return HTTPWriteBodyChunk(sessionP, data, len);
+}
+
+
+
+abyss_bool
+ResponseWriteEnd(TSession * const sessionP) {
+
+ return HTTPWriteEndChunk(sessionP);
+}
+
+
+
+abyss_bool
+ResponseContentType(TSession * const serverP,
+ const char * const type) {
+
+ return ResponseAddField(serverP, "Content-type", type);
+}
+
+
+
+abyss_bool
+ResponseContentLength(TSession * const sessionP,
+ xmlrpc_uint64_t const len) {
+
+ char contentLengthValue[32];
+
+ sprintf(contentLengthValue, "%" PRIu64, len);
+
+ return ResponseAddField(sessionP, "Content-length", contentLengthValue);
+}
+
+
+/*********************************************************************
+** MIMEType
+*********************************************************************/
+
+struct MIMEType {
+ TList typeList;
+ TList extList;
+ TPool pool;
+};
+
+
+static MIMEType * globalMimeTypeP = NULL;
+
+
+
+MIMEType *
+MIMETypeCreate(void) {
+
+ MIMEType * MIMETypeP;
+
+ MALLOCVAR(MIMETypeP);
+
+ if (MIMETypeP) {
+ ListInit(&MIMETypeP->typeList);
+ ListInit(&MIMETypeP->extList);
+ PoolCreate(&MIMETypeP->pool, 1024);
+ }
+ return MIMETypeP;
+}
+
+
+
+void
+MIMETypeDestroy(MIMEType * const MIMETypeP) {
+
+ PoolFree(&MIMETypeP->pool);
+}
+
+
+
+void
+MIMETypeInit(void) {
+
+ if (globalMimeTypeP != NULL)
+ abort();
+
+ globalMimeTypeP = MIMETypeCreate();
+}
+
+
+
+void
+MIMETypeTerm(void) {
+
+ if (globalMimeTypeP == NULL)
+ abort();
+
+ MIMETypeDestroy(globalMimeTypeP);
+
+ globalMimeTypeP = NULL;
+}
+
+
+
+static void
+mimeTypeAdd(MIMEType * const MIMETypeP,
+ const char * const type,
+ const char * const ext,
+ bool * const successP) {
+
+ uint16_t index;
+ void * mimeTypesItem;
+ bool typeIsInList;
+
+ assert(MIMETypeP != NULL);
+
+ typeIsInList = ListFindString(&MIMETypeP->typeList, type, &index);
+ if (typeIsInList)
+ mimeTypesItem = MIMETypeP->typeList.item[index];
+ else
+ mimeTypesItem = (void*)PoolStrdup(&MIMETypeP->pool, type);
+
+ if (mimeTypesItem) {
+ bool extIsInList;
+ extIsInList = ListFindString(&MIMETypeP->extList, ext, &index);
+ if (extIsInList) {
+ MIMETypeP->typeList.item[index] = mimeTypesItem;
+ *successP = TRUE;
+ } else {
+ void * extItem = (void*)PoolStrdup(&MIMETypeP->pool, ext);
+ if (extItem) {
+ bool addedToMimeTypes;
+
+ addedToMimeTypes =
+ ListAdd(&MIMETypeP->typeList, mimeTypesItem);
+ if (addedToMimeTypes) {
+ bool addedToExt;
+
+ addedToExt = ListAdd(&MIMETypeP->extList, extItem);
+ *successP = addedToExt;
+ if (!*successP)
+ ListRemove(&MIMETypeP->typeList);
+ } else
+ *successP = FALSE;
+ if (!*successP)
+ PoolReturn(&MIMETypeP->pool, extItem);
+ } else
+ *successP = FALSE;
+ }
+ } else
+ *successP = FALSE;
+}
+
+
+
+
+abyss_bool
+MIMETypeAdd2(MIMEType * const MIMETypeArg,
+ const char * const type,
+ const char * const ext) {
+
+ MIMEType * MIMETypeP = MIMETypeArg ? MIMETypeArg : globalMimeTypeP;
+
+ bool success;
+
+ if (MIMETypeP == NULL)
+ success = FALSE;
+ else
+ mimeTypeAdd(MIMETypeP, type, ext, &success);
+
+ return success;
+}
+
+
+
+abyss_bool
+MIMETypeAdd(const char * const type,
+ const char * const ext) {
+
+ return MIMETypeAdd2(globalMimeTypeP, type, ext);
+}
+
+
+
+static const char *
+mimeTypeFromExt(MIMEType * const MIMETypeP,
+ const char * const ext) {
+
+ const char * retval;
+ uint16_t extindex;
+ bool extIsInList;
+
+ assert(MIMETypeP != NULL);
+
+ extIsInList = ListFindString(&MIMETypeP->extList, ext, &extindex);
+ if (!extIsInList)
+ retval = NULL;
+ else
+ retval = MIMETypeP->typeList.item[extindex];
+
+ return retval;
+}
+
+
+
+const char *
+MIMETypeFromExt2(MIMEType * const MIMETypeArg,
+ const char * const ext) {
+
+ const char * retval;
+
+ MIMEType * MIMETypeP = MIMETypeArg ? MIMETypeArg : globalMimeTypeP;
+
+ if (MIMETypeP == NULL)
+ retval = NULL;
+ else
+ retval = mimeTypeFromExt(MIMETypeP, ext);
+
+ return retval;
+}
+
+
+
+const char *
+MIMETypeFromExt(const char * const ext) {
+
+ return MIMETypeFromExt2(globalMimeTypeP, ext);
+}
+
+
+
+static void
+findExtension(const char * const fileName,
+ const char ** const extP) {
+
+ unsigned int extPos = 0; /* stifle unset variable warning */
+ /* Running estimation of where in fileName[] the extension starts */
+ bool extFound;
+ unsigned int i;
+
+ /* We're looking for the last dot after the last slash */
+ for (i = 0, extFound = FALSE; fileName[i]; ++i) {
+ char const c = fileName[i];
+
+ if (c == '.') {
+ extFound = TRUE;
+ extPos = i + 1;
+ }
+ if (c == '/')
+ extFound = FALSE;
+ }
+
+ if (extFound)
+ *extP = &fileName[extPos];
+ else
+ *extP = NULL;
+}
+
+
+
+static const char *
+mimeTypeFromFileName(MIMEType * const MIMETypeP,
+ const char * const fileName) {
+
+ const char * retval;
+ const char * ext;
+
+ assert(MIMETypeP != NULL);
+
+ findExtension(fileName, &ext);
+
+ if (ext)
+ retval = MIMETypeFromExt2(MIMETypeP, ext);
+ else
+ retval = "application/octet-stream";
+
+ return retval;
+}
+
+
+
+const char *
+MIMETypeFromFileName2(MIMEType * const MIMETypeArg,
+ const char * const fileName) {
+
+ const char * retval;
+
+ MIMEType * MIMETypeP = MIMETypeArg ? MIMETypeArg : globalMimeTypeP;
+
+ if (MIMETypeP == NULL)
+ retval = NULL;
+ else
+ retval = mimeTypeFromFileName(MIMETypeP, fileName);
+
+ return retval;
+}
+
+
+
+const char *
+MIMETypeFromFileName(const char * const fileName) {
+
+ return MIMETypeFromFileName2(globalMimeTypeP, fileName);
+}
+
+
+
+static bool
+fileContainsText(const char * const fileName) {
+/*----------------------------------------------------------------------------
+ Return true iff we can read the contents of the file named 'fileName'
+ and see that it appears to be composed of plain text characters.
+-----------------------------------------------------------------------------*/
+ bool retval;
+ bool fileOpened;
+ TFile * fileP;
+
+ fileOpened = FileOpen(&fileP, fileName, O_BINARY | O_RDONLY);
+ if (fileOpened) {
+ char const ctlZ = 26;
+ unsigned char buffer[80];
+ int32_t readRc;
+ unsigned int i;
+
+ readRc = FileRead(fileP, buffer, sizeof(buffer));
+
+ if (readRc >= 0) {
+ unsigned int bytesRead = readRc;
+ bool nonTextFound;
+
+ nonTextFound = FALSE; /* initial value */
+
+ for (i = 0; i < bytesRead; ++i) {
+ char const c = buffer[i];
+ if (c < ' ' && !isspace(c) && c != ctlZ)
+ nonTextFound = TRUE;
+ }
+ retval = !nonTextFound;
+ } else
+ retval = FALSE;
+ FileClose(fileP);
+ } else
+ retval = FALSE;
+
+ return retval;
+}
+
+
+
+static const char *
+mimeTypeGuessFromFile(MIMEType * const MIMETypeP,
+ const char * const fileName) {
+
+ const char * retval;
+ const char * ext;
+
+ findExtension(fileName, &ext);
+
+ retval = NULL;
+
+ if (ext && MIMETypeP)
+ retval = MIMETypeFromExt2(MIMETypeP, ext);
+
+ if (!retval) {
+ if (fileContainsText(fileName))
+ retval = "text/plain";
+ else
+ retval = "application/octet-stream";
+ }
+ return retval;
+}
+
+
+
+const char *
+MIMETypeGuessFromFile2(MIMEType * const MIMETypeArg,
+ const char * const fileName) {
+
+ return mimeTypeGuessFromFile(MIMETypeArg ? MIMETypeArg : globalMimeTypeP,
+ fileName);
+}
+
+
+
+const char *
+MIMETypeGuessFromFile(const char * const fileName) {
+
+ return mimeTypeGuessFromFile(globalMimeTypeP, fileName);
+}
+
+
+
+/*********************************************************************
+** Base64
+*********************************************************************/
+
+void
+Base64Encode(const char * const chars,
+ char * const base64) {
+
+ /* Conversion table. */
+ static char tbl[64] = {
+ 'A','B','C','D','E','F','G','H',
+ 'I','J','K','L','M','N','O','P',
+ 'Q','R','S','T','U','V','W','X',
+ 'Y','Z','a','b','c','d','e','f',
+ 'g','h','i','j','k','l','m','n',
+ 'o','p','q','r','s','t','u','v',
+ 'w','x','y','z','0','1','2','3',
+ '4','5','6','7','8','9','+','/'
+ };
+
+ uint i;
+ uint32_t length;
+ char * p;
+ const char * s;
+
+ length = strlen(chars); /* initial value */
+ s = &chars[0]; /* initial value */
+ p = &base64[0]; /* initial value */
+ /* Transform the 3x8 bits to 4x6 bits, as required by base64. */
+ for (i = 0; i < length; i += 3) {
+ *p++ = tbl[s[0] >> 2];
+ *p++ = tbl[((s[0] & 3) << 4) + (s[1] >> 4)];
+ *p++ = tbl[((s[1] & 0xf) << 2) + (s[2] >> 6)];
+ *p++ = tbl[s[2] & 0x3f];
+ s += 3;
+ }
+
+ /* Pad the result if necessary... */
+ if (i == length + 1)
+ *(p - 1) = '=';
+ else if (i == length + 2)
+ *(p - 1) = *(p - 2) = '=';
+
+ /* ...and zero-terminate it. */
+ *p = '\0';
+}
+
+
+
+/******************************************************************************
+**
+** http.c
+**
+** Copyright (C) 2000 by Moez Mahfoudh <mmoez at bigfoot.com>.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR 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.
+**
+******************************************************************************/
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/server.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/server.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/server.c Fri May 23 16:56:24 2008
@@ -1,929 +1,1235 @@
-/*******************************************************************************
-**
-** server.c
-**
-** This file is part of the ABYSS Web server project.
-**
-** Copyright (C) 2000 by Moez Mahfoudh <mmoez at bigfoot.com>.
-** All rights reserved.
-**
-** Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions
-** are met:
-** 1. Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** 2. Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in the
-** documentation and/or other materials provided with the distribution.
-** 3. The name of the author may not be used to endorse or promote products
-** derived from this software without specific prior written permission.
-**
-** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR 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.
-**
-*******************************************************************************/
+/* Copyright information is at end of file */
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+#ifndef WIN32
+ #include <grp.h>
+#endif
+
+#include "xmlrpc_config.h"
+#include "bool.h"
+#include "girmath.h"
+#include "mallocvar.h"
+#include "xmlrpc-c/string_int.h"
+#include "xmlrpc-c/sleep_int.h"
+
+#include "xmlrpc-c/abyss.h"
+#include "trace.h"
+#include "session.h"
+#include "file.h"
+#include "conn.h"
+#include "chanswitch.h"
+#include "channel.h"
+#include "socket.h"
+#ifdef WIN32
+ #include "socket_win.h"
+#else
+ #include "socket_unix.h"
+#endif
+#include "http.h"
+#include "handler.h"
+
+#include "server.h"
+
+
+void
+ServerTerminate(TServer * const serverP) {
+
+ struct _TServer * const srvP = serverP->srvP;
+
+ srvP->terminationRequested = true;
+
+ if (srvP->chanSwitchP)
+ ChanSwitchInterrupt(srvP->chanSwitchP);
+}
+
+
+
+void
+ServerResetTerminate(TServer * const serverP) {
+
+ struct _TServer * const srvP = serverP->srvP;
+
+ srvP->terminationRequested = false;
+}
+
+
+
+static void
+initUnixStuff(struct _TServer * const srvP) {
+#ifndef WIN32
+ srvP->pidfileP = NULL;
+ srvP->uid = srvP->gid = -1;
+#endif
+}
+
+
+
+static bool
+logOpen(struct _TServer * const srvP) {
+
+ bool success;
+
+ success = FileOpenCreate(&srvP->logfileP, srvP->logfilename,
+ O_WRONLY | O_APPEND);
+ if (success) {
+ bool success;
+ success = MutexCreate(&srvP->logmutexP);
+ if (success)
+ srvP->logfileisopen = TRUE;
+ else
+ TraceMsg("Can't create mutex for log file");
+
+ if (!success)
+ FileClose(srvP->logfileP);
+ } else
+ TraceMsg("Can't open log file '%s'", srvP->logfilename);
+
+ return success;
+}
+
+
+
+static void
+logClose(struct _TServer * const srvP) {
+
+ if (srvP->logfileisopen) {
+ FileClose(srvP->logfileP);
+ MutexDestroy(srvP->logmutexP);
+ srvP->logfileisopen = FALSE;
+ }
+}
+
+
+
+static void
+initChanSwitchStuff(struct _TServer * const srvP,
+ bool const noAccept,
+ TChanSwitch * const userSwitchP,
+ unsigned short const port,
+ const char ** const errorP) {
+
+ if (userSwitchP) {
+ *errorP = NULL;
+ srvP->serverAcceptsConnections = TRUE;
+ srvP->chanSwitchP = userSwitchP;
+ } else if (noAccept) {
+ *errorP = NULL;
+ srvP->serverAcceptsConnections = FALSE;
+ srvP->chanSwitchP = NULL;
+ } else {
+ *errorP = NULL;
+ srvP->serverAcceptsConnections = TRUE;
+ srvP->chanSwitchP = NULL;
+ srvP->port = port;
+ }
+ srvP->weCreatedChanSwitch = FALSE;
+}
+
+
+
+static void
+createServer(struct _TServer ** const srvPP,
+ bool const noAccept,
+ TChanSwitch * const userChanSwitchP,
+ unsigned short const portNumber,
+ const char ** const errorP) {
+
+ struct _TServer * srvP;
+
+ MALLOCVAR(srvP);
+
+ if (srvP == NULL) {
+ xmlrpc_asprintf(errorP,
+ "Unable to allocate space for server descriptor");
+ } else {
+ srvP->terminationRequested = false;
+
+ initChanSwitchStuff(srvP, noAccept, userChanSwitchP, portNumber,
+ errorP);
+
+ if (!*errorP) {
+ srvP->builtinHandlerP = HandlerCreate();
+ if (!srvP->builtinHandlerP)
+ xmlrpc_asprintf(errorP, "Unable to allocate space for "
+ "builtin handler descriptor");
+ else {
+ srvP->defaultHandler = HandlerDefaultBuiltin;
+ srvP->defaultHandlerContext = srvP->builtinHandlerP;
+
+ srvP->name = strdup("unnamed");
+ srvP->logfilename = NULL;
+ srvP->keepalivetimeout = 15;
+ srvP->keepalivemaxconn = 30;
+ srvP->timeout = 15;
+ srvP->advertise = TRUE;
+ srvP->useSigchld = FALSE;
+
+ initUnixStuff(srvP);
+
+ ListInitAutoFree(&srvP->handlers);
+
+ srvP->logfileisopen = FALSE;
+
+ *errorP = NULL;
+
+ if (*errorP)
+ HandlerDestroy(srvP->builtinHandlerP);
+ }
+ }
+ if (*errorP)
+ free(srvP);
+ }
+ *srvPP = srvP;
+}
+
+
+
+static void
+setNamePathLog(TServer * const serverP,
+ const char * const name,
+ const char * const filesPath,
+ const char * const logFileName) {
+/*----------------------------------------------------------------------------
+ This odd function exists to help with backward compatibility.
+ Today, we have the expandable model where you create a server with
+ default parameters, then use ServerSet... functions to choose
+ non-default parameters. But before, you specified these three
+ parameters right in the arguments of various create functions.
+-----------------------------------------------------------------------------*/
+ if (name)
+ ServerSetName(serverP, name);
+ if (filesPath)
+ ServerSetFilesPath(serverP, filesPath);
+ if (logFileName)
+ ServerSetLogFileName(serverP, logFileName);
+}
+
+
+
+abyss_bool
+ServerCreate(TServer * const serverP,
+ const char * const name,
+ xmlrpc_uint16_t const portNumber,
+ const char * const filesPath,
+ const char * const logFileName) {
+
+ bool const noAcceptFalse = FALSE;
+
+ bool success;
+ const char * error;
+
+ createServer(&serverP->srvP, noAcceptFalse, NULL, portNumber, &error);
+
+ if (error) {
+ TraceMsg(error);
+ xmlrpc_strfree(error);
+ success = FALSE;
+ } else {
+ success = TRUE;
+
+ setNamePathLog(serverP, name, filesPath, logFileName);
+ }
+
+ return success;
+}
+
+
+
+static void
+createSwitchFromOsSocket(TOsSocket const osSocket,
+ TChanSwitch ** const chanSwitchPP,
+ const char ** const errorP) {
+
+#ifdef WIN32
+ ChanSwitchWinCreateWinsock(osSocket, chanSwitchPP, errorP);
+#else
+ ChanSwitchUnixCreateFd(osSocket, chanSwitchPP, errorP);
+#endif
+}
+
+
+
+static void
+createChannelFromOsSocket(TOsSocket const osSocket,
+ TChannel ** const channelPP,
+ void ** const channelInfoPP,
+ const char ** const errorP) {
+
+#ifdef WIN32
+ ChannelWinCreateWinsock(osSocket, channelPP,
+ (struct abyss_win_chaninfo**)channelInfoPP,
+ errorP);
+#else
+ ChannelUnixCreateFd(osSocket, channelPP,
+ (struct abyss_unix_chaninfo**)channelInfoPP,
+ errorP);
+#endif
+}
+
+
+
+abyss_bool
+ServerCreateSocket(TServer * const serverP,
+ const char * const name,
+ TOsSocket const socketFd,
+ const char * const filesPath,
+ const char * const logFileName) {
+
+ bool success;
+ TChanSwitch * chanSwitchP;
+ const char * error;
+
+ createSwitchFromOsSocket(socketFd, &chanSwitchP, &error);
+
+ if (error) {
+ TraceMsg(error);
+ success = FALSE;
+ xmlrpc_strfree(error);
+ } else {
+ bool const noAcceptFalse = FALSE;
+
+ const char * error;
+
+ createServer(&serverP->srvP, noAcceptFalse, chanSwitchP, 0, &error);
+
+ if (error) {
+ TraceMsg(error);
+ success = FALSE;
+ xmlrpc_strfree(error);
+ } else {
+ success = TRUE;
+
+ setNamePathLog(serverP, name, filesPath, logFileName);
+ }
+ }
+
+ return success;
+}
+
+
+
+abyss_bool
+ServerCreateNoAccept(TServer * const serverP,
+ const char * const name,
+ const char * const filesPath,
+ const char * const logFileName) {
+
+ bool const noAcceptTrue = TRUE;
+
+ bool success;
+ const char * error;
+
+ createServer(&serverP->srvP, noAcceptTrue, NULL, 0, &error);
+
+ if (error) {
+ TraceMsg(error);
+ success = FALSE;
+ xmlrpc_strfree(error);
+ } else {
+ success = TRUE;
+
+ setNamePathLog(serverP, name, filesPath, logFileName);
+ }
+ return success;
+}
+
+
+
+void
+ServerCreateSwitch(TServer * const serverP,
+ TChanSwitch * const chanSwitchP,
+ const char ** const errorP) {
+
+ bool const noAcceptFalse = FALSE;
+
+ assert(serverP);
+ assert(chanSwitchP);
+
+ createServer(&serverP->srvP, noAcceptFalse, chanSwitchP, 0, errorP);
+}
+
+
+
+void
+ServerCreateSocket2(TServer * const serverP,
+ TSocket * const socketP,
+ const char ** const errorP) {
+
+ TChanSwitch * const chanSwitchP = SocketGetChanSwitch(socketP);
+
+ assert(socketP);
+
+ if (!chanSwitchP)
+ xmlrpc_asprintf(
+ errorP, "Socket is not a listening socket. "
+ "You should use ServerCreateSwitch() instead, anyway.");
+ else
+ ServerCreateSwitch(serverP, chanSwitchP, errorP);
+}
+
+
+
+static void
+terminateHandlers(TList * const handlersP) {
+/*----------------------------------------------------------------------------
+ Terminate all handlers in the list '*handlersP'.
+
+ I.e. call each handler's terminate function.
+-----------------------------------------------------------------------------*/
+ if (handlersP->item) {
+ unsigned int i;
+ for (i = handlersP->size; i > 0; --i) {
+ URIHandler2 * const handlerP = handlersP->item[i-1];
+ if (handlerP->term)
+ handlerP->term(handlerP->userdata);
+ }
+ }
+}
+
+
+
+void
+ServerFree(TServer * const serverP) {
+
+ struct _TServer * const srvP = serverP->srvP;
+
+ if (srvP->weCreatedChanSwitch)
+ ChanSwitchDestroy(srvP->chanSwitchP);
+
+ xmlrpc_strfree(srvP->name);
+
+ terminateHandlers(&srvP->handlers);
+
+ ListFree(&srvP->handlers);
+
+ HandlerDestroy(srvP->builtinHandlerP);
+
+ logClose(srvP);
+
+ if (srvP->logfilename)
+ xmlrpc_strfree(srvP->logfilename);
+
+ free(srvP);
+}
+
+
+
+void
+ServerSetName(TServer * const serverP,
+ const char * const name) {
+
+ xmlrpc_strfree(serverP->srvP->name);
+
+ serverP->srvP->name = strdup(name);
+}
+
+
+
+void
+ServerSetFilesPath(TServer * const serverP,
+ const char * const filesPath) {
+
+ HandlerSetFilesPath(serverP->srvP->builtinHandlerP, filesPath);
+}
+
+
+
+void
+ServerSetLogFileName(TServer * const serverP,
+ const char * const logFileName) {
+
+ struct _TServer * const srvP = serverP->srvP;
+
+ if (srvP->logfilename)
+ xmlrpc_strfree(srvP->logfilename);
+
+ srvP->logfilename = strdup(logFileName);
+}
+
+
+
+void
+ServerSetKeepaliveTimeout(TServer * const serverP,
+ xmlrpc_uint32_t const keepaliveTimeout) {
+
+ serverP->srvP->keepalivetimeout = keepaliveTimeout;
+}
+
+
+
+void
+ServerSetKeepaliveMaxConn(TServer * const serverP,
+ xmlrpc_uint32_t const keepaliveMaxConn) {
+
+ serverP->srvP->keepalivemaxconn = keepaliveMaxConn;
+}
+
+
+
+void
+ServerSetTimeout(TServer * const serverP,
+ xmlrpc_uint32_t const timeout) {
+
+ serverP->srvP->timeout = timeout;
+}
+
+
+
+void
+ServerSetAdvertise(TServer * const serverP,
+ abyss_bool const advertise) {
+
+ serverP->srvP->advertise = advertise;
+}
+
+
+
+void
+ServerSetMimeType(TServer * const serverP,
+ MIMEType * const mimeTypeP) {
+
+ HandlerSetMimeType(serverP->srvP->builtinHandlerP, mimeTypeP);
+}
+
+
+
+static void
+runUserHandler(TSession * const sessionP,
+ struct _TServer * const srvP) {
+
+ abyss_bool handled;
+ int i;
+
+ for (i = srvP->handlers.size-1, handled = FALSE;
+ i >= 0 && !handled;
+ --i) {
+ URIHandler2 * const handlerP = srvP->handlers.item[i];
+
+ if (handlerP->handleReq2)
+ handlerP->handleReq2(handlerP, sessionP, &handled);
+ else if (handlerP->handleReq1)
+ handled = handlerP->handleReq1(sessionP);
+ }
+
+ assert(srvP->defaultHandler);
+
+ if (!handled)
+ srvP->defaultHandler(sessionP);
+}
+
+
+
+static void
+processDataFromClient(TConn * const connectionP,
+ bool const lastReqOnConn,
+ uint32_t const timeout,
+ bool * const keepAliveP) {
+
+ TSession session;
+
+ RequestInit(&session, connectionP);
+
+ session.serverDeniesKeepalive = lastReqOnConn;
+
+ RequestRead(&session, timeout);
+
+ if (session.status == 0) {
+ if (session.version.major >= 2)
+ ResponseStatus(&session, 505);
+ else if (!RequestValidURI(&session))
+ ResponseStatus(&session, 400);
+ else
+ runUserHandler(&session, connectionP->server->srvP);
+ }
+
+ assert(session.status != 0);
+
+ if (session.responseStarted)
+ HTTPWriteEndChunk(&session);
+ else
+ ResponseError(&session);
+
+ *keepAliveP = HTTPKeepalive(&session);
+
+ SessionLog(&session);
+
+ RequestFree(&session);
+}
+
+
+
+static TThreadProc serverFunc;
+
+static void
+serverFunc(void * const userHandle) {
+/*----------------------------------------------------------------------------
+ Do server stuff on one connection. At its simplest, this means do
+ one HTTP request. But with keepalive, it can be many requests.
+-----------------------------------------------------------------------------*/
+ TConn * const connectionP = userHandle;
+ struct _TServer * const srvP = connectionP->server->srvP;
+
+ unsigned int requestCount;
+ /* Number of requests we've handled so far on this connection */
+ bool connectionDone;
+ /* No more need for this HTTP connection */
+
+ requestCount = 0;
+ connectionDone = FALSE;
+
+ while (!connectionDone) {
+ bool success;
+
+ /* Wait to read until timeout */
+ success = ConnRead(connectionP, srvP->keepalivetimeout);
+
+ if (!success)
+ connectionDone = TRUE;
+ else {
+ bool const lastReqOnConn =
+ requestCount + 1 >= srvP->keepalivemaxconn;
+
+ bool keepalive;
+
+ processDataFromClient(connectionP, lastReqOnConn, srvP->timeout,
+ &keepalive);
+
+ ++requestCount;
+
+ if (!keepalive)
+ connectionDone = TRUE;
+
+ /**************** Must adjust the read buffer *****************/
+ ConnReadInit(connectionP);
+ }
+ }
+}
+
+
+
+static void
+createSwitchFromPortNum(unsigned short const portNumber,
+ TChanSwitch ** const chanSwitchPP,
+ const char ** const errorP) {
+
+#ifdef WIN32
+ ChanSwitchWinCreate(portNumber, chanSwitchPP, errorP);
+#else
+ ChanSwitchUnixCreate(portNumber, chanSwitchPP, errorP);
+#endif
+}
+
+
+
+static void
+createChanSwitch(struct _TServer * const srvP,
+ const char ** const errorP) {
+
+ TChanSwitch * chanSwitchP;
+ const char * error;
+
+ /* Not valid to call this when channel switch already exists: */
+ assert(srvP->chanSwitchP == NULL);
+
+ createSwitchFromPortNum(srvP->port, &chanSwitchP, &error);
+
+ if (error) {
+ xmlrpc_asprintf(errorP,
+ "Can't create channel switch. %s", error);
+ xmlrpc_strfree(error);
+ } else {
+ *errorP = NULL;
+
+ srvP->weCreatedChanSwitch = TRUE;
+ srvP->chanSwitchP = chanSwitchP;
+ }
+}
+
+
+
+void
+ServerInit(TServer * const serverP) {
+/*----------------------------------------------------------------------------
+ Initialize a server to accept connections.
+
+ Do not confuse this with creating the server -- ServerCreate().
+
+ Not necessary or valid with a server that doesn't accept connections (i.e.
+ user supplies the channels (TCP connections)).
+-----------------------------------------------------------------------------*/
+ struct _TServer * const srvP = serverP->srvP;
+ const char * retError;
+
+ if (!srvP->serverAcceptsConnections)
+ xmlrpc_asprintf(&retError,
+ "ServerInit() is not valid on a server that doesn't "
+ "accept connections "
+ "(i.e. created with ServerCreateNoAccept)");
+ else {
+ retError = NULL; /* initial value */
+
+ if (!srvP->chanSwitchP) {
+ const char * error;
+ createChanSwitch(srvP, &error);
+
+ if (error) {
+ xmlrpc_asprintf(&retError, "Unable to create a channel switch "
+ "for the server. %s", error);
+ xmlrpc_strfree(error);
+ }
+ }
+
+ if (!retError) {
+ const char * error;
+
+ assert(srvP->chanSwitchP);
+
+ ChanSwitchListen(srvP->chanSwitchP, MAX_CONN, &error);
+
+ if (error) {
+ xmlrpc_asprintf(&retError,
+ "Failed to listen on bound socket. %s",
+ error);
+ xmlrpc_strfree(error);
+ }
+ }
+ }
+ if (retError) {
+ TraceMsg("ServerInit() failed. %s", retError);
+ exit(1);
+ xmlrpc_strfree(retError);
+ }
+}
+
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#ifdef ABYSS_WIN32
-#include <io.h>
-#else
-/* Check this
-#include <sys/io.h>
+
+/* We don't do any locking on the outstanding connections list, so
+ we must make sure that only the master thread (the one that listens
+ for connections) ever accesses it.
+
+ That's why when a thread completes, it places the connection in
+ "finished" status, but doesn't destroy the connection.
*/
-#endif /* ABYSS_WIN32 */
-#include <fcntl.h>
-#include "mallocvar.h"
+typedef struct {
-#include "xmlrpc-c/abyss.h"
+ TConn * firstP;
+ unsigned int count;
+ /* Redundant with 'firstP', for quick access */
+} outstandingConnList;
+
+
+
+static void
+createOutstandingConnList(outstandingConnList ** const listPP) {
+
+ outstandingConnList * listP;
-#define BOUNDARY "##123456789###BOUNDARY"
+ MALLOCVAR_NOFAIL(listP);
-typedef int (*TQSortProc)(const void *, const void *);
+ listP->firstP = NULL; /* empty list */
+ listP->count = 0;
-static int
-cmpfilenames(const TFileInfo **f1,const TFileInfo **f2) {
- if (((*f1)->attrib & A_SUBDIR) && !((*f2)->attrib & A_SUBDIR))
- return (-1);
- if (!((*f1)->attrib & A_SUBDIR) && ((*f2)->attrib & A_SUBDIR))
- return 1;
-
- return strcmp((*f1)->name,(*f2)->name);
-}
-
-static int
-cmpfiledates(const TFileInfo **f1,const TFileInfo **f2) {
- if (((*f1)->attrib & A_SUBDIR) && !((*f2)->attrib & A_SUBDIR))
- return (-1);
- if (!((*f1)->attrib & A_SUBDIR) && ((*f2)->attrib & A_SUBDIR))
- return 1;
-
- return ((*f1)->time_write-(*f2)->time_write);
+ *listPP = listP;
}
-static abyss_bool
-ServerDirectoryHandler(TSession *r,char *z,TDate *dirdate) {
- TFileInfo fileinfo,*fi;
- TFileFind findhandle;
- char *p,z1[26],z2[20],z3[9],u,*z4;
- TList list;
- int16_t i;
- uint32_t k;
- abyss_bool text=FALSE;
- abyss_bool ascending=TRUE;
- uint16_t sort=1; /* 1=by name, 2=by date */
- struct tm ftm;
- TPool pool;
- TDate date;
-
- if (r->query) {
- if (strcmp(r->query,"plain")==0)
- text=TRUE;
- else if (strcmp(r->query,"name-up")==0)
- {
- sort=1;
- ascending=TRUE;
- }
- else if (strcmp(r->query,"name-down")==0)
- {
- sort=1;
- ascending=FALSE;
- }
- else if (strcmp(r->query,"date-up")==0)
- {
- sort=2;
- ascending=TRUE;
- }
- else if (strcmp(r->query,"date-down")==0)
- {
- sort=2;
- ascending=FALSE;
- }
- else
- {
- ResponseStatus(r,400);
- return TRUE;
- };
- }
- if (DateCompare(&r->date,dirdate)<0)
- dirdate=&r->date;
-
- p=RequestHeaderValue(r,"If-Modified-Since");
- if (p) {
- if (DateDecode(p,&date)) {
- if (DateCompare(dirdate,&date)<=0)
- {
- ResponseStatus(r,304);
- ResponseWrite(r);
- return TRUE;
- };
- }
- }
- if (!FileFindFirst(&findhandle,z,&fileinfo))
- {
- ResponseStatusErrno(r);
- return TRUE;
- };
-
- ListInit(&list);
-
- if (!PoolCreate(&pool,1024))
- {
- ResponseStatus(r,500);
- return TRUE;
- };
-
- do
- {
- /* Files which names start with a dot are ignored */
- /* This includes implicitly the ./ and ../ */
- if (*fileinfo.name=='.') {
- if (strcmp(fileinfo.name,"..")==0)
- {
- if (strcmp(r->uri,"/")==0)
- continue;
- }
- else
- continue;
- }
- fi=(TFileInfo *)PoolAlloc(&pool,sizeof(fileinfo));
- if (fi)
- {
- memcpy(fi,&fileinfo,sizeof(fileinfo));
- if (ListAdd(&list,fi))
- continue;
- };
-
- ResponseStatus(r,500);
- FileFindClose(&findhandle);
- ListFree(&list);
- PoolFree(&pool);
- return TRUE;
-
- } while (FileFindNext(&findhandle,&fileinfo));
-
- FileFindClose(&findhandle);
-
- /* Send something to the user to show that we are still alive */
- ResponseStatus(r,200);
- ResponseContentType(r,(text?"text/plain":"text/html"));
-
- if (DateToString(dirdate,z))
- ResponseAddField(r,"Last-Modified",z);
-
- ResponseChunked(r);
- ResponseWrite(r);
-
- if (r->method!=m_head)
- {
- if (text)
- {
- sprintf(z,"Index of %s" CRLF,r->uri);
- i=strlen(z)-2;
- p=z+i+2;
-
- while (i>0)
- {
- *(p++)='-';
- i--;
- };
-
- *p='\0';
- strcat(z,CRLF CRLF
- "Name Size "
- "Date-Time Type" CRLF
- "------------------------------------"
- "--------------------------------------------"CRLF);
- }
- else
- {
- sprintf(z,"<HTML><HEAD><TITLE>Index of %s</TITLE></HEAD><BODY>"
- "<H1>Index of %s</H1><PRE>",r->uri,r->uri);
- strcat(z,"Name Size "
- "Date-Time Type<HR WIDTH=100%>"CRLF);
- };
-
- HTTPWrite(r,z,strlen(z));
-
- /* Sort the files */
- qsort(list.item,list.size,sizeof(void *),
- (TQSortProc)(sort==1?cmpfilenames:cmpfiledates));
-
- /* Write the listing */
- if (ascending)
- i=0;
- else
- i=list.size-1;
+static void
+destroyOutstandingConnList(outstandingConnList * const listP) {
- while ((i<list.size) && (i>=0))
- {
- fi=list.item[i];
-
- if (ascending)
- i++;
- else
- i--;
-
- strcpy(z,fi->name);
+ assert(listP->firstP == NULL);
+ assert(listP->count == 0);
- k=strlen(z);
+ free(listP);
+}
- if (fi->attrib & A_SUBDIR)
- {
- z[k++]='/';
- z[k]='\0';
- };
-
- if (k>24)
- {
- z[10]='\0';
- strcpy(z1,z);
- strcat(z1,"...");
- strcat(z1,z+k-11);
- k=24;
- p=z1+24;
- }
- else
- {
- strcpy(z1,z);
-
- k++;
- p=z1+k;
- while (k<25)
- z1[k++]=' ';
-
- z1[25]='\0';
- };
-
- ftm=*(gmtime(&fi->time_write));
- sprintf(z2,"%02u/%02u/%04u %02u:%02u:%02u",ftm.tm_mday,ftm.tm_mon,
- ftm.tm_year+1900,ftm.tm_hour,ftm.tm_min,ftm.tm_sec);
-
- if (fi->attrib & A_SUBDIR)
- {
- strcpy(z3," -- ");
- z4="Directory";
- }
- else
- {
- if (fi->size<9999)
- u='b';
- else
- {
- fi->size/=1024;
- if (fi->size<9999)
- u='K';
- else
- {
- fi->size/=1024;
- if (fi->size<9999)
- u='M';
- else
- u='G';
- };
- };
-
- sprintf(z3, "%5llu %c", fi->size, u);
-
- if (strcmp(fi->name,"..")==0)
- z4="";
- else
- z4=MIMETypeFromFileName(fi->name);
-
- if (!z4)
- z4="Unknown";
- };
-
- if (text)
- sprintf(z,"%s%s %s %s %s"CRLF,
- z1,p,z3,z2,z4);
- else
- sprintf(z,"<A HREF=\"%s%s\">%s</A>%s %s %s %s"CRLF,
- fi->name,(fi->attrib & A_SUBDIR?"/":""),z1,p,z3,z2,z4);
- HTTPWrite(r,z,strlen(z));
- };
-
- /* Write the tail of the file */
- if (text)
- strcpy(z,SERVER_PLAIN_INFO);
- else
- strcpy(z,"</PRE>" SERVER_HTML_INFO "</BODY></HTML>" CRLF CRLF);
- HTTPWrite(r,z,strlen(z));
- };
-
- HTTPWriteEnd(r);
- /* Free memory and exit */
- ListFree(&list);
- PoolFree(&pool);
-
- return TRUE;
-}
-
-static abyss_bool
-ServerFileHandler(TSession *r,char *z,TDate *filedate) {
- char *mediatype;
- TFile file;
- uint64_t filesize,start,end;
- uint16_t i;
- TDate date;
- char *p;
-
- mediatype=MIMETypeGuessFromFile(z);
-
- if (!FileOpen(&file,z,O_BINARY | O_RDONLY))
- {
- ResponseStatusErrno(r);
- return TRUE;
- };
-
- if (DateCompare(&r->date,filedate)<0)
- filedate=&r->date;
-
- p=RequestHeaderValue(r,"if-modified-since");
- if (p) {
- if (DateDecode(p,&date)) {
- if (DateCompare(filedate,&date)<=0) {
- ResponseStatus(r,304);
- ResponseWrite(r);
- return TRUE;
- }
- else
- r->ranges.size=0;
- }
- }
- filesize=FileSize(&file);
+static void
+addToOutstandingConnList(outstandingConnList * const listP,
+ TConn * const connectionP) {
- switch (r->ranges.size)
- {
- case 0:
- ResponseStatus(r,200);
- break;
+ connectionP->nextOutstandingP = listP->firstP;
- case 1:
- if (!RangeDecode((char *)(r->ranges.item[0]),filesize,&start,&end))
- {
- ListFree(&(r->ranges));
- ResponseStatus(r,200);
- break;
- }
-
- sprintf(z, "bytes %llu-%llu/%llu", start, end, filesize);
+ listP->firstP = connectionP;
- ResponseAddField(r,"Content-range",z);
- ResponseContentLength(r,end-start+1);
- ResponseStatus(r,206);
- break;
+ ++listP->count;
+}
- default:
- ResponseContentType(r,"multipart/ranges; boundary=" BOUNDARY);
- ResponseStatus(r,206);
- break;
- };
-
- if (r->ranges.size==0)
- {
- ResponseContentLength(r,filesize);
- ResponseContentType(r,mediatype);
- };
-
- if (DateToString(filedate,z))
- ResponseAddField(r,"Last-Modified",z);
-
- ResponseWrite(r);
-
- if (r->method!=m_head)
- {
- if (r->ranges.size==0)
- ConnWriteFromFile(r->conn,&file,0,filesize-1,z,4096,0);
- else if (r->ranges.size==1)
- ConnWriteFromFile(r->conn,&file,start,end,z,4096,0);
- else
- for (i=0;i<=r->ranges.size;i++)
- {
- ConnWrite(r->conn,"--",2);
- ConnWrite(r->conn,BOUNDARY,strlen(BOUNDARY));
- ConnWrite(r->conn,CRLF,2);
-
- if (i<r->ranges.size)
- if (RangeDecode((char *)(r->ranges.item[i]),
- filesize,
- &start,&end))
- {
- /* Entity header, not response header */
- sprintf(z,"Content-type: %s" CRLF
- "Content-range: bytes %llu-%llu/%llu" CRLF
- "Content-length: %llu" CRLF
- CRLF, mediatype, start, end,
- filesize, end-start+1);
-
- ConnWrite(r->conn,z,strlen(z));
-
- ConnWriteFromFile(r->conn,&file,start,end,z,4096,0);
- };
- };
- };
-
- FileClose(&file);
-
- return TRUE;
-}
-
-static abyss_bool
-ServerDefaultHandlerFunc(TSession *r) {
- char *p,z[4096];
- TFileStat fs;
- uint16_t i;
- abyss_bool endingslash=FALSE;
- TDate objdate;
-
- if (!RequestValidURIPath(r))
- {
- ResponseStatus(r,400);
- return TRUE;
- };
-
- /* Must check for * (asterisk uri) in the future */
- if (r->method==m_options)
- {
- ResponseAddField(r,"Allow","GET, HEAD");
- ResponseContentLength(r,0);
- ResponseStatus(r,200);
- return TRUE;
- };
-
- if ((r->method!=m_get) && (r->method!=m_head))
- {
- ResponseAddField(r,"Allow","GET, HEAD");
- ResponseStatus(r,405);
- return TRUE;
- };
-
- strcpy(z,r->server->filespath);
- strcat(z,r->uri);
-
- p=z+strlen(z)-1;
- if (*p=='/')
- {
- endingslash=TRUE;
- *p='\0';
- };
-
-#ifdef ABYSS_WIN32
- p=z;
- while (*p)
- {
- if ((*p)=='/')
- *p='\\';
-
- p++;
- };
-#endif /* ABYSS_WIN32 */
-
- if (!FileStat(z,&fs))
- {
- ResponseStatusErrno(r);
- return TRUE;
- };
-
- if (fs.st_mode & S_IFDIR)
- {
- /* Redirect to the same directory but with the ending slash
- ** to avoid problems with some browsers (IE for examples) when
- ** they generate relative urls */
- if (!endingslash)
- {
- strcpy(z,r->uri);
- p=z+strlen(z);
- *p='/';
- *(p+1)='\0';
- ResponseAddField(r,"Location",z);
- ResponseStatus(r,302);
- ResponseWrite(r);
- return TRUE;
- };
-#ifdef ABYSS_WIN32
- *p='\\';
-#else
- *p='/';
-#endif /* ABYSS_WIN32 */
- p++;
-
- i=r->server->defaultfilenames.size;
- while (i-->0) {
- *p='\0';
- strcat(z,(char *)(r->server->defaultfilenames.item[i]));
- if (FileStat(z,&fs)) {
- if (!(fs.st_mode & S_IFDIR)) {
- if (DateFromLocal(&objdate,fs.st_mtime))
- return ServerFileHandler(r,z,&objdate);
- else
- return ServerFileHandler(r,z,NULL);
- }
- }
- };
- *(p-1)='\0';
-
- if (!FileStat(z,&fs))
- {
- ResponseStatusErrno(r);
- return TRUE;
- };
+static void
+freeFinishedConns(outstandingConnList * const listP) {
+/*----------------------------------------------------------------------------
+ Garbage-collect the resources associated with connections that are
+ finished with their jobs. Thread resources, connection pool
+ descriptor, etc.
+-----------------------------------------------------------------------------*/
+ TConn ** pp;
- if (DateFromLocal(&objdate,fs.st_mtime))
- return ServerDirectoryHandler(r,z,&objdate);
- else
- return ServerDirectoryHandler(r,z,NULL);
+ pp = &listP->firstP;
+
+ while (*pp) {
+ TConn * const connectionP = (*pp);
+ ThreadUpdateStatus(connectionP->threadP);
+
+ if (connectionP->finished) {
+ /* Take it out of the list */
+ *pp = connectionP->nextOutstandingP;
+ --listP->count;
+
+ ConnWaitAndRelease(connectionP);
+ } else {
+ /* Move to next connection in list */
+ pp = &connectionP->nextOutstandingP;
+ }
}
- else
- if (DateFromLocal(&objdate,fs.st_mtime))
- return ServerFileHandler(r,z,&objdate);
- else
- return ServerFileHandler(r,z,NULL);
}
-abyss_bool
-ServerCreate(TServer * const srvP,
- const char * const name,
- uint16_t const port,
- const char * const filespath,
- const char * const logfilename) {
-
- abyss_bool success;
-
- if (name)
- srvP->name = strdup(name);
- else
- srvP->name = "unnamed";
+static void
+waitForConnectionFreed(outstandingConnList * const outstandingConnListP
+ ATTR_UNUSED) {
+/*----------------------------------------------------------------------------
+ Wait for a connection descriptor in 'connectionPool' to be probably
+ freed.
+-----------------------------------------------------------------------------*/
- srvP->port = port;
+ /* TODO: We should do something more sophisticated here. For pthreads,
+ we can have a thread signal us by semaphore when it terminates.
+ For fork, we might be able to use the "done" handler argument
+ to ConnCreate() to get interrupted when the death of a child
+ signal happens.
+ */
- srvP->defaulthandler = ServerDefaultHandlerFunc;
+ xmlrpc_millisecond_sleep(2000);
+}
- if (filespath)
- srvP->filespath = strdup(filespath);
- else
- srvP->filespath = strdup(DEFAULT_DOCS);
- srvP->keepalivetimeout = 15;
- srvP->keepalivemaxconn = 30;
- srvP->timeout = 15;
- srvP->advertise = TRUE;
-#ifdef _UNIX
- srvP->pidfile = srvP->uid = srvP->gid = -1;
-#endif /* _UNIX */
- ListInit(&srvP->handlers);
- ListInitAutoFree(&srvP->defaultfilenames);
+static void
+waitForNoConnections(outstandingConnList * const outstandingConnListP) {
- if (logfilename)
- success = LogOpen(srvP, logfilename);
- else {
- srvP->logfile = -1;
- success = TRUE;
+ while (outstandingConnListP->firstP) {
+ freeFinishedConns(outstandingConnListP);
+
+ if (outstandingConnListP->firstP)
+ waitForConnectionFreed(outstandingConnListP);
}
- return success;
}
static void
-terminateHandlers(TList * const handlersP) {
+waitForConnectionCapacity(outstandingConnList * const outstandingConnListP) {
/*----------------------------------------------------------------------------
- Terminate all handlers in the list '*handlersP'.
-
- I.e. call each handler's terminate function.
+ Wait until there are fewer than the maximum allowed connections in
+ progress.
-----------------------------------------------------------------------------*/
- if (handlersP->item) {
- unsigned int i;
- for (i = handlersP->size; i > 0; --i) {
- URIHandler2 * const handlerP = handlersP->item[i-1];
- if (handlerP->term)
- handlerP->term(handlerP);
- }
+ /* We need to make this number configurable. Note that MAX_CONN (16) is
+ also the backlog limit on the TCP socket, and they really aren't
+ related. As it stands, we can have 16 connections in progress inside
+ Abyss plus 16 waiting in the the channel switch.
+ */
+
+ while (outstandingConnListP->count >= MAX_CONN) {
+ freeFinishedConns(outstandingConnListP);
+ if (outstandingConnListP->firstP)
+ waitForConnectionFreed(outstandingConnListP);
}
}
+#ifndef WIN32
void
-ServerFree(TServer * const srvP) {
+ServerHandleSigchld(pid_t const pid) {
- free(srvP->name);
+ ThreadHandleSigchld(pid);
+}
+#endif
- free(srvP->filespath);
-
- terminateHandlers(&srvP->handlers);
- ListFree(&srvP->handlers);
- ListInitAutoFree(&srvP->defaultfilenames);
+void
+ServerUseSigchld(TServer * const serverP) {
- LogClose(srvP);
+ struct _TServer * const srvP = serverP->srvP;
+
+ srvP->useSigchld = TRUE;
}
+static TThreadDoneFn destroyChannel;
+
static void
-ServerFunc(TConn * c) {
+destroyChannel(void * const userHandle) {
+/*----------------------------------------------------------------------------
+ This is a "connection done" function for the connection the server
+ serves. It gets called some time after the connection has done its
+ thing. Its job is to clean up stuff the server created for use by
+ the connection, but the server can't clean up because the
+ connection might be processed asynchronously in a background
+ thread.
- TSession r;
- uint32_t ka;
- TList handlers = c->server->handlers;
+ To wit, we destroy the connection's channel and release the memory
+ for the information about that channel.
+-----------------------------------------------------------------------------*/
+ TConn * const connectionP = userHandle;
- ka=c->server->keepalivemaxconn;
+ ChannelDestroy(connectionP->channelP);
+ free(connectionP->channelInfoP);
+}
- while (ka--) {
- RequestInit(&r,c);
- /* Wait to read until timeout */
- if (!ConnRead(c,c->server->keepalivetimeout))
- break;
- if (RequestRead(&r)) {
- /* Check if it is the last keepalive */
- if (ka==1)
- r.keepalive=FALSE;
-
- r.cankeepalive=r.keepalive;
-
- if (r.status==0) {
- if (r.versionmajor>=2)
- ResponseStatus(&r,505);
- else if (!RequestValidURI(&r))
- ResponseStatus(&r,400);
- else {
- abyss_bool handled;
- int i;
-
- for (i = c->server->handlers.size-1, handled = FALSE;
- i >= 0 && !handled;
- --i) {
- URIHandler2 * const handlerP = handlers.item[i];
-
- if (handlerP->handleReq2)
- handlerP->handleReq2(handlerP, &r, &handled);
- else if (handlerP->handleReq1)
- handled = handlerP->handleReq1(&r);
- }
+static void
+acceptAndProcessNextConnection(
+ TServer * const serverP,
+ outstandingConnList * const outstandingConnListP) {
+
+ struct _TServer * const srvP = serverP->srvP;
+
+ TConn * connectionP;
+ const char * error;
+ TChannel * channelP;
+ void * channelInfoP;
+
+ ChanSwitchAccept(srvP->chanSwitchP, &channelP, &channelInfoP, &error);
+
+ if (error) {
+ TraceMsg("Failed to accept the next connection from a client "
+ "at the channel level. %s", error);
+ xmlrpc_strfree(error);
+ } else {
+ if (channelP) {
+ const char * error;
- if (!handled)
- ((URIHandler)(c->server->defaulthandler))(&r);
- }
+ freeFinishedConns(outstandingConnListP);
+
+ waitForConnectionCapacity(outstandingConnListP);
+
+ ConnCreate(&connectionP, serverP, channelP, channelInfoP,
+ &serverFunc, &destroyChannel, ABYSS_BACKGROUND,
+ srvP->useSigchld,
+ &error);
+ if (!error) {
+ addToOutstandingConnList(outstandingConnListP,
+ connectionP);
+ ConnProcess(connectionP);
+ /* When connection is done (which could be later, courtesy
+ of a background thread), destroyChannel() will
+ destroy *channelP.
+ */
+ } else {
+ xmlrpc_strfree(error);
+ ChannelDestroy(channelP);
+ free(channelInfoP);
}
+ } else {
+ /* Accept function was interrupted before it got a connection */
}
-
- HTTPWriteEnd(&r);
+ }
+}
+
+
- if (!r.done)
- ResponseError(&r);
+static void
+serverRun2(TServer * const serverP) {
- SessionLog(&r);
+ struct _TServer * const srvP = serverP->srvP;
+ outstandingConnList * outstandingConnListP;
- if (!(r.keepalive && r.cankeepalive))
- break;
+ createOutstandingConnList(&outstandingConnListP);
- /**************** Must adjust the read buffer *****************/
- ConnReadInit(c);
- };
+ while (!srvP->terminationRequested)
+ acceptAndProcessNextConnection(serverP, outstandingConnListP);
- RequestFree(&r);
- SocketClose(&(c->socket));
+ waitForNoConnections(outstandingConnListP);
+
+ destroyOutstandingConnList(outstandingConnListP);
}
-int ServerInit(TServer *srv)
-{
- /********* Must check errors from these functions *************/
- if (!SocketInit()) {
- TraceMsg("Can't initialize TCP sockets\n");
- return FALSE;
- }
- if (!SocketCreate(&srv->listensock)) {
- TraceMsg("Can't create a socket\n");
- return FALSE;
- }
- if (!SocketBind(&srv->listensock,NULL,srv->port)) {
- TraceMsg("Can't bind\n");
- return FALSE;
- }
+void
+ServerRun(TServer * const serverP) {
- if (!SocketListen(&srv->listensock,MAX_CONN)) {
- TraceMsg("Can't listen\n");
- return FALSE;
- }
+ struct _TServer * const srvP = serverP->srvP;
- return TRUE;
+ if (!srvP->chanSwitchP)
+ TraceMsg("This server is not set up to accept connections "
+ "on its own, so you can't use ServerRun(). "
+ "Try ServerRunConn() or ServerInit()");
+ else
+ serverRun2(serverP);
}
-/* With pthread configuration, our connections run as threads of a
- single address space, so we manage a pool of connection
- descriptors. With fork configuration, our connections run as
- separate processes with their own memory, so we don't have the
- pool.
-*/
-static abyss_bool const usingPthreadsForConnections =
-#ifdef _THREAD
-TRUE;
-#else
-FALSE;
-#endif
+static void
+serverRunChannel(TServer * const serverP,
+ TChannel * const channelP,
+ void * const channelInfoP,
+ const char ** const errorP) {
+/*----------------------------------------------------------------------------
+ Do the HTTP transaction on the channel 'channelP'.
+ (channel must be at the beginning of the HTTP request -- nothing having
+ been read or written yet).
+ channelInfoP == NULL means no channel info supplied.
+-----------------------------------------------------------------------------*/
+ struct _TServer * const srvP = serverP->srvP;
-static void
-ServerRunThreaded(TServer *srv)
-{
- uint32_t i;
- TSocket s,ns;
- TIPAddr peerIpAddr;
- TConn *c;
-
- /* Connection array from Heap. Small systems might not
- * have the "stack_size" required to have the array of
- * connections right on it */
- MALLOCARRAY_NOFAIL(c, MAX_CONN);
-
- for (i=0;i<MAX_CONN;i++)
- c[i].inUse = FALSE;
-
- s=srv->listensock;
- srv->running = 1;
- while( srv->running )
- {
- /* collect all threads resources for closed connections */
- for (i=0;i<MAX_CONN;i++)
- {
- if( c[i].inUse && ( c[i].connected == FALSE ) )
- {
- ConnClose( &c[i] );
- c[i].inUse = FALSE;
- }
- }
-
- for (i=0; i<MAX_CONN && c[i].inUse; ++i);
+ TConn * connectionP;
+ const char * error;
- if (i==MAX_CONN)
- {
- /* Every connection descriptor was in use. */
- ThreadWait(2000);
- continue;
- };
-
- if (SocketAccept(&s,&ns,&peerIpAddr))
- {
- abyss_bool success;
- c[i].inUse = TRUE;
- success = ConnCreate2(&c[i], srv, ns, peerIpAddr, &ServerFunc,
- ABYSS_BACKGROUND);
- if (success)
- {
- ConnProcess(&c[i]);
- }
- else
- {
- SocketClose(&ns);
- c[i].inUse = FALSE;
- }
- }
- else
- TraceMsg("Socket Error=%d\n", SocketError());
+ srvP->keepalivemaxconn = 1;
+
+ ConnCreate(&connectionP,
+ serverP, channelP, channelInfoP,
+ &serverFunc, NULL, ABYSS_FOREGROUND, srvP->useSigchld,
+ &error);
+ if (error) {
+ xmlrpc_asprintf(errorP, "Couldn't create HTTP connection out of "
+ "channel (connected socket). %s", error);
+ xmlrpc_strfree(error);
+ } else {
+ *errorP = NULL;
+
+ ConnProcess(connectionP);
+
+ ConnWaitAndRelease(connectionP);
}
- /* We never get here, but it's conceptually possible for someone to
- terminate a server normally, so...
- */
- free( c );
}
-static void
-ServerRunForked(TServer *srv)
-{
- TSocket s,ns;
- TConn c;
- TIPAddr ip;
-
- s=srv->listensock;
-
- while (1)
- {
- if (SocketAccept(&s,&ns,&ip))
- {
- abyss_bool success;
- success = ConnCreate2(&c,
- srv, ns, ip, ServerFunc, ABYSS_BACKGROUND);
-
- /* ConnCreate2() forks. Child does not return. */
- if (success)
- ConnProcess(&c);
+void
+ServerRunChannel(TServer * const serverP,
+ TChannel * const channelP,
+ void * const channelInfoP,
+ const char ** const errorP) {
+/*----------------------------------------------------------------------------
+ Do the HTTP transaction on the channel 'channelP'.
- SocketClose(&ns); /* Close parent's copy of socket */
- }
- else
- TraceMsg("Socket Error=%d\n", SocketError());
- };
+ (channel must be at the beginning of the HTTP request -- nothing having
+ been read or written yet).
+-----------------------------------------------------------------------------*/
+ struct _TServer * const srvP = serverP->srvP;
+
+ if (srvP->serverAcceptsConnections)
+ xmlrpc_asprintf(errorP,
+ "This server is configured to accept connections on "
+ "its own socket. "
+ "Try ServerRun() or ServerCreateNoAccept().");
+ else
+ serverRunChannel(serverP, channelP, channelInfoP, errorP);
}
-void
-ServerRun(TServer * const serverP) {
- if (usingPthreadsForConnections)
- ServerRunThreaded(serverP);
+void
+ServerRunConn2(TServer * const serverP,
+ TSocket * const connectedSocketP,
+ const char ** const errorP) {
+/*----------------------------------------------------------------------------
+ Do the HTTP transaction on the TCP connection on the socket
+ *connectedSocketP.
+ (socket must be connected state, with nothing having been read or
+ written on the connection yet).
+-----------------------------------------------------------------------------*/
+ TChannel * const channelP = SocketGetChannel(connectedSocketP);
+
+ if (!channelP)
+ xmlrpc_asprintf(errorP, "The socket supplied is not a connected "
+ "socket. You should use ServerRunChannel() instead, "
+ "anyway.");
else
- ServerRunForked(serverP);
+ ServerRunChannel(serverP,
+ channelP, SocketGetChannelInfo(connectedSocketP),
+ errorP);
}
-/* ServerRunOnce() supplied by Brian Quinlan of ActiveState. */
+void
+ServerRunConn(TServer * const serverP,
+ TOsSocket const connectedOsSocket) {
-/* Bryan Henderson found this to be completely wrong on 2001.11.29
- and changed it so it does the same thing as ServerRun(), but only
- once.
+ TChannel * channelP;
+ void * channelInfoP;
+ const char * error;
+
+ createChannelFromOsSocket(connectedOsSocket,
+ &channelP, &channelInfoP, &error);
+ if (error) {
+ TraceExit("Unable to use supplied socket");
+ xmlrpc_strfree(error);
+ } else {
+ const char * error;
+
+ ServerRunChannel(serverP, channelP, channelInfoP, &error);
+
+ if (error) {
+ TraceExit("Failed to run server on connection on file "
+ "descriptor %d. %s", connectedOsSocket, error);
+ xmlrpc_strfree(error);
+ }
+ ChannelDestroy(channelP);
+ free(channelInfoP);
+ }
+}
- The biggest problem it had was that when it forked the child (via
- ConnCreate(), both the parent and the child read the socket and
- processed the request!
-*/
-static void
-closeParentSocketCopy(TSocket * socketP) {
+void
+ServerRunOnce(TServer * const serverP) {
/*----------------------------------------------------------------------------
- If we're doing forked connections, close the indicated socket because it
- is the parent's copy and the parent doesn't need it. If we're doing
- threaded connections, then there's no such thing as a parent's copy, so
- nothing to close.
+ Accept a connection from the channel switch and do the HTTP
+ transaction that comes over it.
+
+ If no connection is presently waiting at the switch, wait for one.
+ But return immediately if we receive a signal during the wait.
-----------------------------------------------------------------------------*/
-#ifndef _THREAD
- SocketClose(socketP);
-#endif
+ struct _TServer * const srvP = serverP->srvP;
+
+ if (!srvP->chanSwitchP)
+ TraceMsg("This server is not set up to accept connections "
+ "on its own, so you can't use ServerRunOnce(). "
+ "Try ServerRunChannel() or ServerInit()");
+ else {
+ const char * error;
+ TChannel * channelP;
+ void * channelInfoP;
+
+ srvP->keepalivemaxconn = 1;
+
+ ChanSwitchAccept(srvP->chanSwitchP, &channelP, &channelInfoP, &error);
+ if (error) {
+ TraceMsg("Failed to accept the next connection from a client "
+ "at the channel level. %s", error);
+ xmlrpc_strfree(error);
+ } else {
+ if (channelP) {
+ const char * error;
+
+ serverRunChannel(serverP, channelP, channelInfoP, &error);
+
+ if (error) {
+ const char * peerDesc;
+ ChannelFormatPeerInfo(channelP, &peerDesc);
+ TraceExit("Got a connection from '%s', but failed to "
+ "run server on it. %s", peerDesc, error);
+ xmlrpc_strfree(peerDesc);
+ xmlrpc_strfree(error);
+ }
+ ChannelDestroy(channelP);
+ free(channelInfoP);
+ }
+ }
+ }
}
-void ServerRunOnce2(TServer * const srv,
- enum abyss_foreback const foregroundBackground)
-{
- TConn connection;
- TSocket listenSocket;
- TSocket connectedSocket;
- TIPAddr remoteAddr;
- abyss_bool succeeded;
- srv->keepalivemaxconn = 1;
+void
+ServerRunOnce2(TServer * const serverP,
+ enum abyss_foreback const foregroundBackground ATTR_UNUSED) {
+/*----------------------------------------------------------------------------
+ This is a backward compatibility interface to ServerRunOnce().
+
+ 'foregroundBackground' is meaningless. We always process the
+ connection in the foreground. The parameter exists because we once
+ thought we could do them in the background, but we really can't do
+ that in any clean way. If Caller wants background execution, he can
+ spin his own thread or process to call us. It makes much more sense
+ in Caller's context.
+-----------------------------------------------------------------------------*/
+ ServerRunOnce(serverP);
+}
+
+
- connection.connected = FALSE;
- connection.inUse = FALSE;
+static void
+setGroups(void) {
- listenSocket = srv->listensock;
-
- succeeded = SocketAccept(&listenSocket, &connectedSocket, &remoteAddr);
- if (succeeded) {
- abyss_bool success;
- success = ConnCreate2(&connection,
- srv, connectedSocket, remoteAddr,
- &ServerFunc,
- foregroundBackground);
- if (success)
- ConnProcess(&connection);
- closeParentSocketCopy(&connectedSocket);
- } else
- TraceMsg("Socket Error=%d\n", SocketError());
+#if HAVE_SETGROUPS
+ if (setgroups(0, NULL) == (-1))
+ TraceExit("Failed to setup the group.");
+#endif
}
-void ServerRunOnce(TServer *srv)
-{
- ServerRunOnce2(srv, ABYSS_BACKGROUND);
+
+
+void
+ServerDaemonize(TServer * const serverP) {
+/*----------------------------------------------------------------------------
+ Turn Caller into a daemon (i.e. fork a child, then exit; the child
+ returns to Caller).
+
+ NOTE: It's ridiculous, but conventional, for us to do this. It's
+ ridiculous because the task of daemonizing is not something
+ particular to Abyss. It ought to be done by a higher level. In
+ fact, it should be done before the Abyss server program is even
+ execed. The user should run a "daemonize" program that creates a
+ daemon which execs the Abyss server program.
+-----------------------------------------------------------------------------*/
+ struct _TServer * const srvP = serverP->srvP;
+
+#ifndef _WIN32
+ /* Become a daemon */
+ switch (fork()) {
+ case 0:
+ break;
+ case -1:
+ TraceExit("Unable to become a daemon");
+ default:
+ /* We are the parent */
+ exit(0);
+ }
+
+ setsid();
+
+ /* Change the current user if we are root */
+ if (getuid()==0) {
+ if (srvP->uid == (uid_t)-1)
+ TraceExit("Can't run under root privileges. "
+ "Please add a User option in your "
+ "Abyss configuration file.");
+
+ setGroups();
+
+ if (srvP->gid != (gid_t)-1)
+ if (setgid(srvP->gid)==(-1))
+ TraceExit("Failed to change the group.");
+
+ if (setuid(srvP->uid) == -1)
+ TraceExit("Failed to change the user.");
+ }
+
+ if (srvP->pidfileP) {
+ char z[16];
+
+ sprintf(z, "%d", getpid());
+ FileWrite(srvP->pidfileP, z, strlen(z));
+ FileClose(srvP->pidfileP);
+ }
+#endif /* _WIN32 */
}
void
-ServerAddHandler2(TServer * const srvP,
+ServerAddHandler2(TServer * const serverP,
URIHandler2 * const handlerArgP,
abyss_bool * const successP) {
@@ -940,14 +1246,9 @@
else
handlerP->init(handlerP, successP);
- if (*successP) {
- *successP = ListAdd(&srvP->handlers, handlerP);
+ if (*successP)
+ *successP = ListAdd(&serverP->srvP->handlers, handlerP);
- if (!*successP) {
- if (handlerP->term)
- handlerP->term(handlerP);
- }
- }
if (!*successP)
free(handlerP);
}
@@ -955,14 +1256,6 @@
-static void
-destroyHandler(URIHandler2 * const handlerP) {
-
- free(handlerP);
-}
-
-
-
static URIHandler2 *
createHandler(URIHandler const function) {
@@ -971,7 +1264,7 @@
MALLOCVAR(handlerP);
if (handlerP != NULL) {
handlerP->init = NULL;
- handlerP->term = destroyHandler;
+ handlerP->term = NULL;
handlerP->userdata = NULL;
handlerP->handleReq2 = NULL;
handlerP->handleReq1 = function;
@@ -982,18 +1275,18 @@
abyss_bool
-ServerAddHandler(TServer * const srvP,
+ServerAddHandler(TServer * const serverP,
URIHandler const function) {
URIHandler2 * handlerP;
- abyss_bool success;
+ bool success;
handlerP = createHandler(function);
if (handlerP == NULL)
success = FALSE;
else {
- success = ListAdd(&srvP->handlers, handlerP);
+ success = ListAdd(&serverP->srvP->handlers, handlerP);
if (!success)
free(handlerP);
@@ -1004,67 +1297,72 @@
void
-ServerDefaultHandler(TServer * const srvP,
+ServerDefaultHandler(TServer * const serverP,
URIHandler const handler) {
- srvP->defaulthandler = handler;
-}
-
-abyss_bool LogOpen(TServer *srv, const char *filename) {
+ struct _TServer * const srvP = serverP->srvP;
- if (FileOpenCreate(&(srv->logfile),filename,O_WRONLY | O_APPEND)) {
- if (MutexCreate(&(srv->logmutex)))
- return TRUE;
- else {
- FileClose(&(srv->logfile));
- srv->logfile=(-1);
- }
+ if (handler)
+ srvP->defaultHandler = handler;
+ else {
+ srvP->defaultHandler = HandlerDefaultBuiltin;
+ srvP->defaultHandlerContext = srvP->builtinHandlerP;
}
-
- TraceMsg("Can't open log file '%s'",filename);
- return FALSE;
-}
-
-void LogWrite(TServer *srv,char *c)
-{
- if ((srv->logfile)==(-1))
- return;
-
- if (!MutexLock(&(srv->logmutex)))
- return;
-
- FileWrite(&(srv->logfile),c,strlen(c));
- FileWrite(&(srv->logfile),LBR,strlen(LBR));
-
- MutexUnlock(&(srv->logmutex));
}
-void LogClose(TServer *srv)
-{
- if ((srv->logfile)==(-1))
- return;
- FileClose(&(srv->logfile));
- MutexFree(&(srv->logmutex));
-}
-
-abyss_bool SessionLog(TSession *s)
-{
- char z[1024];
- uint32_t n;
-
- if (s->requestline == NULL)
- return FALSE;
-
- if (strlen(s->requestline)>1024-26-50)
- s->requestline[1024-26-50]='\0';
- n=sprintf(z,"%d.%d.%d.%d - %s - [",IPB1(s->conn->peerip),IPB2(s->conn->peerip),IPB3(s->conn->peerip),IPB4(s->conn->peerip),(s->user?s->user:""));
+void
+LogWrite(TServer * const serverP,
+ const char * const msg) {
- DateToLogString(&s->date,z+n);
+ struct _TServer * const srvP = serverP->srvP;
- sprintf(z+n+20,"] \"%s\" %d %d",s->requestline,s->status,s->conn->outbytes);
+ if (!srvP->logfileisopen && srvP->logfilename)
+ logOpen(srvP);
- LogWrite(s->server,z);
- return TRUE;
+ if (srvP->logfileisopen) {
+ bool success;
+ success = MutexLock(srvP->logmutexP);
+ if (success) {
+ const char * const lbr = "\n";
+ FileWrite(srvP->logfileP, msg, strlen(msg));
+ FileWrite(srvP->logfileP, lbr, strlen(lbr));
+
+ MutexUnlock(srvP->logmutexP);
+ }
+ }
}
+/*******************************************************************************
+**
+** server.c
+**
+** This file is part of the ABYSS Web server project.
+**
+** Copyright (C) 2000 by Moez Mahfoudh <mmoez at bigfoot.com>.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR 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.
+**
+******************************************************************************/
Added: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/server.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/server.h Fri May 23 16:56:24 2008
@@ -0,0 +1,85 @@
+#ifndef SERVER_H_INCLUDED
+#define SERVER_H_INCLUDED
+
+#include <sys/types.h>
+
+#include "bool.h"
+#include "xmlrpc-c/abyss.h"
+
+#include "data.h"
+
+struct TFile;
+struct abyss_mutex;
+
+struct _TServer {
+ bool terminationRequested;
+ /* User wants this server to terminate as soon as possible,
+ in particular before accepting any more connections and without
+ waiting for any.
+ */
+ bool chanSwitchBound;
+ /* The channel switch exists and is bound to a local address
+ (may already be listening as well)
+ */
+ TChanSwitch * chanSwitchP;
+ /* Meaningful only when 'chanSwitchBound' is true: the channel
+ switch which directs connections from clients to this server.
+ */
+ bool weCreatedChanSwitch;
+ /* We created the channel switch 'chanSwitchP', as
+ opposed to 1) User supplied it; or 2) there isn't one.
+ */
+ const char * logfilename;
+ bool logfileisopen;
+ struct TFile * logfileP;
+ struct abyss_mutex * logmutexP;
+ const char * name;
+ bool serverAcceptsConnections;
+ /* We listen for and accept TCP connections for HTTP transactions.
+ (The alternative is the user supplies a TCP-connected socket
+ for each transaction)
+ */
+ uint16_t port;
+ /* Meaningful only when 'chanSwitchBound' is false: TCP port
+ number to which we should bind the switch.
+ */
+ uint32_t keepalivetimeout;
+ uint32_t keepalivemaxconn;
+ uint32_t timeout;
+ /* Maximum time in seconds the server will wait to read a header
+ or a data chunk from the channel.
+ */
+ TList handlers;
+ /* Ordered list of HTTP request handlers. For each HTTP request,
+ Server calls each one in order until one reports that it handled
+ it.
+
+ Each item in the list of of type 'URIHandler2'.
+ */
+ URIHandler defaultHandler;
+ /* The handler for HTTP requests that aren't claimed by any handler
+ in the list 'handlers'. This can't be null; if user doesn't
+ supply anything better, it is a built-in basic web server
+ handler. */
+ void * defaultHandlerContext;
+ /* This is opaque data to be given to the default handler when it
+ requests it.
+ */
+ void * builtinHandlerP;
+ bool advertise;
+ bool useSigchld;
+ /* Meaningless if not using forking for threads.
+ TRUE means user will call ServerHandleSigchld to indicate that
+ a SIGCHLD signal was received, and server shall use that as its
+ indication that a child has died. FALSE means server will not
+ be aware of SIGCHLD and will instead poll for existence of PIDs
+ to determine if a child has died.
+ */
+#ifndef WIN32
+ uid_t uid;
+ gid_t gid;
+ struct TFile * pidfileP;
+#endif
+};
+
+#endif
Added: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/session.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/session.c Fri May 23 16:56:24 2008
@@ -0,0 +1,158 @@
+#include <assert.h>
+#include <sys/types.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "bool.h"
+#include "xmlrpc-c/util_int.h"
+#include "xmlrpc-c/string_int.h"
+#include "xmlrpc-c/abyss.h"
+#include "server.h"
+#include "http.h"
+#include "conn.h"
+
+#include "session.h"
+
+
+
+abyss_bool
+SessionRefillBuffer(TSession * const sessionP) {
+/*----------------------------------------------------------------------------
+ Get the next chunk of HTTP request body from the connection into
+ the buffer.
+
+ I.e. read data from the socket.
+-----------------------------------------------------------------------------*/
+ struct _TServer * const srvP = sessionP->conn->server->srvP;
+ bool failed;
+
+ failed = FALSE; /* initial value */
+
+ /* Reset our read buffer & flush data from previous reads. */
+ ConnReadInit(sessionP->conn);
+
+ if (sessionP->continueRequired)
+ failed = !HTTPWriteContinue(sessionP);
+
+ if (!failed) {
+ sessionP->continueRequired = FALSE;
+
+ /* Read more network data into our buffer. If we encounter a
+ timeout, exit immediately. We're very forgiving about the
+ timeout here. We allow a full timeout per network read, which
+ would allow somebody to keep a connection alive nearly
+ indefinitely. But it's hard to do anything intelligent here
+ without very complicated code.
+ */
+ failed = !ConnRead(sessionP->conn, srvP->timeout);
+ }
+ return !failed;
+}
+
+
+
+size_t
+SessionReadDataAvail(TSession * const sessionP) {
+
+ return sessionP->conn->buffersize - sessionP->conn->bufferpos;
+
+}
+
+
+
+void
+SessionGetReadData(TSession * const sessionP,
+ size_t const max,
+ const char ** const outStartP,
+ size_t * const outLenP) {
+/*----------------------------------------------------------------------------
+ Extract some HTTP request body which the server has read and
+ buffered for the session. Don't get or wait for any data that has
+ not yet arrived. Do not return more than 'max'.
+
+ We return a pointer to the first byte as *outStartP, and the length in
+ bytes as *outLenP. The memory pointed to belongs to the session.
+-----------------------------------------------------------------------------*/
+ uint32_t const bufferPos = sessionP->conn->bufferpos;
+
+ *outStartP = &sessionP->conn->buffer[bufferPos];
+
+ assert(bufferPos <= sessionP->conn->buffersize);
+
+ *outLenP = MIN(max, sessionP->conn->buffersize - bufferPos);
+
+ /* move pointer past the bytes we are returning */
+ sessionP->conn->bufferpos += *outLenP;
+
+ assert(sessionP->conn->bufferpos <= sessionP->conn->buffersize);
+}
+
+
+
+void
+SessionGetRequestInfo(TSession * const sessionP,
+ const TRequestInfo ** const requestInfoPP) {
+
+ *requestInfoPP = &sessionP->requestInfo;
+}
+
+
+
+void
+SessionGetChannelInfo(TSession * const sessionP,
+ void ** const channelInfoPP) {
+
+ *channelInfoPP = sessionP->conn->channelInfoP;
+}
+
+
+
+abyss_bool
+SessionLog(TSession * const sessionP) {
+
+ const char * logline;
+ const char * user;
+ const char * date;
+ const char * peerInfo;
+
+ if (sessionP->validRequest) {
+ if (sessionP->requestInfo.user)
+ user = sessionP->requestInfo.user;
+ else
+ user = "no_user";
+ } else
+ user = "???";
+
+ DateToLogString(sessionP->date, &date);
+
+ ConnFormatClientAddr(sessionP->conn, &peerInfo);
+
+ xmlrpc_asprintf(&logline, "%s - %s - [%s] \"%s\" %d %d",
+ peerInfo,
+ user,
+ date,
+ sessionP->validRequest ?
+ sessionP->requestInfo.requestline : "???",
+ sessionP->status,
+ sessionP->conn->outbytes
+ );
+ xmlrpc_strfree(peerInfo);
+ xmlrpc_strfree(date);
+
+ if (logline) {
+ LogWrite(sessionP->conn->server, logline);
+
+ xmlrpc_strfree(logline);
+ }
+ return true;
+}
+
+
+
+void *
+SessionGetDefaultHandlerCtx(TSession * const sessionP) {
+
+ struct _TServer * const srvP = sessionP->conn->server->srvP;
+
+ return srvP->defaultHandlerContext;
+}
Added: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/session.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/session.h Fri May 23 16:56:24 2008
@@ -0,0 +1,74 @@
+#ifndef SESSION_H_INCLUDED
+#define SESSION_H_INCLUDED
+
+#include "xmlrpc-c/abyss.h"
+#include "bool.h"
+#include "date.h"
+#include "data.h"
+
+typedef struct {
+ uint8_t major;
+ uint8_t minor;
+} httpVersion;
+
+struct _TSession {
+ bool validRequest;
+ /* Client has sent, and server has recognized, a valid HTTP request.
+ This is false when the session is new. If and when the server
+ reads the request from the client and finds it to be valid HTTP,
+ it becomes true.
+ */
+ TRequestInfo requestInfo;
+ /* Some of the strings this references are in individually malloc'ed
+ memory, but some are pointers into arbitrary other data structures
+ that happen to live as long as the session. Some day, we will
+ fix that.
+
+ 'requestInfo' is valid only if 'validRequest' is true.
+ */
+ uint32_t nbfileds;
+ TList cookies;
+ TList ranges;
+
+ uint16_t status;
+ /* Response status from handler. Zero means session is not ready
+ for a response yet. This can mean that we ran a handler and it
+ did not call ResponseStatus() to declare this fact.
+ */
+ TString header;
+
+ bool serverDeniesKeepalive;
+ /* Server doesn't want keepalive for this session, regardless of
+ what happens in the session. E.g. because the connection has
+ already been kept alive long enough.
+ */
+ bool responseStarted;
+ /* Handler has at least started the response (i.e. called
+ ResponseWriteStart())
+ */
+
+ struct _TConn * conn;
+
+ httpVersion version;
+
+ TTable request_headers;
+ /* All the headers in the HTTP request. The key is the header
+ name in lower case. The value is the verbatim value from
+ the header.
+ */
+
+ TTable response_headers;
+
+ time_t date;
+
+ bool chunkedwrite;
+ bool chunkedwritemode;
+
+ bool continueRequired;
+ /* This client must receive 100 (continue) status before it will
+ send more of the body of the request.
+ */
+};
+
+
+#endif
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/socket.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/socket.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/socket.c Fri May 23 16:56:24 2008
@@ -1,269 +1,126 @@
-/******************************************************************************
-**
-** socket.c
-**
-** This file is part of the ABYSS Web server project.
-**
-** Copyright (C) 2000 by Moez Mahfoudh <mmoez at bigfoot.com>.
-** All rights reserved.
-**
-** Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions
-** are met:
-** 1. Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** 2. Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in the
-** documentation and/or other materials provided with the distribution.
-** 3. The name of the author may not be used to endorse or promote products
-** derived from this software without specific prior written permission.
-**
-** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR 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.
-**
-******************************************************************************/
+/*============================================================================
+ socket.c
+==============================================================================
+ Implementation of obsolete TSocket class.
-#include "xmlrpc_config.h"
+ Use TChannel and TChanSwitch instead for new work.
+============================================================================*/
+#include <assert.h>
#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#ifdef HAVE_SYS_FILIO_H
- #include <sys/filio.h>
-#endif
+
+#include "mallocvar.h"
#include "xmlrpc-c/abyss.h"
+#include "channel.h"
+#include "chanswitch.h"
-#ifdef ABYSS_WIN32
-#define EINTR WSAEINTR
-#endif
-
-static abyss_bool ABYSS_TRACE_SOCKET;
-
-/*********************************************************************
-** Socket
-*********************************************************************/
-
-abyss_bool SocketInit()
-{
- abyss_bool retval;
-#ifdef ABYSS_WIN32
- WORD wVersionRequested;
- WSADATA wsaData;
- int err;
-
- wVersionRequested = MAKEWORD( 2, 0 );
-
- err = WSAStartup( wVersionRequested, &wsaData );
- retval = ( err == 0 );
-#else
- retval = TRUE;
- ABYSS_TRACE_SOCKET = (getenv("ABYSS_TRACE_SOCKET") != NULL);
-#endif /* ABYSS_WIN32 */
- if (ABYSS_TRACE_SOCKET)
- fprintf(stderr, "Abyss socket layer will trace socket traffic "
- "due to ABYSS_TRACE_SOCKET environment variable\n");
- return retval;
-}
+#include "socket.h"
-#define RET(x) return ((x)!=(-1))
-abyss_bool SocketCreate(TSocket *s)
-{
- int rc;
-
- rc =socket(AF_INET,SOCK_STREAM,0);
- if (rc < 0)
- return FALSE;
- else {
- int32_t n=1;
- *s = rc;
- RET(setsockopt(*s,SOL_SOCKET,SO_REUSEADDR,(char*)&n,sizeof(n)));
- }
-}
+/* SocketCreate...() is not exported to the Abyss user. It is meant to
+ be used by an implementation-specific TSocket generator which is
+ exported to the Abyss user, e.g. SocketCreateUnix() in
+ socket_unix.c
-abyss_bool SocketClose(TSocket *s)
-{
-#ifdef ABYSS_WIN32
- RET(closesocket(*s));
-#else
- RET(close(*s));
-#endif /* ABYSS_WIN32 */
-}
+ The TSocket generator functions are the _only_ user-accessible
+ functions that are particular to an implementation.
+*/
-int SocketWrite(TSocket *s, char *buffer, uint32_t len)
-{
- return send(*s,buffer,len,0);
-}
+static uint const socketSignature = 0x060609;
+static void
+socketCreate(TSocket ** const socketPP) {
-uint32_t SocketRead(TSocket * const socketP,
- char * const buffer,
- uint32_t const len) {
- int rc;
- rc = recv(*socketP, buffer, len, 0);
- if (ABYSS_TRACE_SOCKET) {
- if (rc < 0)
- fprintf(stderr, "Abyss socket: recv() failed. errno=%d (%s)",
- errno, strerror(errno));
- else
- fprintf(stderr, "Abyss socket: read %u bytes: '%.*s'\n",
- len, (int)len, buffer);
- }
- return rc;
+ TSocket * socketP;
+
+ MALLOCVAR(socketP);
+
+ if (socketP) {
+ socketP->signature = socketSignature;
+ *socketPP = socketP;
+ } else
+ *socketPP = NULL;
}
-uint32_t SocketPeek(TSocket *s, char *buffer, uint32_t len)
-{
- int32_t r=recv(*s,buffer,len,MSG_PEEK);
-
- if (r==(-1))
-#ifdef ABYSS_WIN32
- if (SocketError()==WSAEMSGSIZE)
-#else
- if (SocketError()==EMSGSIZE)
-#endif
- return len;
+void
+SocketCreateChannel(TChannel * const channelP,
+ void * const channelInfoP,
+ TSocket ** const socketPP) {
- return r;
-}
+ TSocket * socketP;
-abyss_bool SocketConnect(TSocket *s, TIPAddr *addr, uint16_t port)
-{
- struct sockaddr_in name;
-
- name.sin_family=AF_INET;
- name.sin_port=htons(port);
- name.sin_addr=*addr;
+ socketCreate(&socketP);
- RET(connect(*s,(struct sockaddr *)&name,sizeof(name)));
+ if (socketP) {
+ socketP->channelP = channelP;
+ socketP->chanSwitchP = NULL;
+ socketP->channelInfoP = channelInfoP;
+ *socketPP = socketP;
+ } else
+ *socketPP = NULL;
}
-abyss_bool SocketBind(TSocket *s, TIPAddr *addr, uint16_t port)
-{
- struct sockaddr_in name;
-
- name.sin_family=AF_INET;
- name.sin_port=htons(port);
- if (addr)
- name.sin_addr=*addr;
- else
- name.sin_addr.s_addr=INADDR_ANY;
- RET(bind(*s,(struct sockaddr *)&name,sizeof(name)));
-}
-abyss_bool SocketListen(TSocket *s, uint32_t backlog)
-{
- int32_t n=-1;
+void
+SocketCreateChanSwitch(TChanSwitch * const chanSwitchP,
+ TSocket ** const socketPP) {
- /* Disable the naggle algorithm to make persistant connections faster */
- setsockopt(*s, IPPROTO_TCP,TCP_NODELAY,(char *)&n,sizeof(n));
+ TSocket * socketP;
- RET(listen(*s,backlog));
-}
+ socketCreate(&socketP);
-abyss_bool SocketAccept(TSocket *s, TSocket *ns,TIPAddr *ip)
-{
- struct sockaddr_in sa;
- socklen_t size=sizeof(sa);
- abyss_bool connected;
-
- connected = FALSE;
- for (;;) {
- int rc;
- rc = accept(*s,(struct sockaddr *)&sa,&size);
- if (rc >= 0)
- {
- connected = TRUE;
- *ns = rc;
- *ip=sa.sin_addr;
- break;
- }
- else
- if (SocketError()!=EINTR)
- break;
- }
- return connected;
+ if (socketP) {
+ socketP->channelP = NULL;
+ socketP->chanSwitchP = chanSwitchP;
+ *socketPP = socketP;
+ } else
+ *socketPP = NULL;
}
-uint32_t SocketWait(TSocket *s,abyss_bool rd,abyss_bool wr,uint32_t timems)
-{
- fd_set rfds,wfds;
-#ifdef ABYSS_WIN32
- TIMEVAL tv;
-#else
- struct timeval tv;
-#endif /* ABYSS_WIN32 */
-
- FD_ZERO(&rfds);
- FD_ZERO(&wfds);
-
- if (rd)
- FD_SET(*s,&rfds);
-
- if (wr)
- FD_SET(*s,&wfds);
-
- tv.tv_sec=timems/1000;
- tv.tv_usec=timems%1000;
-
-
- for (;;)
- switch(select((*s)+1,&rfds,&wfds,NULL,
- (timems==TIME_INFINITE?NULL:&tv)))
- {
- case 0: /* time out */
- return 0;
-
- case (-1): /* socket error */
- if (SocketError()==EINTR)
- break;
-
- return 0;
-
- default:
- if (FD_ISSET(*s,&rfds))
- return 1;
- if (FD_ISSET(*s,&wfds))
- return 2;
- return 0;
- };
+
+
+void
+SocketDestroy(TSocket * const socketP) {
+
+ assert(socketP->signature == socketSignature);
+
+ if (socketP->channelP) {
+ ChannelDestroy(socketP->channelP);
+ free(socketP->channelInfoP);
+ }
+
+ if (socketP->chanSwitchP)
+ ChanSwitchDestroy(socketP->chanSwitchP);
+
+ socketP->signature = 0; /* For debuggability */
+
+ free(socketP);
}
-abyss_bool SocketBlocking(TSocket *s, abyss_bool b)
-{
- uint32_t x=b;
- RET(ioctlsocket(*s,FIONBIO,&x));
+
+TChanSwitch *
+SocketGetChanSwitch(TSocket * const socketP) {
+
+ return socketP->chanSwitchP;
}
-uint32_t SocketAvailableReadBytes(TSocket *s)
-{
- uint32_t x;
- if (ioctlsocket(*s,FIONREAD,&x)!=0)
- x=0;
- return x;
+TChannel *
+SocketGetChannel(TSocket * const socketP) {
+
+ return socketP->channelP;
}
-uint32_t SocketError()
-{
-#ifdef ABYSS_WIN32
- return WSAGetLastError();
-#else
- return errno;
-#endif /* ABYSS_WIN32 */
+
+
+void *
+SocketGetChannelInfo(TSocket * const socketP) {
+
+ return socketP->channelInfoP;
}
Added: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/socket.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/socket.h Fri May 23 16:56:24 2008
@@ -0,0 +1,58 @@
+#ifndef SOCKET_H_INCLUDED
+#define SOCKET_H_INCLUDED
+
+/*============================================================================
+ This is for backward compatibility. Abyss used to have a socket
+ concept modelled after POSIX sockets, in which a single class (TSocket)
+ contained two very different kinds of objects: some analogous to
+ a TChanSwitch and analogout to a TChannel.
+
+ Now that we have TChanSwitch and TChannel, users should use those,
+ but there may be old programs that use TSocket, and we want them to
+ continue working.
+
+ Actually, this may not be necessary. There was only one release
+ (1.06) that had the TSocket interface, and that release didn't
+ provide any incentive to upgrade an older program to use TSocket,
+ so there may be few or no users of TSocket.
+============================================================================*/
+
+#include "xmlrpc-c/abyss.h"
+
+struct _TSocket {
+ uint signature;
+ /* With both background and foreground use of sockets, and
+ background being both fork and pthread, it is very easy to
+ screw up socket lifetime and try to destroy twice. We use
+ this signature to help catch such bugs.
+ */
+
+ /* Exactly one of 'chanSwitchP' and 'channelP' is non-null.
+ That's how you know which of the two varieties of socket this is.
+ */
+ TChanSwitch * chanSwitchP;
+ TChannel * channelP;
+
+ void * channelInfoP; /* Defined only for a channel socket */
+};
+
+void
+SocketCreateChannel(TChannel * const channelP,
+ void * const channelInfoP,
+ TSocket ** const socketPP);
+
+void
+SocketCreateChanSwitch(TChanSwitch * const chanSwitchP,
+ TSocket ** const socketPP);
+
+TChanSwitch *
+SocketGetChanSwitch(TSocket * const socketP);
+
+TChannel *
+SocketGetChannel(TSocket * const socketP);
+
+void *
+SocketGetChannelInfo(TSocket * const socketP);
+
+#endif
+
Added: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/socket_openssl.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/socket_openssl.c Fri May 23 16:56:24 2008
@@ -0,0 +1,640 @@
+/*=============================================================================
+ socket_openssl.c
+===============================================================================
+ This is the implementation of TChanSwitch and TChannel
+ for an SSL (Secure Sockets Layer) connection based on an OpenSSL
+ connection object -- what you create with SSL_new().
+
+ This is just a template for future development. It does not function
+ (or even compile) today.
+
+=============================================================================*/
+
+#include "xmlrpc_config.h"
+
+#include <stdlib.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <errno.h>
+
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#include <openssl/rand.h>
+
+#include "xmlrpc-c/util_int.h"
+#include "xmlrpc-c/string_int.h"
+#include "bool.h"
+#include "mallocvar.h"
+#include "trace.h"
+#include "chanswitch.h"
+#include "channel.h"
+#include "socket.h"
+#include "xmlrpc-c/abyss.h"
+
+#include "socket_openssl.h"
+
+
+
+struct channelOpenSsl {
+/*----------------------------------------------------------------------------
+ The properties/state of a TChannel unique to the OpenSSL variety.
+-----------------------------------------------------------------------------*/
+ SSL * sslP;
+ /* SSL connection handle (such as is created by SSL_new() in
+ the openssl library).
+ */
+ bool userSuppliedConn;
+ /* The SSL connection belongs to the user; we did not create
+ it.
+ */
+};
+
+
+
+static bool
+connected(int const fd) {
+/*----------------------------------------------------------------------------
+ Return TRUE iff the socket on file descriptor 'fd' is in the connected
+ state.
+
+ If 'fd' does not identify a stream socket or we are unable to determine
+ the state of the stream socket, the answer is "false".
+-----------------------------------------------------------------------------*/
+ bool connected;
+ struct sockaddr sockaddr;
+ socklen_t nameLen;
+ int rc;
+
+ nameLen = sizeof(sockaddr);
+
+ rc = getpeername(fd, &sockaddr, &nameLen);
+
+ if (rc == 0)
+ connected = TRUE;
+ else
+ connected = FALSE;
+
+ return connected;
+}
+
+
+
+void
+SocketOpensslInit(const char ** const errorP) {
+
+ SSL_load_error_strings();
+ /* readable error messages, don't call this if memory is tight */
+ SSL_library_init(); /* initialize library */
+
+ /* actions_to_seed_PRNG(); */
+
+ *errorP = NULL;
+}
+
+
+
+void
+SocketOpenSslTerm(void) {
+
+ ERR_free_string();
+
+}
+
+
+
+/*=============================================================================
+ TChannel
+=============================================================================*/
+
+static ChannelDestroyImpl channelDestroy;
+
+static void
+channelDestroy(TChannel * const channelP) {
+
+ struct channelOpenssl * const channelOpensslP = channelP->implP;
+
+ if (!socketUnixP->userSuppliedConn)
+ SSL_shutdown(channelOpensslP->sslP);
+
+ free(channelOpensslP);
+}
+
+
+
+static ChannelWriteImpl channelWrite;
+
+static void
+channelWrite(TChannel * const channelP,
+ const unsigned char * const buffer,
+ uint32_t const len,
+ bool * const failedP) {
+
+ struct channelOpenssl * const channelOpensslP = channelP->implP;
+
+ int bytesLeft;
+ bool error;
+
+ assert(sizeof(int) >= sizeof(len));
+
+ for (bytesLeft = len, error = FALSE;
+ bytesLeft > 0 && !error;
+ ) {
+ int const maxSend = (int)(-1) >> 1;
+
+ int rc;
+
+ rc = SSL_write(channelOpensslP->ssl, &buffer[len-bytesLeft],
+ MIN(maxSend, bytesLeft));
+
+ if (ChannelTraceIsActive) {
+ if (rc <= 0)
+ fprintf(stderr,
+ "Abyss socket: SSL_write() failed. rc=%d (%s)",
+ rc, SSL_get_error(rc));
+ else
+ fprintf(stderr, "Abyss socket: sent %u bytes: '%.*s'\n",
+ rc, rc, &buffer[len-bytesLeft]);
+ }
+ if (rc <= 0)
+ /* 0 means connection closed; < 0 means severe error */
+ error = TRUE;
+ else
+ bytesLeft -= rc;
+ }
+ *failedP = error;
+}
+
+
+
+ChannelReadImpl channelRead;
+
+static void
+channelRead(TChannel * const channelP,
+ unsigned char * const buffer,
+ uint32_t const bufferSize,
+ uint32_t * const bytesReceivedP,
+ bool * const failedP) {
+
+ struct channelOpenssl * const channelOpensslP = channelP->implP;
+
+ int rc;
+ rc = SSL_read(channelOpensslP->sslP, buf, len);
+
+ if (rc < 0) {
+ *failedP = TRUE;
+ if (ChannelTraceIsActive)
+ fprintf(stderr, "Failed to receive data from OpenSSL connection. "
+ "SSL_read() failed with rc %d (%s)\n",
+ rc, SSL_get_error(rc));
+ } else {
+ *failedP = FALSE;
+ *bytesReceivedP = rc;
+
+ if (ChannelTraceIsActive)
+ fprintf(stderr, "Abyss channel: read %u bytes: '%.*s'\n",
+ *bytesReceivedP, (int)(*bytesReceivedP), buffer);
+ }
+}
+
+
+
+static ChannelWaitImpl channelWait;
+
+static void
+channelWait(TChannel * const channelP,
+ bool const waitForRead,
+ bool const waitForWrite,
+ uint32_t const timeoutMs,
+ bool * const readyToReadP,
+ bool * const readyToWriteP,
+ bool * const failedP) {
+/*----------------------------------------------------------------------------
+ See socket_unix.c for an explanation of the purpose of this
+ subroutine.
+
+ We don't actually fulfill that purpose, though, because we don't know
+ how yet. Instead, we return immediately and hope that if Caller
+ subsequently does a read or write, it blocks until it can do its thing.
+-----------------------------------------------------------------------------*/
+
+}
+
+
+
+static ChannelInterruptImpl channelInterrupt;
+
+static void
+channelInterrupt(TChannel * const channelP) {
+/*----------------------------------------------------------------------------
+ Interrupt any waiting that a thread might be doing in channelWait()
+ now or in the future.
+-----------------------------------------------------------------------------*/
+
+ /* This is trivial, since channelWait() doesn't actually wait */
+}
+
+
+
+static struct TChannelVtbl const channelVtbl = {
+ &channelDestroy,
+ &channelWrite,
+ &channelRead,
+ &channelWait,
+ &channelInterrupt,
+ &channelFormatPeerInfo,
+};
+
+
+
+static void
+makeChannelInfo(struct abyss_openssl_chaninfo ** const channelInfoPP,
+ SSL * const sslP,
+ const char ** const errorP) {
+
+ struct abyss_openssl_chaninfo * channelInfoP;
+
+ MALLOCVAR(channelInfoP);
+
+ if (channelInfoP == NULL)
+ xmlrpc_asprintf(errorP, "Unable to allocate memory");
+ else {
+
+ *channelInfoPP = channelInfoP;
+
+ *errorP = NULL;
+ }
+}
+
+
+
+static void
+makeChannelFromSsl(SSL * const sslP,
+ TChannel ** const channelPP,
+ const char ** const errorP) {
+
+ struct channelOpenssl * channelOpensslP;
+
+ MALLOCVAR(channelOpensslP);
+
+ if (channelOpensslP == NULL)
+ xmlrpc_asprintf(errorP, "Unable to allocate memory for OpenSSL "
+ "socket descriptor");
+ else {
+ TChannel * channelP;
+
+ channelOpensslP->sslP = sslP;
+ channelOpensslP->userSuppliedSsl = TRUE;
+
+ /* This should be ok as far as I can tell */
+ ChannelCreate(&channelVtbl, channelOpensslP, &channelP);
+
+ if (channelP == NULL)
+ xmlrpc_asprintf(errorP, "Unable to allocate memory for "
+ "channel descriptor.");
+ else {
+ *channelPP = channelP;
+ *errorP = NULL;
+ }
+ if (*errorP)
+ free(channelOpensslP);
+ }
+}
+
+
+
+void
+ChannelOpensslCreateSsl(SSL * const sslP,
+ TChannel ** const channelPP,
+ struct abyss_openssl_chaninfo ** const channelInfoPP,
+ const char ** const errorP) {
+
+ assert(sslP);
+
+ makeChannelInfo(channelInfoPP, sslP, errorP);
+ if (!*errorP) {
+ makeChannelFromSsl(ssl, channelPP, errorP);
+
+ if (*errorP) {
+ free(*channelInfoPP);
+ }
+ }
+}
+
+
+
+/*=============================================================================
+ TChanSwitch
+=============================================================================*/
+
+struct opensslSwitch {
+/*----------------------------------------------------------------------------
+ The properties/state of a TChanSwitch uniqe to the OpenSSL variety.
+
+ Note that OpenSSL deals only in connected sockets, so this switch
+ doesn't really have anything to do with OpenSSL except that it
+ creates OpenSSL TChannels. The switch is just a POSIX listening
+ socket, and is almost identical to the Abyss Unix channel switch.
+-----------------------------------------------------------------------------*/
+ int fd;
+ /* File descriptor of the POSIX socket (such as is created by
+ socket() in the C library) for the socket.
+ */
+ bool userSuppliedFd;
+ /* The file descriptor and associated POSIX socket belong to the
+ user; we did not create it.
+ */
+};
+
+
+
+static SwitchDestroyImpl chanSwitchDestroy;
+
+static void
+chanSwitchDestroy(TChanSwitch * const chanSwitchP) {
+
+static void
+chanSwitchDestroy(TChanSwitch * const chanSwitchP) {
+
+ struct opensslSwitch * const opensslSwitchP = chanSwitchP->implP;
+
+ if (!opensslSwitchP->userSuppliedFd)
+ close(opensslSwitchP->fd);
+
+ free(opensslSwitchP);
+}
+
+
+
+static SwitchListenImpl chanSwitchListen;
+
+static void
+chanSwitchListen(TChanSwitch * const chanSwitchP,
+ uint32_t const backlog,
+ const char ** const errorP) {
+
+ struct opensslSwitch * const opensslSwitchP = chanSwitchP->implP;
+
+ int32_t const minus1 = -1;
+
+ int rc;
+
+ /* Disable the Nagle algorithm to make persistant connections faster */
+
+ setsockopt(opensslSwitchP->fd, IPPROTO_TCP, TCP_NODELAY,
+ &minus1, sizeof(minus1));
+
+ rc = listen(opensslSwitchP->fd, backlog);
+
+ if (rc == -1)
+ xmlrpc_asprintf(errorP, "listen() failed with errno %d (%s)",
+ errno, strerror(errno));
+ else
+ *errorP = NULL;
+}
+
+
+
+static SwitchAcceptImpl chanSwitchAccept;
+
+static void
+chanSwitchAccept(TChanSwitch * const chanSwitchP,
+ TChannel ** const channelPP,
+ void ** const channelInfoPP,
+ const char ** const errorP) {
+/*----------------------------------------------------------------------------
+ Accept a connection via the channel switch *chanSwitchP. Return as
+ *channelPP the channel for the accepted connection.
+
+ If no connection is waiting at *chanSwitchP, wait until one is.
+
+ If we receive a signal while waiting, return immediately with
+ *channelPP == NULL.
+-----------------------------------------------------------------------------*/
+ struct opensslSwitch * const listenSocketP = chanSwitchP->implP;
+
+ bool interrupted;
+ TChannel * channelP;
+
+ interrupted = FALSE; /* Haven't been interrupted yet */
+ channelP = NULL; /* No connection yet */
+ *errorP = NULL; /* No error yet */
+
+ while (!channelP && !*errorP && !interrupted) {
+ struct sockaddr peerAddr;
+ socklen_t size = sizeof(peerAddr);
+ int rc;
+
+ rc = accept(listenSocketP->fd, &peerAddr, &size);
+
+ if (rc >= 0) {
+ int const acceptedFd = rc;
+ struct channelOpenssl * opensslChannelP;
+
+ MALLOCVAR(opensslChannelP);
+
+ if (!opensslChannelP)
+ xmlrpc_asprintf(errorP, "Unable to allocate memory");
+ else {
+ struct abyss_openssl_chaninfo * channelInfoP;
+
+ openChannelP->userSuppliedFd = FALSE;
+ TODO("turn connected socket 'acceptedFd' into an OpenSSL "
+ "connection opensslChannelP->sslP");
+
+ makeChannelInfo(&channelInfoP, peerAddr, size, errorP);
+ if (!*errorP) {
+ *channelInfoPP = channelInfoP;
+
+ ChannelCreate(&channelVtbl, opensslChannelP, &channelP);
+ if (!channelP)
+ xmlrpc_asprintf(errorP,
+ "Failed to create TChannel object.");
+ else
+ *errorP = NULL;
+
+ if (*errorP)
+ free(channelInfoP);
+ }
+ if (*errorP)
+ free(opensslChannelP);
+ }
+ if (*errorP)
+ close(acceptedFd);
+ } else if (errno == EINTR)
+ interrupted = TRUE;
+ else
+ xmlrpc_asprintf(errorP, "accept() failed, errno = %d (%s)",
+ errno, strerror(errno));
+ }
+ *channelPP = channelP;
+}
+
+
+
+static SwitchInterruptImpl chanSwitchInterrupt;
+
+static void
+chanSwitchInterrupt(TChanSwitch * const chanSwitchP) {
+/*----------------------------------------------------------------------------
+ Interrupt any waiting that a thread might be doing in chanSwitchAccept()
+ now or in the future.
+
+ Actually, this is a no-op, since we don't yet know how to accomplish
+ that.
+-----------------------------------------------------------------------------*/
+
+}
+
+
+
+static struct TChanSwitchVtbl const chanSwitchVtbl = {
+ &chanSwitchDestroy,
+ &chanSwitchListen,
+ &chanSwitchAccept,
+};
+
+
+
+static void
+setSocketOptions(int const fd,
+ const char ** const errorP) {
+
+ int32_t n = 1;
+ int rc;
+
+ rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&n, sizeof(n));
+
+ if (rc < 0)
+ xmlrpc_asprintf(errorP, "Failed to set socket options. "
+ "setsockopt() failed with errno %d (%s)",
+ errno, strerror(errno));
+ else
+ *errorP = NULL;
+}
+
+
+
+static void
+bindSocketToPort(int const fd,
+ struct in_addr * const addrP,
+ uint16_t const portNumber,
+ const char ** const errorP) {
+
+ struct sockaddr_in name;
+ int rc;
+
+ name.sin_family = AF_INET;
+ name.sin_port = htons(portNumber);
+ if (addrP)
+ name.sin_addr = *addrP;
+ else
+ name.sin_addr.s_addr = INADDR_ANY;
+
+ rc = bind(fd, (struct sockaddr *)&name, sizeof(name));
+
+ if (rc == -1)
+ xmlrpc_asprintf(errorP, "Unable to bind socket to port number %hu. "
+ "bind() failed with errno %d (%s)",
+ portNumber, errno, strerror(errno));
+ else
+ *errorP = NULL;
+}
+
+
+
+void
+ChanSwitchOpensslCreate(unsigned short const portNumber,
+ TChanSwitch ** const chanSwitchPP,
+ const char ** const errorP) {
+/*----------------------------------------------------------------------------
+ Create an OpenSSL-based channel switch.
+
+ Use an IP socket.
+
+ Set the socket's local address so that a subsequent "listen" will listen
+ on all IP addresses, port number 'portNumber'.
+-----------------------------------------------------------------------------*/
+ struct opensslSwitch * opensslSwitchP;
+
+ MALLOCVAR(opensslSwitchP);
+
+ if (!opensslSwitchP)
+ xmlrpc_asprintf(errorP, "Unable to allocate memory for Openssl "
+ "channel switch descriptor structure.");
+ else {
+ int rc;
+ rc = socket(AF_INET, SOCK_STREAM, 0);
+ if (rc < 0)
+ xmlrpc_asprintf(errorP, "socket() failed with errno %d (%s)",
+ errno, strerror(errno));
+ else {
+ opensslSwitchP->fd = rc;
+ opensslSwitchP->userSuppliedFd = FALSE;
+
+ setSocketOptions(opensslSwitchP->fd, errorP);
+ if (!*errorP) {
+ bindSocketToPort(opensslSwitchP->fd, NULL, portNumber, errorP);
+
+ if (!*errorP)
+ ChanSwitchCreate(&chanSwitchVtbl, opensslSwitchP,
+ chanSwitchPP);
+ }
+ if (*errorP)
+ close(opensslSwitchP->fd);
+ }
+ if (*errorP)
+ free(opensslSwitchP);
+ }
+}
+
+
+
+void
+ChanSwitchOpensslCreateFd(int const fd,
+ TChanSwitch ** const chanSwitchPP,
+ const char ** const errorP) {
+/*----------------------------------------------------------------------------
+ Create an OpenSSL-based channel switch, based on a POSIX socket that
+ is in listen state.
+-----------------------------------------------------------------------------*/
+ struct opensslSwitch * opensslSwitchP;
+
+ if (connected(fd))
+ xmlrpc_asprintf(errorP,
+ "Socket (file descriptor %d) is in connected "
+ "state.", fd);
+ else {
+ MALLOCVAR(opensslSwitchP);
+
+ if (opensslSwitchP == NULL)
+ xmlrpc_asprintf(errorP, "unable to allocate memory for Openssl "
+ "channel switch descriptor.");
+ else {
+ TChanSwitch * chanSwitchP;
+
+ opensslSwitchP->fd = fd;
+ opensslSwitchP->userSuppliedFd = TRUE;
+
+ ChanSwitchCreate(&chanSwitchVtbl, opensslSwitchP, &chanSwitchP);
+
+ if (chanSwitchP == NULL)
+ xmlrpc_asprintf(errorP, "Unable to allocate memory for "
+ "channel switch descriptor");
+ else {
+ *chanSwitchPP = chanSwitchP;
+ *errorP = NULL;
+ }
+ if (*errorP)
+ free(opensslSwitchP);
+ }
+ }
+}
Added: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/socket_unix.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/socket_unix.c Fri May 23 16:56:24 2008
@@ -0,0 +1,951 @@
+/*=============================================================================
+ socket_unix.c
+===============================================================================
+ This is the implementation of TChanSwitch and TChannel (and
+ obsolete TSocket) for a standard Unix (POSIX)
+ stream socket -- what you create with a socket() C library call.
+=============================================================================*/
+
+#include "xmlrpc_config.h"
+
+#include <stdlib.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <poll.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <errno.h>
+
+#if HAVE_SYS_FILIO_H
+ #include <sys/filio.h>
+#endif
+
+#include "c_util.h"
+#include "int.h"
+#include "xmlrpc-c/util_int.h"
+#include "xmlrpc-c/string_int.h"
+#include "mallocvar.h"
+#include "trace.h"
+#include "chanswitch.h"
+#include "channel.h"
+#include "socket.h"
+#include "xmlrpc-c/abyss.h"
+
+#include "socket_unix.h"
+
+
+
+typedef struct {
+ int interruptorFd;
+ int interrupteeFd;
+} interruptPipe;
+
+
+
+static void
+initInterruptPipe(interruptPipe * const pipeP,
+ const char ** const errorP) {
+
+ int pipeFd[2];
+ int rc;
+
+ rc = pipe(pipeFd);
+
+ if (rc != 0)
+ xmlrpc_asprintf(errorP, "Unable to create a pipe to use to interrupt "
+ "waits. pipe() failed with errno %d (%s)",
+ errno, strerror(errno));
+ else {
+ *errorP = NULL;
+ pipeP->interruptorFd = pipeFd[1];
+ pipeP->interrupteeFd = pipeFd[0];
+ }
+}
+
+
+
+static void
+termInterruptPipe(interruptPipe const pipe) {
+
+ close(pipe.interruptorFd);
+ close(pipe.interrupteeFd);
+}
+
+
+
+struct socketUnix {
+/*----------------------------------------------------------------------------
+ The properties/state of a TChanSwitch or TChannel unique to the
+ Unix variety.
+-----------------------------------------------------------------------------*/
+ int fd;
+ /* File descriptor of the POSIX socket (such as is created by
+ socket() in the C library) for the socket.
+ */
+ bool userSuppliedFd;
+ /* The file descriptor and associated POSIX socket belong to the
+ user; we did not create it.
+ */
+ interruptPipe interruptPipe;
+};
+
+
+
+static bool
+connected(int const fd) {
+/*----------------------------------------------------------------------------
+ Return TRUE iff the socket on file descriptor 'fd' is in the connected
+ state.
+
+ If 'fd' does not identify a stream socket or we are unable to determine
+ the state of the stream socket, the answer is "false".
+-----------------------------------------------------------------------------*/
+ bool connected;
+ struct sockaddr sockaddr;
+ socklen_t nameLen;
+ int rc;
+
+ nameLen = sizeof(sockaddr);
+
+ rc = getpeername(fd, &sockaddr, &nameLen);
+
+ if (rc == 0)
+ connected = TRUE;
+ else
+ connected = FALSE;
+
+ return connected;
+}
+
+
+
+void
+SocketUnixInit(const char ** const errorP) {
+
+ *errorP = NULL;
+}
+
+
+
+void
+SocketUnixTerm(void) {
+
+}
+
+
+
+/*=============================================================================
+ TChannel
+=============================================================================*/
+
+static void
+channelDestroy(TChannel * const channelP) {
+
+ struct socketUnix * const socketUnixP = channelP->implP;
+
+ termInterruptPipe(socketUnixP->interruptPipe);
+
+ if (!socketUnixP->userSuppliedFd)
+ close(socketUnixP->fd);
+
+ free(socketUnixP);
+}
+
+
+
+static ChannelWriteImpl channelWrite;
+
+static void
+channelWrite(TChannel * const channelP,
+ const unsigned char * const buffer,
+ uint32_t const len,
+ bool * const failedP) {
+
+ struct socketUnix * const socketUnixP = channelP->implP;
+
+ size_t bytesLeft;
+ bool error;
+
+ assert(sizeof(size_t) >= sizeof(len));
+
+ for (bytesLeft = len, error = FALSE;
+ bytesLeft > 0 && !error;
+ ) {
+ size_t const maxSend = (size_t)(-1) >> 1;
+
+ ssize_t rc;
+
+ rc = send(socketUnixP->fd, &buffer[len-bytesLeft],
+ MIN(maxSend, bytesLeft), 0);
+
+ if (ChannelTraceIsActive) {
+ if (rc < 0)
+ fprintf(stderr, "Abyss channel: send() failed. errno=%d (%s)",
+ errno, strerror(errno));
+ else if (rc == 0)
+ fprintf(stderr, "Abyss channel: send() failed. "
+ "Socket closed.\n");
+ else
+ fprintf(stderr, "Abyss channel: sent %u bytes: '%.*s'\n",
+ rc, rc, &buffer[len-bytesLeft]);
+ }
+ if (rc <= 0)
+ /* 0 means connection closed; < 0 means severe error */
+ error = TRUE;
+ else
+ bytesLeft -= rc;
+ }
+ *failedP = error;
+}
+
+
+
+static ChannelReadImpl channelRead;
+
+static void
+channelRead(TChannel * const channelP,
+ unsigned char * const buffer,
+ uint32_t const bufferSize,
+ uint32_t * const bytesReceivedP,
+ bool * const failedP) {
+
+ struct socketUnix * const socketUnixP = channelP->implP;
+
+ int rc;
+ rc = recv(socketUnixP->fd, buffer, bufferSize, 0);
+
+ if (rc < 0) {
+ *failedP = TRUE;
+ if (ChannelTraceIsActive)
+ fprintf(stderr, "Abyss channel: "
+ "Failed to receive data from socket. "
+ "recv() failed with errno %d (%s)\n",
+ errno, strerror(errno));
+ } else {
+ *failedP = FALSE;
+ *bytesReceivedP = rc;
+
+ if (ChannelTraceIsActive)
+ fprintf(stderr, "Abyss channel: read %u bytes: '%.*s'\n",
+ *bytesReceivedP, (int)(*bytesReceivedP), buffer);
+ }
+}
+
+
+
+static ChannelWaitImpl channelWait;
+
+static void
+channelWait(TChannel * const channelP,
+ bool const waitForRead,
+ bool const waitForWrite,
+ uint32_t const timeoutMs,
+ bool * const readyToReadP,
+ bool * const readyToWriteP,
+ bool * const failedP) {
+/*----------------------------------------------------------------------------
+ Wait for the channel to be immediately readable or writable.
+
+ Readable means there is at least one byte of data to read or the
+ partner has disconnected. Writable means the channel will take at
+ least one byte of data to send or the partner has disconnected.
+
+ 'waitForRead' and 'waitForWrite' determine which of these
+ conditions for which to wait; if both are true, we wait for either
+ one.
+
+ We return before the requested condition holds if 'timeoutMs'
+ milliseconds pass. timoutMs == TIME_INFINITE means infinity.
+
+ We return before the requested condition holds if the process receives
+ (and catches) a signal, but only if it receives that signal a certain
+ time after we start running. (That means this function isn't useful
+ for most purposes).
+
+ Return *readyToReadP == true if the reason for returning is that
+ the channel is immediately readable. *readyToWriteP is analogous
+ for writable. Both may be true.
+
+ Return *failedP true iff we fail to wait for the requested
+ condition because of some unusual problem. Being interrupted by a
+ signal is not a failure.
+
+ If one of these return value pointers is NULL, don't return that
+ value.
+-----------------------------------------------------------------------------*/
+ struct socketUnix * const socketUnixP = channelP->implP;
+
+ /* Design note: some old systems may not have poll(). We're assuming
+ that we don't have to run on any such system. select() is more
+ universal, but can't handle a file descriptor with a high number.
+
+ pselect() and ppoll() would allow us to be properly
+ interruptible by a signal -- we would add a signal mask to our
+ arguments. But ppoll() is fairly rare. pselect() is more
+ common, but in older Linux systems it doesn't actually work.
+ */
+ bool readyToRead, readyToWrite, failed;
+ struct pollfd pollfds[2];
+ int rc;
+
+ pollfds[0].fd = socketUnixP->fd;
+ pollfds[0].events =
+ (waitForRead ? POLLIN : 0) |
+ (waitForWrite ? POLLOUT : 0);
+
+ pollfds[1].fd = socketUnixP->interruptPipe.interrupteeFd;
+ pollfds[1].events = POLLIN;
+
+ rc = poll(pollfds, ARRAY_SIZE(pollfds),
+ timeoutMs == TIME_INFINITE ? -1 : timeoutMs);
+
+ if (rc < 0) {
+ if (errno == EINTR) {
+ failed = FALSE;
+ readyToRead = FALSE;
+ readyToWrite = FALSE;
+ } else {
+ failed = TRUE;
+ readyToRead = FALSE; /* quiet compiler warning */
+ readyToWrite = FALSE; /* quiet compiler warning */
+ }
+ } else {
+ failed = FALSE;
+ readyToRead = !!(pollfds[0].revents & POLLIN);
+ readyToWrite = !!(pollfds[0].revents & POLLOUT);
+ }
+
+ if (failedP)
+ *failedP = failed;
+ if (readyToReadP)
+ *readyToReadP = readyToRead;
+ if (readyToWriteP)
+ *readyToWriteP = readyToWrite;
+}
+
+
+
+static ChannelInterruptImpl channelInterrupt;
+
+static void
+channelInterrupt(TChannel * const channelP) {
+/*----------------------------------------------------------------------------
+ Interrupt any waiting that a thread might be doing in channelWait()
+ now or in the future.
+
+ TODO: Make a way to reset this so that future channelWait()s can once
+ again wait.
+-----------------------------------------------------------------------------*/
+ struct socketUnix * const socketUnixP = channelP->implP;
+ unsigned char const zero[1] = {0u};
+
+ write(socketUnixP->interruptPipe.interruptorFd, &zero, sizeof(zero));
+}
+
+
+
+void
+ChannelUnixGetPeerName(TChannel * const channelP,
+ struct sockaddr ** const sockaddrPP,
+ size_t * const sockaddrLenP,
+ const char ** const errorP) {
+
+ struct socketUnix * const socketUnixP = channelP->implP;
+
+ unsigned char * peerName;
+ socklen_t nameSize;
+
+ nameSize = sizeof(struct sockaddr) + 1;
+
+ peerName = malloc(nameSize);
+
+ if (peerName == NULL)
+ xmlrpc_asprintf(errorP, "Unable to allocate space for peer name");
+ else {
+ int rc;
+ socklen_t nameLen;
+ nameLen = nameSize; /* initial value */
+ rc = getpeername(socketUnixP->fd, (struct sockaddr *)peerName,
+ &nameLen);
+
+ if (rc < 0)
+ xmlrpc_asprintf(errorP, "getpeername() failed. errno=%d (%s)",
+ errno, strerror(errno));
+ else {
+ if (nameLen > nameSize-1)
+ xmlrpc_asprintf(errorP,
+ "getpeername() says the socket name is "
+ "larger than %u bytes, which means it is "
+ "not in the expected format.",
+ nameSize-1);
+ else {
+ *sockaddrPP = (struct sockaddr *)peerName;
+ *sockaddrLenP = nameLen;
+ *errorP = NULL;
+ }
+ }
+ if (*errorP)
+ free(peerName);
+ }
+}
+
+
+
+static ChannelFormatPeerInfoImpl channelFormatPeerInfo;
+
+static void
+channelFormatPeerInfo(TChannel * const channelP,
+ const char ** const peerStringP) {
+
+ struct socketUnix * const socketUnixP = channelP->implP;
+
+ struct sockaddr sockaddr;
+ socklen_t sockaddrLen;
+ int rc;
+
+ sockaddrLen = sizeof(sockaddr);
+
+ rc = getpeername(socketUnixP->fd, &sockaddr, &sockaddrLen);
+
+ if (rc < 0)
+ xmlrpc_asprintf(peerStringP, "?? getpeername() failed. errno=%d (%s)",
+ errno, strerror(errno));
+ else {
+ switch (sockaddr.sa_family) {
+ case AF_INET: {
+ struct sockaddr_in * const sockaddrInP =
+ (struct sockaddr_in *) &sockaddr;
+ if (sockaddrLen < sizeof(*sockaddrInP))
+ xmlrpc_asprintf(peerStringP, "??? getpeername() returned "
+ "the wrong size");
+ else {
+ unsigned char * const ipaddr = (unsigned char *)
+ &sockaddrInP->sin_addr.s_addr;
+ xmlrpc_asprintf(peerStringP, "%u.%u.%u.%u:%hu",
+ ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3],
+ sockaddrInP->sin_port);
+ }
+ } break;
+ default:
+ xmlrpc_asprintf(peerStringP, "??? AF=%u", sockaddr.sa_family);
+ }
+ }
+}
+
+
+
+static struct TChannelVtbl const channelVtbl = {
+ &channelDestroy,
+ &channelWrite,
+ &channelRead,
+ &channelWait,
+ &channelInterrupt,
+ &channelFormatPeerInfo,
+};
+
+
+
+static void
+makeChannelInfo(struct abyss_unix_chaninfo ** const channelInfoPP,
+ struct sockaddr const peerAddr,
+ socklen_t const peerAddrLen,
+ const char ** const errorP) {
+
+ struct abyss_unix_chaninfo * channelInfoP;
+
+ MALLOCVAR(channelInfoP);
+
+ if (channelInfoP == NULL)
+ xmlrpc_asprintf(errorP, "Unable to allocate memory");
+ else {
+ channelInfoP->peerAddrLen = peerAddrLen;
+ channelInfoP->peerAddr = peerAddr;
+
+ *channelInfoPP = channelInfoP;
+
+ *errorP = NULL;
+ }
+}
+
+
+
+static void
+makeChannelFromFd(int const fd,
+ TChannel ** const channelPP,
+ const char ** const errorP) {
+
+ struct socketUnix * socketUnixP;
+
+ MALLOCVAR(socketUnixP);
+
+ if (socketUnixP == NULL)
+ xmlrpc_asprintf(errorP, "Unable to allocate memory for Unix "
+ "channel descriptor");
+ else {
+ TChannel * channelP;
+
+ socketUnixP->fd = fd;
+ socketUnixP->userSuppliedFd = TRUE;
+
+ initInterruptPipe(&socketUnixP->interruptPipe, errorP);
+
+ if (!*errorP) {
+ ChannelCreate(&channelVtbl, socketUnixP, &channelP);
+
+ if (channelP == NULL)
+ xmlrpc_asprintf(errorP, "Unable to allocate memory for "
+ "channel descriptor.");
+ else {
+ *channelPP = channelP;
+ *errorP = NULL;
+ }
+ if (*errorP)
+ termInterruptPipe(socketUnixP->interruptPipe);
+ }
+ if (*errorP)
+ free(socketUnixP);
+ }
+}
+
+
+
+void
+ChannelUnixCreateFd(int const fd,
+ TChannel ** const channelPP,
+ struct abyss_unix_chaninfo ** const channelInfoPP,
+ const char ** const errorP) {
+
+ struct sockaddr peerAddr;
+ socklen_t peerAddrLen;
+ int rc;
+
+ peerAddrLen = sizeof(peerAddrLen);
+
+ rc = getpeername(fd, &peerAddr, &peerAddrLen);
+
+ if (rc != 0) {
+ if (errno == ENOTCONN)
+ xmlrpc_asprintf(errorP, "Socket on file descriptor %d is not in "
+ "connected state.", fd);
+ else
+ xmlrpc_asprintf(errorP, "getpeername() failed on fd %d. "
+ "errno=%d (%s)", fd, errno, strerror(errno));
+ } else {
+ makeChannelInfo(channelInfoPP, peerAddr, peerAddrLen, errorP);
+ if (!*errorP) {
+ makeChannelFromFd(fd, channelPP, errorP);
+
+ if (*errorP)
+ free(*channelInfoPP);
+ }
+ }
+}
+
+
+
+/*=============================================================================
+ TChanSwitch
+=============================================================================*/
+
+static SwitchDestroyImpl chanSwitchDestroy;
+
+static void
+chanSwitchDestroy(TChanSwitch * const chanSwitchP) {
+
+ struct socketUnix * const socketUnixP = chanSwitchP->implP;
+
+ termInterruptPipe(socketUnixP->interruptPipe);
+
+ if (!socketUnixP->userSuppliedFd)
+ close(socketUnixP->fd);
+
+ free(socketUnixP);
+}
+
+
+
+static SwitchListenImpl chanSwitchListen;
+
+static void
+chanSwitchListen(TChanSwitch * const chanSwitchP,
+ uint32_t const backlog,
+ const char ** const errorP) {
+
+ struct socketUnix * const socketUnixP = chanSwitchP->implP;
+
+ int32_t const minus1 = -1;
+
+ int rc;
+
+ /* Disable the Nagle algorithm to make persistant connections faster */
+
+ setsockopt(socketUnixP->fd, IPPROTO_TCP, TCP_NODELAY,
+ &minus1, sizeof(minus1));
+
+ rc = listen(socketUnixP->fd, backlog);
+
+ if (rc == -1)
+ xmlrpc_asprintf(errorP, "listen() failed with errno %d (%s)",
+ errno, strerror(errno));
+ else
+ *errorP = NULL;
+}
+
+
+
+static void
+waitForConnection(struct socketUnix * const listenSocketP,
+ bool * const interruptedP,
+ const char ** const errorP) {
+/*----------------------------------------------------------------------------
+ Wait for the listening socket to have a connection ready to accept.
+
+ We return before the requested condition holds if the process receives
+ (and catches) a signal, but only if it receives that signal a certain
+ time after we start running. (That means this function isn't useful
+ for most purposes).
+
+ Return *interruptedP == true if we return before there is a connection
+ ready to accept.
+-----------------------------------------------------------------------------*/
+ struct pollfd pollfds[2];
+ int rc;
+
+ pollfds[0].fd = listenSocketP->fd;
+ pollfds[0].events = POLLIN;
+
+ pollfds[1].fd = listenSocketP->interruptPipe.interrupteeFd;
+ pollfds[1].events = POLLIN;
+
+ rc = poll(pollfds, ARRAY_SIZE(pollfds), -1);
+
+ if (rc < 0) {
+ if (errno == EINTR) {
+ *errorP = NULL;
+ *interruptedP = TRUE;
+ } else {
+ xmlrpc_asprintf(errorP, "poll() failed, errno = %d (%s)",
+ errno, strerror(errno));
+ *interruptedP = FALSE; /* quiet compiler warning */
+ }
+ } else {
+ *errorP = NULL;
+ *interruptedP = !(pollfds[0].revents & POLLIN);
+ }
+}
+
+
+
+static void
+createChannelForAccept(int const acceptedFd,
+ struct sockaddr const peerAddr,
+ TChannel ** const channelPP,
+ void ** const channelInfoPP,
+ const char ** const errorP) {
+/*----------------------------------------------------------------------------
+ Make a channel object (TChannel) out of a socket just created by
+ accept() on a listening socket -- i.e. a socket for a client connection.
+
+ 'acceptedFd' is the file descriptor of the socket.
+
+ 'peerAddr' is the address of the client, from accept().
+-----------------------------------------------------------------------------*/
+ struct socketUnix * acceptedSocketP;
+
+ MALLOCVAR(acceptedSocketP);
+
+ if (!acceptedSocketP)
+ xmlrpc_asprintf(errorP, "Unable to allocate memory");
+ else {
+ struct abyss_unix_chaninfo * channelInfoP;
+ acceptedSocketP->fd = acceptedFd;
+ acceptedSocketP->userSuppliedFd = FALSE;
+
+ makeChannelInfo(&channelInfoP, peerAddr, sizeof(peerAddr), errorP);
+ if (!*errorP) {
+ TChannel * channelP;
+
+ ChannelCreate(&channelVtbl, acceptedSocketP, &channelP);
+ if (!channelP)
+ xmlrpc_asprintf(errorP,
+ "Failed to create TChannel object.");
+ else {
+ *errorP = NULL;
+ *channelPP = channelP;
+ *channelInfoPP = channelInfoP;
+ }
+ if (*errorP)
+ free(channelInfoP);
+ }
+ if (*errorP)
+ free(acceptedSocketP);
+ }
+}
+
+
+
+static SwitchAcceptImpl chanSwitchAccept;
+
+static void
+chanSwitchAccept(TChanSwitch * const chanSwitchP,
+ TChannel ** const channelPP,
+ void ** const channelInfoPP,
+ const char ** const errorP) {
+/*----------------------------------------------------------------------------
+ Accept a connection via the channel switch *chanSwitchP. Return as
+ *channelPP the channel for the accepted connection.
+
+ If no connection is waiting at *chanSwitchP, wait until one is.
+
+ If we receive a signal while waiting, return immediately with
+ *channelPP == NULL.
+-----------------------------------------------------------------------------*/
+ struct socketUnix * const listenSocketP = chanSwitchP->implP;
+
+ bool interrupted;
+ TChannel * channelP;
+
+ interrupted = FALSE; /* Haven't been interrupted yet */
+ channelP = NULL; /* No connection yet */
+ *errorP = NULL; /* No error yet */
+
+ while (!channelP && !*errorP && !interrupted) {
+
+ waitForConnection(listenSocketP, &interrupted, errorP);
+
+ if (!*errorP && !interrupted) {
+ struct sockaddr peerAddr;
+ socklen_t size = sizeof(peerAddr);
+ int rc;
+
+ rc = accept(listenSocketP->fd, &peerAddr, &size);
+
+ if (rc >= 0) {
+ int const acceptedFd = rc;
+
+ createChannelForAccept(acceptedFd, peerAddr,
+ &channelP, channelInfoPP, errorP);
+
+ if (*errorP)
+ close(acceptedFd);
+ } else if (errno == EINTR)
+ interrupted = TRUE;
+ else
+ xmlrpc_asprintf(errorP, "accept() failed, errno = %d (%s)",
+ errno, strerror(errno));
+ }
+ }
+ *channelPP = channelP;
+}
+
+
+
+static SwitchInterruptImpl chanSwitchInterrupt;
+
+static void
+chanSwitchInterrupt(TChanSwitch * const chanSwitchP) {
+/*----------------------------------------------------------------------------
+ Interrupt any waiting that a thread might be doing in chanSwitchAccept()
+ now or in the future.
+
+ TODO: Make a way to reset this so that future chanSwitchAccept()s can once
+ again wait.
+-----------------------------------------------------------------------------*/
+ struct socketUnix * const listenSocketP = chanSwitchP->implP;
+
+ unsigned char const zero[1] = {0u};
+
+ write(listenSocketP->interruptPipe.interruptorFd, &zero, sizeof(zero));
+}
+
+
+
+static struct TChanSwitchVtbl const chanSwitchVtbl = {
+ &chanSwitchDestroy,
+ &chanSwitchListen,
+ &chanSwitchAccept,
+ &chanSwitchInterrupt,
+};
+
+
+
+static void
+createChanSwitch(int const fd,
+ bool const userSuppliedFd,
+ TChanSwitch ** const chanSwitchPP,
+ const char ** const errorP) {
+
+ struct socketUnix * socketUnixP;
+
+ assert(!connected(fd));
+
+ MALLOCVAR(socketUnixP);
+
+ if (socketUnixP == NULL)
+ xmlrpc_asprintf(errorP, "unable to allocate memory for Unix "
+ "channel switch descriptor.");
+ else {
+ TChanSwitch * chanSwitchP;
+
+ socketUnixP->fd = fd;
+ socketUnixP->userSuppliedFd = userSuppliedFd;
+
+ initInterruptPipe(&socketUnixP->interruptPipe, errorP);
+
+ if (!*errorP) {
+ ChanSwitchCreate(&chanSwitchVtbl, socketUnixP, &chanSwitchP);
+ if (*errorP)
+ termInterruptPipe(socketUnixP->interruptPipe);
+
+ if (chanSwitchP == NULL)
+ xmlrpc_asprintf(errorP, "Unable to allocate memory for "
+ "channel switch descriptor");
+ else {
+ *chanSwitchPP = chanSwitchP;
+ *errorP = NULL;
+ }
+ }
+ if (*errorP)
+ free(socketUnixP);
+ }
+}
+
+
+
+static void
+setSocketOptions(int const fd,
+ const char ** const errorP) {
+
+ int32_t n = 1;
+ int rc;
+
+ rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&n, sizeof(n));
+
+ if (rc < 0)
+ xmlrpc_asprintf(errorP, "Failed to set socket options. "
+ "setsockopt() failed with errno %d (%s)",
+ errno, strerror(errno));
+ else
+ *errorP = NULL;
+}
+
+
+
+static void
+bindSocketToPort(int const fd,
+ struct in_addr * const addrP,
+ uint16_t const portNumber,
+ const char ** const errorP) {
+
+ struct sockaddr_in name;
+ int rc;
+
+ name.sin_family = AF_INET;
+ name.sin_port = htons(portNumber);
+ if (addrP)
+ name.sin_addr = *addrP;
+ else
+ name.sin_addr.s_addr = INADDR_ANY;
+
+ rc = bind(fd, (struct sockaddr *)&name, sizeof(name));
+
+ if (rc == -1)
+ xmlrpc_asprintf(errorP, "Unable to bind socket to port number %hu. "
+ "bind() failed with errno %d (%s)",
+ portNumber, errno, strerror(errno));
+ else
+ *errorP = NULL;
+}
+
+
+
+void
+ChanSwitchUnixCreate(unsigned short const portNumber,
+ TChanSwitch ** const chanSwitchPP,
+ const char ** const errorP) {
+/*----------------------------------------------------------------------------
+ Create a POSIX-socket-based channel switch.
+
+ Use an IP socket.
+
+ Set the socket's local address so that a subsequent "listen" will listen
+ on all IP addresses, port number 'portNumber'.
+-----------------------------------------------------------------------------*/
+ int rc;
+ rc = socket(AF_INET, SOCK_STREAM, 0);
+ if (rc < 0)
+ xmlrpc_asprintf(errorP, "socket() failed with errno %d (%s)",
+ errno, strerror(errno));
+ else {
+ int const socketFd = rc;
+
+ setSocketOptions(socketFd, errorP);
+ if (!*errorP) {
+ bindSocketToPort(socketFd, NULL, portNumber, errorP);
+
+ if (!*errorP) {
+ bool const userSupplied = false;
+ createChanSwitch(socketFd, userSupplied, chanSwitchPP, errorP);
+ }
+ }
+ if (*errorP)
+ close(socketFd);
+ }
+}
+
+
+
+void
+ChanSwitchUnixCreateFd(int const fd,
+ TChanSwitch ** const chanSwitchPP,
+ const char ** const errorP) {
+
+ if (connected(fd))
+ xmlrpc_asprintf(errorP,
+ "Socket (file descriptor %d) is in connected "
+ "state.", fd);
+ else {
+ bool const userSupplied = true;
+ createChanSwitch(fd, userSupplied, chanSwitchPP, errorP);
+ }
+}
+
+
+
+/*=============================================================================
+ obsolete TSocket interface
+=============================================================================*/
+
+
+void
+SocketUnixCreateFd(int const fd,
+ TSocket ** const socketPP) {
+
+ TSocket * socketP;
+ const char * error;
+
+ if (connected(fd)) {
+ TChannel * channelP;
+ struct abyss_unix_chaninfo * channelInfoP;
+ ChannelUnixCreateFd(fd, &channelP, &channelInfoP, &error);
+ if (!error)
+ SocketCreateChannel(channelP, channelInfoP, &socketP);
+ } else {
+ TChanSwitch * chanSwitchP;
+ ChanSwitchUnixCreateFd(fd, &chanSwitchP, &error);
+ if (!error)
+ SocketCreateChanSwitch(chanSwitchP, &socketP);
+ }
+ if (error) {
+ *socketPP = NULL;
+ xmlrpc_strfree(error);
+ } else
+ *socketPP = socketP;
+}
Added: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/socket_unix.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/socket_unix.h Fri May 23 16:56:24 2008
@@ -0,0 +1,14 @@
+#ifndef SOCKET_UNIX_H_INCLUDED
+#define SOCKET_UNIX_H_INCLUDED
+
+#include <sys/socket.h>
+
+#include <xmlrpc-c/abyss.h>
+
+void
+SocketUnixInit(const char ** const errorP);
+
+void
+SocketUnixTerm(void);
+
+#endif
Added: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/socket_win.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/socket_win.c Fri May 23 16:56:24 2008
@@ -0,0 +1,940 @@
+/*=============================================================================
+ socket_win.c
+===============================================================================
+ This is the implementation of TChanSwitch and TChannel
+ for a Winsock socket.
+=============================================================================*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <winsock.h>
+#include <errno.h>
+
+#include "xmlrpc_config.h"
+#include "xmlrpc-c/util_int.h"
+#include "xmlrpc-c/string_int.h"
+#include "mallocvar.h"
+#include "trace.h"
+#include "chanswitch.h"
+#include "channel.h"
+#include "socket.h"
+#include "xmlrpc-c/abyss.h"
+
+#include "socket_win.h"
+
+#ifndef socklen_t
+typedef int socklen_t;
+#endif
+
+/* =============================================================
+ Provided nice error strings, NOT available in system errors.
+ ============================================================= */
+
+typedef struct tagSOCKERRS {
+ int err; // WSAGetLastError() value
+ char * desc; // description of error
+} SOCKERR;
+
+/* could/should perhaps be by the actual call,
+ but for now, just one big list, with some repeats
+*/
+
+SOCKERR sSockErr[] = {
+ { WSANOTINITIALISED,
+ "WSANOTINITIALISED - "
+ "WSAStartup must be called before using this function." },
+ { WSAENETDOWN,
+ "WSAENETDOWN - "
+ "The network subsystem has failed." },
+ { WSAEACCES,
+ "WSAEACCES - "
+ "Attempt to connect datagram socket to broadcast address failed "
+ "because setsockopt option SO_BROADCAST is not enabled." },
+ { WSAEADDRINUSE,
+ "WSAEADDRINUSE - "
+ "A process on the computer is already bound to the same fully-qualified "
+ "address and the socket has not been marked to allow address reuse with "
+ "SO_REUSEADDR. For example, the IP address and port are bound in the "
+ "af_inet case). (See the SO_REUSEADDR socket option under setsockopt.)" },
+ { WSAEADDRNOTAVAIL,
+ "WSAEADDRNOTAVAIL - "
+ "The specified address is not a valid address for this computer." },
+ { WSAEFAULT,
+ "WSAEFAULT - "
+ "The name or namelen parameter is not a valid part of the user "
+ "address space, the namelen parameter is too small, the name parameter "
+ "contains an incorrect address format for the associated "
+ "address family, or the first two bytes of the memory block "
+ "specified by name does not match the address family associated with "
+ "the socket descriptor s." },
+ { WSAEINPROGRESS,
+ "WSAEINPROGRESS - "
+ "A blocking Windows Sockets 1.1 call is in progress, or the "
+ "service provider is still processing a callback function." },
+ { WSAEINVAL,
+ "WSAEINVAL - "
+ "The socket is already bound to an address." },
+ { WSAENOBUFS,
+ "WSAENOBUFS - "
+ "Not enough buffers available, too many connections." },
+ { WSAENOTSOCK,
+ "WSAENOTSOCK - "
+ "The descriptor is not a socket." },
+
+ // setsocketopt
+ { WSAENETRESET,
+ "WSAENETRESET - "
+ "Connection has timed out when SO_KEEPALIVE is set." },
+ { WSAENOPROTOOPT,
+ "WSAENOPROTOOPT - "
+ "The option is unknown or the specified provider "
+ "or socket is not capable of implementing it "
+ "(see SO_GROUP_PRIORITY limitations)." },
+ { WSAENOTCONN,
+ "WSAENOTCONN - "
+ "Connection has been reset when SO_KEEPALIVE is set." },
+
+ // WSAStartup
+ { WSASYSNOTREADY,
+ "WSASYSNOTREADY - "
+ "The underlying network subsystem is not ready for "
+ "network communication." },
+ { WSAVERNOTSUPPORTED,
+ "WSAVERNOTSUPPORTED - "
+ "The version of Windows Sockets function requested is not provided "
+ "by this particular Windows Sockets implementation." },
+ { WSAEINPROGRESS,
+ "WSAEINPROGRESS - "
+ "A blocking Windows Sockets 1.1 operation is in progress." },
+ { WSAEPROCLIM,
+ "WSAEPROCLIM - "
+ "Limit on the number of tasks allowed by the Windows Sockets "
+ "implementation has been reached." },
+ { WSAEFAULT,
+ "WSAEFAULT - "
+ "The lpWSAData is not a valid pointer." },
+ // listen
+ { WSANOTINITIALISED,
+ "WSANOTINITIALISED - "
+ "A successful WSAStartup call must occur before using this function." },
+ { WSAENETDOWN,
+ "WSAENETDOWN - "
+ "The network subsystem has failed." },
+ { WSAEADDRINUSE,
+ "WSAEADDRINUSE - "
+ "The socket's local address is already in use and the socket "
+ "was not marked to allow address reuse with SO_REUSEADDR. "
+ "This error usually occurs during execution of the bind function, "
+ "but could be delayed until this function if the bind was to "
+ "a partially wildcard address (involving ADDR_ANY) "
+ "and if a specific address needs to be committed at the time "
+ "of this function call." },
+ { WSAEINPROGRESS,
+ "WSAEINPROGRESS - "
+ "A blocking Windows Sockets 1.1 call is in progress, "
+ "or the service provider is still processing a callback function." },
+ { WSAEINVAL,
+ "WSAEINVAL - "
+ "The socket has not been bound with bind." },
+ { WSAEISCONN,
+ "WSAEISCONN - "
+ "The socket is already connected." },
+ { WSAEMFILE,
+ "WSAEMFILE - "
+ "No more socket descriptors are available." },
+ { WSAENOBUFS,
+ "WSAENOBUFS - "
+ "No buffer space is available." },
+ { WSAENOTSOCK,
+ "WSAENOTSOCK - "
+ "The descriptor is not a socket." },
+ { WSAEOPNOTSUPP,
+ "WSAEOPNOTSUPP - "
+ "The referenced socket is not of a type that has a listen operation." },
+
+ // getpeername
+ { WSANOTINITIALISED,
+ "WSANOTINITIALISED - "
+ "A successful WSAStartup call must occur before using this function." },
+ { WSAENETDOWN,
+ "WSAENETDOWN - "
+ "The network subsystem has failed." },
+ { WSAEFAULT,
+ "WSAEFAULT - "
+ "The name or the namelen parameter is not a valid part of the "
+ "user address space, or the namelen parameter is too small." },
+ { WSAEINPROGRESS,
+ "WSAEINPROGRESS - "
+ "A blocking Windows Sockets 1.1 call is in progress, "
+ "or the service provider is still processing a callback function." },
+ { WSAENOTCONN,
+ "WSAENOTCONN - "
+ "The socket is not connected." },
+ { WSAENOTSOCK,
+ "WSAENOTSOCK - "
+ "The descriptor is not a socket." },
+
+ // accept
+ { WSANOTINITIALISED,
+ "WSANOTINITIALISED - "
+ "A successful WSAStartup call must occur before using this function." },
+ { WSAENETDOWN,
+ "WSAENETDOWN - "
+ "The network subsystem has failed." },
+ { WSAEFAULT,
+ "WSAEFAULT - "
+ "The addrlen parameter is too small or addr is not a valid part "
+ "of the user address space." },
+ { WSAEINTR,
+ "WSAEINTR - "
+ "A blocking Windows Sockets 1.1 call was canceled through "
+ "WSACancelBlockingCall." },
+ { WSAEINPROGRESS,
+ "WSAEINPROGRESS - "
+ "A blocking Windows Sockets 1.1 call is in progress, "
+ "or the service provider is still processing a callback function." },
+ { WSAEINVAL,
+ "WSAEINVAL - "
+ "The listen function was not invoked prior to accept." },
+ { WSAEMFILE,
+ "WSAEMFILE - "
+ "The queue is nonempty upon entry to accept and "
+ "there are no descriptors available." },
+ { WSAENOBUFS,
+ "WSAENOBUFS - "
+ "No buffer space is available." },
+ { WSAENOTSOCK,
+ "WSAENOTSOCK - "
+ "The descriptor is not a socket." },
+ { WSAEOPNOTSUPP,
+ "WSAEOPNOTSUPP - "
+ "The referenced socket is not a type that offers connection-oriented "
+ "service." },
+ { WSAEWOULDBLOCK,
+ "WSAEWOULDBLOCK - "
+ "The socket is marked as nonblocking and no connections are present "
+ "to be accepted." },
+
+ /* must be last entry */
+ { 0, 0 }
+};
+
+
+
+static const char *
+getWSAError(int const wsaErrno) {
+
+ SOCKERR * pseP;
+
+ pseP = &sSockErr[0]; // initial value
+
+ while (pseP->desc) {
+ if (pseP->err == wsaErrno)
+ return pseP->desc;
+
+ ++pseP;
+ }
+
+ return "(no description available)";
+}
+
+
+
+struct socketWin {
+/*----------------------------------------------------------------------------
+ The properties/state of a TSocket unique to a Unix TSocket.
+-----------------------------------------------------------------------------*/
+ SOCKET winsock;
+ bool userSuppliedWinsock;
+ /* 'socket' was supplied by the user; it belongs to him */
+};
+
+static
+bool
+connected(SOCKET const fd) {
+/*----------------------------------------------------------------------------
+ Return TRUE iff the socket on file descriptor 'fd' is in the connected
+ state.
+ If 'fd' does not identify a stream socket or we are unable to determine
+ the state of the stream socket, the answer is "false".
+-----------------------------------------------------------------------------*/
+ bool connected;
+ struct sockaddr sockaddr;
+ socklen_t nameLen;
+ int rc;
+
+ nameLen = sizeof(sockaddr);
+
+ rc = getpeername(fd, &sockaddr, &nameLen);
+
+ if (rc == 0)
+ connected = TRUE;
+ else
+ connected = FALSE;
+
+ return connected;
+}
+
+
+
+void
+SocketWinInit(const char ** const errorP) {
+
+ WORD wVersionRequested;
+ WSADATA wsaData;
+ int err;
+
+ wVersionRequested = MAKEWORD(1, 0);
+
+ err = WSAStartup(wVersionRequested, &wsaData);
+
+ if (err != 0) {
+ int const lastError = WSAGetLastError();
+ xmlrpc_asprintf(errorP, "WSAStartup() faild with error %d (%s)",
+ lastError, getWSAError(lastError));
+ } else
+ *errorP = NULL;
+}
+
+
+
+void
+SocketWinTerm(void) {
+
+ WSACleanup();
+}
+
+
+
+/*=============================================================================
+ TChannel
+=============================================================================*/
+
+static ChannelDestroyImpl channelDestroy;
+
+static void
+channelDestroy(TChannel * const channelP) {
+
+ struct socketWin * const socketWinP = channelP->implP;
+
+ if (!socketWinP->userSuppliedWinsock)
+ closesocket(socketWinP->winsock);
+
+ free(socketWinP);
+}
+
+
+
+static ChannelWriteImpl channelWrite;
+
+static void
+channelWrite(TChannel * const channelP,
+ const unsigned char * const buffer,
+ uint32_t const len,
+ bool * const failedP) {
+
+ struct socketWin * const socketWinP = channelP->implP;
+
+ size_t bytesLeft;
+ bool error;
+
+ assert(sizeof(size_t) >= sizeof(len));
+
+ for (bytesLeft = len, error = FALSE;
+ bytesLeft > 0 && !error;
+ ) {
+ size_t const maxSend = (size_t)(-1) >> 1;
+
+ int rc;
+
+ rc = send(socketWinP->winsock, &buffer[len-bytesLeft],
+ MIN(maxSend, bytesLeft), 0);
+
+ if (rc <= 0)
+ /* 0 means connection closed; < 0 means severe error */
+ error = TRUE;
+ else
+ bytesLeft -= rc;
+ }
+ *failedP = error;
+}
+
+
+
+static ChannelReadImpl channelRead;
+
+static void
+channelRead(TChannel * const channelP,
+ unsigned char * const buffer,
+ uint32_t const bufferSize,
+ uint32_t * const bytesReceivedP,
+ bool * const failedP) {
+
+ struct socketWin * const socketWinP = channelP->implP;
+
+ int rc;
+ rc = recv(socketWinP->winsock, buffer, bufferSize, 0);
+
+ if (rc < 0) {
+ *failedP = TRUE;
+ } else {
+ *failedP = FALSE;
+ *bytesReceivedP = rc;
+ }
+}
+
+
+
+static ChannelWaitImpl channelWait;
+
+static void
+channelWait(TChannel * const channelP,
+ bool const waitForRead,
+ bool const waitForWrite,
+ uint32_t const timems,
+ bool * const readyToReadP,
+ bool * const readyToWriteP,
+ bool * const failedP) {
+
+ struct socketWin * const socketWinP = channelP->implP;
+
+ fd_set rfds, wfds;
+ TIMEVAL tv;
+ bool failed, readRdy, writeRdy, timedOut;
+
+ FD_ZERO(&rfds);
+ FD_ZERO(&wfds);
+
+ if (waitForRead)
+ FD_SET(socketWinP->winsock, &rfds);
+
+ if (waitForWrite)
+ FD_SET(socketWinP->winsock, &wfds);
+
+ tv.tv_sec = timems / 1000;
+ tv.tv_usec = timems % 1000;
+
+ for (failed = FALSE, readRdy = FALSE, writeRdy = FALSE, timedOut = FALSE;
+ !failed && !readRdy && !writeRdy && !timedOut;
+ ) {
+
+ int rc;
+
+ rc = select(socketWinP->winsock + 1, &rfds, &wfds, NULL,
+ (timems == TIME_INFINITE ? NULL : &tv));
+
+ switch(rc) {
+ case 0:
+ timedOut = TRUE;
+ break;
+ case -1: /* socket error */
+ if (errno != EINTR)
+ failed = TRUE;
+ break;
+ default:
+ if (FD_ISSET(socketWinP->winsock, &rfds))
+ readRdy = TRUE;
+ if (FD_ISSET(socketWinP->winsock, &wfds))
+ writeRdy = TRUE;
+ }
+ }
+
+ if (failedP)
+ *failedP = failed;
+ if (readyToReadP)
+ *readyToReadP = readRdy;
+ if (readyToWriteP)
+ *readyToWriteP = writeRdy;
+}
+
+
+
+static ChannelInterruptImpl channelInterrupt;
+
+static void
+channelInterrupt(TChannel * const channelP) {
+/*----------------------------------------------------------------------------
+ Interrupt any waiting that a thread might be doing in channelWait()
+ now or in the future.
+
+ Actually, this is just a no-op because we don't yet know how to
+ accomplish that.
+-----------------------------------------------------------------------------*/
+
+}
+
+
+
+void
+ChannelWinGetPeerName(TChannel * const channelP,
+ struct sockaddr_in * const inAddrP,
+ const char ** const errorP) {
+
+ struct socketWin * const socketWinP = channelP->implP;
+
+ socklen_t addrlen;
+ int rc;
+ struct sockaddr sockAddr;
+
+ addrlen = sizeof(sockAddr);
+
+ rc = getpeername(socketWinP->winsock, &sockAddr, &addrlen);
+
+ if (rc != 0) {
+ int const lastError = WSAGetLastError();
+ xmlrpc_asprintf(errorP, "getpeername() failed. WSAERROR = %d (%s)",
+ lastError, getWSAError(lastError));
+ } else {
+ if (addrlen != sizeof(sockAddr))
+ xmlrpc_asprintf(errorP, "getpeername() returned a socket address "
+ "of the wrong size: %u. Expected %u",
+ addrlen, sizeof(sockAddr));
+ else {
+ if (sockAddr.sa_family != AF_INET)
+ xmlrpc_asprintf(errorP,
+ "Socket does not use the Inet (IP) address "
+ "family. Instead it uses family %d",
+ sockAddr.sa_family);
+ else {
+ *inAddrP = *(struct sockaddr_in *)&sockAddr;
+
+ *errorP = NULL;
+ }
+ }
+ }
+}
+
+
+
+static ChannelFormatPeerInfoImpl channelFormatPeerInfo;
+
+static void
+channelFormatPeerInfo(TChannel * const channelP,
+ const char ** const peerStringP) {
+
+ struct socketWin * const socketWinP = channelP->implP;
+
+ struct sockaddr sockaddr;
+ socklen_t sockaddrLen;
+ int rc;
+
+ sockaddrLen = sizeof(sockaddr);
+
+ rc = getpeername(socketWinP->winsock, &sockaddr, &sockaddrLen);
+
+ if (rc != 0) {
+ int const lastError = WSAGetLastError();
+ xmlrpc_asprintf(peerStringP, "?? getpeername() failed. "
+ "WSAERROR %d (%s)",
+ lastError, getWSAError(lastError));
+ } else {
+ switch (sockaddr.sa_family) {
+ case AF_INET: {
+ struct sockaddr_in * const sockaddrInP =
+ (struct sockaddr_in *) &sockaddr;
+ if (sockaddrLen < sizeof(*sockaddrInP))
+ xmlrpc_asprintf(peerStringP, "??? getpeername() returned "
+ "the wrong size");
+ else {
+ unsigned char * const ipaddr = (unsigned char *)
+ &sockaddrInP->sin_addr.s_addr;
+ xmlrpc_asprintf(peerStringP, "%u.%u.%u.%u:%hu",
+ ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3],
+ sockaddrInP->sin_port);
+ }
+ } break;
+ default:
+ xmlrpc_asprintf(peerStringP, "??? AF=%u", sockaddr.sa_family);
+ }
+ }
+}
+
+
+
+static struct TChannelVtbl const channelVtbl = {
+ &channelDestroy,
+ &channelWrite,
+ &channelRead,
+ &channelWait,
+ &channelInterrupt,
+ &channelFormatPeerInfo,
+};
+
+
+
+static void
+makeChannelFromWinsock(SOCKET const winsock,
+ TChannel ** const channelPP,
+ const char ** const errorP) {
+
+ struct socketWin * socketWinP;
+
+ MALLOCVAR(socketWinP);
+
+ if (socketWinP == NULL)
+ xmlrpc_asprintf(errorP, "Unable to allocate memory for Windows "
+ "socket descriptor");
+ else {
+ TChannel * channelP;
+
+ socketWinP->winsock = winsock;
+ socketWinP->userSuppliedWinsock = TRUE;
+
+ ChannelCreate(&channelVtbl, socketWinP, &channelP);
+
+ if (channelP == NULL)
+ xmlrpc_asprintf(errorP, "Unable to allocate memory for "
+ "channel descriptor.");
+ else {
+ *channelPP = channelP;
+ *errorP = NULL;
+ }
+ if (*errorP)
+ free(socketWinP);
+ }
+}
+
+
+
+static void
+makeChannelInfo(struct abyss_win_chaninfo ** const channelInfoPP,
+ struct sockaddr const peerAddr,
+ socklen_t const peerAddrLen,
+ const char ** const errorP) {
+
+ struct abyss_win_chaninfo * channelInfoP;
+
+ MALLOCVAR(channelInfoP);
+
+ if (channelInfoP == NULL)
+ xmlrpc_asprintf(errorP, "Unable to allocate memory");
+ else {
+ channelInfoP->peerAddrLen = peerAddrLen;
+ channelInfoP->peerAddr = peerAddr;
+
+ *channelInfoPP = channelInfoP;
+
+ *errorP = NULL;
+ }
+}
+
+
+
+void
+ChannelWinCreateWinsock(SOCKET const fd,
+ TChannel ** const channelPP,
+ struct abyss_win_chaninfo ** const channelInfoPP,
+ const char ** const errorP) {
+
+ struct sockaddr peerAddr;
+ socklen_t peerAddrLen;
+ int rc;
+
+ peerAddrLen = sizeof(peerAddrLen);
+
+ rc = getpeername(fd, &peerAddr, &peerAddrLen);
+
+ if (rc != 0) {
+ int const lastError = WSAGetLastError();
+ if (lastError == WSAENOTCONN) {
+ /* NOTE: This specific string 'not in connected' is
+ required by one of the rpctest suite items, in abyss.c
+ (line 186), hence the separation of the error messages
+ in this case ...
+ */
+ xmlrpc_asprintf(errorP, "Socket on file descriptor %d "
+ "is not in connected state. WSAERROR = %d (%s)",
+ fd, lastError, getWSAError(lastError));
+ } else
+ xmlrpc_asprintf(errorP, "getpeername() failed. WSAERROR = %d (%s)",
+ lastError, getWSAError(lastError));
+ } else {
+ makeChannelInfo(channelInfoPP, peerAddr, peerAddrLen, errorP);
+ if (!*errorP) {
+ makeChannelFromWinsock(fd, channelPP, errorP);
+
+ if (*errorP)
+ free(*channelInfoPP);
+ }
+ }
+}
+
+
+/*=============================================================================
+ TChanSwitch
+=============================================================================*/
+
+static SwitchDestroyImpl chanSwitchDestroy;
+
+void
+chanSwitchDestroy(TChanSwitch * const chanSwitchP) {
+
+ struct socketWin * const socketWinP = chanSwitchP->implP;
+
+ if (!socketWinP->userSuppliedWinsock)
+ closesocket(socketWinP->winsock);
+
+ free(socketWinP);
+}
+
+
+
+static SwitchListenImpl chanSwitchListen;
+
+static void
+chanSwitchListen(TChanSwitch * const chanSwitchP,
+ uint32_t const backlog,
+ const char ** const errorP) {
+
+ struct socketWin * const socketWinP = chanSwitchP->implP;
+
+ int32_t const minus1 = -1;
+
+ int rc;
+
+ /* Disable the Nagle algorithm to make persistant connections faster */
+
+ setsockopt(socketWinP->winsock, IPPROTO_TCP, TCP_NODELAY,
+ (const char *)&minus1, sizeof(minus1));
+
+ rc = listen(socketWinP->winsock, backlog);
+
+ if (rc != 0) {
+ int const lastError = WSAGetLastError();
+ xmlrpc_asprintf(errorP, "setsockopt() failed with WSAERROR %d (%s)",
+ lastError, getWSAError(lastError));
+ } else
+ *errorP = NULL;
+}
+
+
+
+static SwitchAcceptImpl chanSwitchAccept;
+
+static void
+chanSwitchAccept(TChanSwitch * const chanSwitchP,
+ TChannel ** const channelPP,
+ void ** const channelInfoPP,
+ const char ** const errorP) {
+/*----------------------------------------------------------------------------
+ Accept a connection via the channel switch *chanSwitchP. Return as
+ *channelPP the channel for the accepted connection.
+
+ If no connection is waiting at *chanSwitchP, wait until one is.
+
+ If we receive a signal while waiting, return immediately with
+ *channelPP == NULL.
+-----------------------------------------------------------------------------*/
+ struct socketWin * const listenSocketP = chanSwitchP->implP;
+
+ bool interrupted;
+ TChannel * channelP;
+
+ interrupted = FALSE; /* Haven't been interrupted yet */
+ channelP = NULL; /* No connection yet */
+ *errorP = NULL; /* No error yet */
+
+ while (!channelP && !*errorP && !interrupted) {
+ struct sockaddr peerAddr;
+ socklen_t size = sizeof(peerAddr);
+ int rc;
+
+ rc = accept(listenSocketP->winsock, &peerAddr, &size);
+
+ if (rc >= 0) {
+ int const acceptedWinsock = rc;
+ struct socketWin * acceptedSocketP;
+
+ MALLOCVAR(acceptedSocketP);
+
+ if (!acceptedSocketP)
+ xmlrpc_asprintf(errorP, "Unable to allocate memory");
+ else {
+ acceptedSocketP->winsock = acceptedWinsock;
+ acceptedSocketP->userSuppliedWinsock = FALSE;
+
+ *channelInfoPP = NULL;
+
+ ChannelCreate(&channelVtbl, acceptedSocketP, &channelP);
+ if (!channelP)
+ xmlrpc_asprintf(errorP,
+ "Failed to create TChannel object.");
+ else
+ *errorP = NULL;
+
+ if (*errorP)
+ free(acceptedSocketP);
+ }
+ if (*errorP)
+ closesocket(acceptedWinsock);
+ } else if (errno == EINTR)
+ interrupted = TRUE;
+ else
+ xmlrpc_asprintf(errorP, "accept() failed, errno = %d (%s)",
+ errno, strerror(errno));
+ }
+ *channelPP = channelP;
+}
+
+
+
+static SwitchInterruptImpl chanSwitchInterrupt;
+
+static void
+chanSwitchInterrupt(TChanSwitch * const chanSwitchP) {
+/*----------------------------------------------------------------------------
+ Interrupt any waiting that a thread might be doing in chanSwitchAccept()
+ now or in the future.
+
+ Actually, this is just a no-op because we don't yet know how to
+ accomplish that.
+-----------------------------------------------------------------------------*/
+
+}
+
+
+
+static struct TChanSwitchVtbl const chanSwitchVtbl = {
+ &chanSwitchDestroy,
+ &chanSwitchListen,
+ &chanSwitchAccept,
+ &chanSwitchInterrupt,
+};
+
+
+
+static void
+setSocketOptions(SOCKET const fd,
+ const char ** const errorP) {
+
+ int32_t const n = 1;
+
+ int rc;
+
+ rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&n, sizeof(n));
+
+ if (rc != 0) {
+ int const lastError = WSAGetLastError();
+ xmlrpc_asprintf(errorP, "Failed to set socket options. "
+ "setsockopt() failed with WSAERROR %d (%s)",
+ lastError, getWSAError(lastError));
+ } else
+ *errorP = NULL;
+}
+
+
+
+void
+bindSocketToPort(SOCKET const winsock,
+ struct in_addr * const addrP,
+ uint16_t const portNumber,
+ const char ** const errorP) {
+
+ struct sockaddr_in name;
+ int rc;
+
+ ZeroMemory(&name, sizeof(name));
+ name.sin_family = AF_INET;
+ name.sin_port = htons(portNumber);
+ if (addrP)
+ name.sin_addr = *addrP;
+
+ rc = bind(winsock, (struct sockaddr *)&name, sizeof(name));
+
+ if (rc != 0) {
+ int const lastError = WSAGetLastError();
+ xmlrpc_asprintf(errorP, "Unable to bind socket to port number %u. "
+ "bind() failed with WSAERROR %i (%s)",
+ portNumber, lastError, getWSAError(lastError));
+ } else
+ *errorP = NULL;
+}
+
+
+
+void
+ChanSwitchWinCreate(uint16_t const portNumber,
+ TChanSwitch ** const chanSwitchPP,
+ const char ** const errorP) {
+/*----------------------------------------------------------------------------
+ Create a Winsock-based channel switch.
+
+ Set the socket's local address so that a subsequent "listen" will listen
+ on all IP addresses, port number 'portNumber'.
+-----------------------------------------------------------------------------*/
+ struct socketWin * socketWinP;
+
+ MALLOCVAR(socketWinP);
+
+ if (!socketWinP)
+ xmlrpc_asprintf(errorP, "Unable to allocate memory for Windows socket "
+ "descriptor structure.");
+ else {
+ SOCKET winsock;
+
+ winsock = socket(AF_INET, SOCK_STREAM, 0);
+
+ if (winsock == 0 || winsock == INVALID_SOCKET) {
+ int const lastError = WSAGetLastError();
+ xmlrpc_asprintf(errorP, "socket() failed with WSAERROR %d (%s)",
+ lastError, getWSAError(lastError));
+ } else {
+ socketWinP->winsock = winsock;
+ socketWinP->userSuppliedWinsock = FALSE;
+
+ setSocketOptions(socketWinP->winsock, errorP);
+ if (!*errorP) {
+ bindSocketToPort(socketWinP->winsock, NULL, portNumber,
+ errorP);
+ if (!*errorP)
+ ChanSwitchCreate(&chanSwitchVtbl, socketWinP,
+ chanSwitchPP);
+ }
+
+ if (*errorP)
+ closesocket(winsock);
+ }
+ if (*errorP)
+ free(socketWinP);
+ }
+}
+
+
+
+void
+ChanSwitchWinCreateWinsock(SOCKET const winsock,
+ TChanSwitch ** const chanSwitchPP,
+ const char ** const errorP) {
+
+ struct socketWin * socketWinP;
+
+ if (connected(winsock))
+ xmlrpc_asprintf(errorP, "Socket is in connected state.");
+ else {
+ MALLOCVAR(socketWinP);
+
+ if (socketWinP == NULL)
+ xmlrpc_asprintf(errorP, "unable to allocate memory for Windows "
+ "socket descriptor.");
+ else {
+ TChanSwitch * chanSwitchP;
+
+ socketWinP->winsock = winsock;
+ socketWinP->userSuppliedWinsock = TRUE;
+
+ ChanSwitchCreate(&chanSwitchVtbl, socketWinP, &chanSwitchP);
+
+ if (chanSwitchP == NULL)
+ xmlrpc_asprintf(errorP, "Unable to allocate memory for "
+ "channel switch descriptor");
+ else {
+ *chanSwitchPP = chanSwitchP;
+ *errorP = NULL;
+ }
+ if (*errorP)
+ free(socketWinP);
+ }
+ }
+}
Added: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/socket_win.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/socket_win.h Fri May 23 16:56:24 2008
@@ -0,0 +1,10 @@
+#ifndef SOCKET_WIN_H_INCLUDED
+#define SOCKET_WIN_H_INCLUDED
+
+void
+SocketWinInit(const char ** const errorP);
+
+void
+SocketWinTerm(void);
+
+#endif
Added: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/thread.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/thread.h Fri May 23 16:56:24 2008
@@ -0,0 +1,76 @@
+#ifndef THREAD_H_INCLUDED
+#define THREAD_H_INCLUDED
+
+/*********************************************************************
+** Thread
+*********************************************************************/
+
+#include "bool.h"
+
+typedef struct abyss_thread TThread;
+
+void
+ThreadPoolInit(void);
+
+typedef void TThreadProc(void * const userHandleP);
+typedef void TThreadDoneFn(void * const userHandleP);
+
+void
+ThreadCreate(TThread ** const threadPP,
+ void * const userHandle,
+ TThreadProc * const func,
+ TThreadDoneFn * const threadDone,
+ bool const useSigchld,
+ const char ** const errorP);
+
+bool
+ThreadRun(TThread * const threadP);
+
+bool
+ThreadStop(TThread * const threadP);
+
+bool
+ThreadKill(TThread * const threadP);
+
+void
+ThreadWaitAndRelease(TThread * const threadP);
+
+void
+ThreadExit(int const retValue);
+
+void
+ThreadRelease(TThread * const threadP);
+
+bool
+ThreadForks(void);
+
+void
+ThreadUpdateStatus(TThread * const threadP);
+
+#ifndef WIN32
+void
+ThreadHandleSigchld(pid_t const pid);
+#endif
+
+/*********************************************************************
+** Mutex
+*********************************************************************/
+
+typedef struct abyss_mutex TMutex;
+
+bool
+MutexCreate(TMutex ** const mutexP);
+
+bool
+MutexLock(TMutex * const mutexP);
+
+bool
+MutexUnlock(TMutex * const mutexP);
+
+bool
+MutexTryLock(TMutex * const mutexP);
+
+void
+MutexDestroy(TMutex * const mutexP);
+
+#endif
Added: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/thread_fork.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/thread_fork.c Fri May 23 16:56:24 2008
@@ -0,0 +1,323 @@
+#include <sys/types.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <wait.h>
+#include <signal.h>
+
+#include "xmlrpc_config.h"
+#include "xmlrpc-c/string_int.h"
+#include "xmlrpc-c/abyss.h"
+
+#include "mallocvar.h"
+#include "thread.h"
+
+
+static void
+blockSignalClass(int const signalClass,
+ sigset_t * const oldBlockedSetP) {
+
+ sigset_t newBlockedSet;
+
+ sigemptyset(&newBlockedSet);
+ sigaddset(&newBlockedSet, signalClass);
+
+ sigprocmask(SIG_BLOCK, &newBlockedSet, oldBlockedSetP);
+}
+
+
+
+struct abyss_thread {
+ struct abyss_thread * nextInPoolP;
+ TThreadDoneFn * threadDone;
+ void * userHandle;
+ pid_t pid;
+ bool useSigchld;
+ /* This means that user is going to call ThreadHandleSigchld()
+ when it gets a death of a child signal for this process. If
+ false, he's going to leave us in the dark, so we'll have to
+ poll to know if the process is dead or not.
+ */
+};
+
+
+/* Because signals are global, we need this global variable in order for
+ the signal handler to figure out to what thread the signal belongs.
+*/
+
+/* We use a singly linked list. Every time we access it, we have to run
+ the whole chain. To make this scale up, we should replace it with
+ a doubly linked list and some kind of index by PID.
+
+ But large scale systems probably aren't using fork threads anyway.
+*/
+
+static struct {
+ struct abyss_thread * firstP;
+} ThreadPool;
+
+
+
+void
+ThreadPoolInit(void) {
+
+ ThreadPool.firstP = NULL;
+}
+
+
+
+static struct abyss_thread *
+findThread(pid_t const pid) {
+
+ struct abyss_thread * p;
+
+ for (p = ThreadPool.firstP; p && p->pid != pid; p = p->nextInPoolP);
+
+ return p;
+}
+
+
+
+static void
+addToPool(struct abyss_thread * const threadP) {
+
+ if (ThreadPool.firstP == NULL)
+ ThreadPool.firstP = threadP;
+ else {
+ struct abyss_thread * p;
+
+ for (p = ThreadPool.firstP; p->nextInPoolP; p = p->nextInPoolP);
+
+ /* p points to the last thread in the list */
+
+ p->nextInPoolP = threadP;
+ }
+}
+
+
+
+static void
+removeFromPool(struct abyss_thread * const threadP) {
+
+ if (threadP == ThreadPool.firstP)
+ ThreadPool.firstP = threadP->nextInPoolP;
+ else {
+ struct abyss_thread * p;
+
+ for (p = ThreadPool.firstP;
+ p && p->nextInPoolP != threadP;
+ p = p->nextInPoolP);
+
+ if (p)
+ /* p points to thread right before the one we want to remove */
+ p->nextInPoolP = threadP->nextInPoolP;
+ }
+}
+
+
+
+void
+ThreadHandleSigchld(pid_t const pid) {
+/*----------------------------------------------------------------------------
+ Handle a death of a child signal for process 'pid', which may be one
+ of our threads.
+-----------------------------------------------------------------------------*/
+ struct abyss_thread * const threadP = findThread(pid);
+
+ if (threadP) {
+ if (threadP->threadDone)
+ threadP->threadDone(threadP->userHandle);
+ threadP->pid = 0;
+ }
+ /* Note that threadDone might free *threadP */
+}
+
+
+
+void
+ThreadUpdateStatus(TThread * const threadP) {
+
+ if (!threadP->useSigchld) {
+ if (threadP->pid) {
+ if (kill(threadP->pid, 0) != 0) {
+ if (threadP->threadDone)
+ threadP->threadDone(threadP->userHandle);
+ threadP->pid = 0;
+ }
+ }
+ }
+}
+
+
+
+void
+ThreadCreate(TThread ** const threadPP,
+ void * const userHandle,
+ TThreadProc * const func,
+ TThreadDoneFn * const threadDone,
+ bool const useSigchld,
+ const char ** const errorP) {
+
+ TThread * threadP;
+
+ MALLOCVAR(threadP);
+ if (threadP == NULL)
+ xmlrpc_asprintf(errorP,
+ "Can't allocate memory for thread descriptor.");
+ else {
+ sigset_t oldBlockedSet;
+ pid_t rc;
+
+ threadP->nextInPoolP = NULL;
+ threadP->threadDone = threadDone;
+ threadP->userHandle = userHandle;
+ threadP->useSigchld = useSigchld;
+ threadP->pid = 0;
+
+ /* We have to be sure we don't get the SIGCHLD for this child's
+ death until the child is properly registered in the thread pool
+ so that the handler will know who he is.
+ */
+ blockSignalClass(SIGCHLD, &oldBlockedSet);
+
+ rc = fork();
+
+ if (rc < 0)
+ xmlrpc_asprintf(errorP, "fork() failed, errno=%d (%s)",
+ errno, strerror(errno));
+ else if (rc == 0) {
+ /* This is the child */
+ (*func)(userHandle);
+ exit(0);
+ } else {
+ /* This is the parent */
+ threadP->pid = rc;
+
+ addToPool(threadP);
+
+ sigprocmask(SIG_SETMASK, &oldBlockedSet, NULL); /* restore */
+
+ *errorP = NULL;
+ *threadPP = threadP;
+ }
+ if (*errorP) {
+ removeFromPool(threadP);
+ free(threadP);
+ }
+ }
+}
+
+
+
+bool
+ThreadRun(TThread * const threadP ATTR_UNUSED) {
+ return TRUE;
+}
+
+
+
+bool
+ThreadStop(TThread * const threadP ATTR_UNUSED) {
+ return TRUE;
+}
+
+
+
+bool
+ThreadKill(TThread * const threadP ATTR_UNUSED) {
+ return TRUE;
+}
+
+
+
+void
+ThreadWaitAndRelease(TThread * const threadP) {
+
+ if (threadP->pid) {
+ int exitStatus;
+
+ waitpid(threadP->pid, &exitStatus, 0);
+
+ threadP->threadDone(threadP->userHandle);
+
+ threadP->pid = 0;
+ }
+ ThreadRelease(threadP);
+}
+
+
+
+void
+ThreadExit(int const retValue) {
+
+ /* Note that the OS will automatically send a SIGCHLD signal to
+ the parent process after we exit. The handler for that signal
+ will run threadDone in parent's context. Alternatively, if
+ the parent is set up for signals, the parent will eventually
+ poll for the existence of our PID and call threadDone when he
+ sees we've gone.
+ */
+
+ exit(retValue);
+}
+
+
+
+void
+ThreadRelease(TThread * const threadP) {
+
+ removeFromPool(threadP);
+ free(threadP);
+}
+
+
+
+bool
+ThreadForks(void) {
+
+ return TRUE;
+}
+
+
+
+/*********************************************************************
+** Mutex
+*********************************************************************/
+
+/* As two processes don't share memory, there is nothing to synchronize,
+ so locking is a no-op.
+*/
+
+bool
+MutexCreate(TMutex ** const mutexP ATTR_UNUSED) {
+ return TRUE;
+}
+
+
+
+bool
+MutexLock(TMutex * const mutexP ATTR_UNUSED) {
+ return TRUE;
+}
+
+
+
+bool
+MutexUnlock(TMutex * const mutexP ATTR_UNUSED) {
+ return TRUE;
+}
+
+
+
+bool
+MutexTryLock(TMutex * const mutexP ATTR_UNUSED) {
+ return TRUE;
+}
+
+
+
+void
+MutexDestroy(TMutex * const mutexP ATTR_UNUSED) {
+
+}
Added: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/thread_pthread.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/thread_pthread.c Fri May 23 16:56:24 2008
@@ -0,0 +1,245 @@
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+
+#include "xmlrpc_config.h"
+
+#include "bool.h"
+#include "mallocvar.h"
+#include "xmlrpc-c/string_int.h"
+#include "pthreadx.h"
+
+#include "xmlrpc-c/abyss.h"
+
+#include "thread.h"
+
+
+
+struct abyss_thread {
+ pthread_t thread;
+ void * userHandle;
+ TThreadProc * func;
+ TThreadDoneFn * threadDone;
+};
+
+/* We used to have THREAD_STACK_SIZE = 16K, which was said to be the
+ minimum stack size on Win32. Scott Kolodzeski found in November
+ 2005 that this was insufficient for 64 bit Solaris -- we fail
+ when creating the first thread. So we changed to 128K.
+*/
+#define THREAD_STACK_SIZE (128*1024L)
+
+
+typedef void * (pthreadStartRoutine)(void *);
+
+
+
+static pthreadStartRoutine pthreadStart;
+
+static void *
+pthreadStart(void * const arg) {
+
+ struct abyss_thread * const threadP = arg;
+ bool const executeTrue = true;
+
+ pthread_cleanup_push(threadP->threadDone, threadP->userHandle);
+
+ threadP->func(threadP->userHandle);
+
+ pthread_cleanup_pop(executeTrue);
+
+ return NULL;
+}
+
+
+
+void
+ThreadCreate(TThread ** const threadPP,
+ void * const userHandle,
+ TThreadProc * const func,
+ TThreadDoneFn * const threadDone,
+ bool const useSigchld ATTR_UNUSED,
+ const char ** const errorP) {
+
+ TThread * threadP;
+
+ MALLOCVAR(threadP);
+ if (threadP == NULL)
+ xmlrpc_asprintf(errorP,
+ "Can't allocate memory for thread descriptor.");
+ else {
+ pthread_attr_t attr;
+ int rc;
+
+ pthread_attr_init(&attr);
+
+ pthread_attr_setstacksize(&attr, THREAD_STACK_SIZE);
+
+ threadP->userHandle = userHandle;
+ threadP->func = func;
+ threadP->threadDone = threadDone;
+
+ rc = pthread_create(&threadP->thread, &attr,
+ pthreadStart, threadP);
+ if (rc == 0) {
+ *errorP = NULL;
+ *threadPP = threadP;
+ } else
+ xmlrpc_asprintf(
+ errorP, "pthread_create() failed, errno = %d (%s)",
+ errno, strerror(errno));
+
+ pthread_attr_destroy(&attr);
+
+ if (*errorP)
+ free(threadP);
+ }
+}
+
+
+
+bool
+ThreadRun(TThread * const threadP ATTR_UNUSED) {
+ return TRUE;
+}
+
+
+
+bool
+ThreadStop(TThread * const threadP ATTR_UNUSED) {
+ return TRUE;
+}
+
+
+
+bool
+ThreadKill(TThread * const threadP ATTR_UNUSED) {
+
+ return (pthread_kill(threadP->thread, SIGTERM) == 0);
+}
+
+
+
+void
+ThreadWaitAndRelease(TThread * const threadP) {
+
+ void * threadReturn;
+
+ pthread_join(threadP->thread, &threadReturn);
+
+ free(threadP);
+}
+
+
+
+void
+ThreadExit(int const retValue) {
+
+ pthread_exit((void*)&retValue);
+
+ /* Note that the above runs our cleanup routine (which we registered
+ with pthread_cleanup_push() before exiting.
+ */
+}
+
+
+
+void
+ThreadRelease(TThread * const threadP) {
+
+ pthread_detach(threadP->thread);
+
+ free(threadP);
+}
+
+
+
+bool
+ThreadForks(void) {
+
+ return FALSE;
+}
+
+
+
+void
+ThreadUpdateStatus(TThread * const threadP ATTR_UNUSED) {
+
+ /* Threads keep their own statuses up to date, so there's nothing
+ to do here.
+ */
+}
+
+
+
+void
+ThreadHandleSigchld(pid_t const pid ATTR_UNUSED) {
+
+ /* Death of a child signals have nothing to do with pthreads */
+}
+
+
+
+/*********************************************************************
+** Mutex
+*********************************************************************/
+
+struct abyss_mutex {
+ pthread_mutex_t pthreadMutex;
+};
+
+
+bool
+MutexCreate(TMutex ** const mutexPP) {
+
+ TMutex * mutexP;
+ bool succeeded;
+
+ MALLOCVAR(mutexP);
+
+ if (mutexP) {
+ int rc;
+ rc = pthread_mutex_init(&mutexP->pthreadMutex, NULL);
+
+ succeeded = (rc == 0);
+ } else
+ succeeded = FALSE;
+
+ if (!succeeded)
+ free(mutexP);
+
+ *mutexPP = mutexP;
+
+ return succeeded;
+}
+
+
+
+bool
+MutexLock(TMutex * const mutexP) {
+ return (pthread_mutex_lock(&mutexP->pthreadMutex) == 0);
+}
+
+
+
+bool
+MutexUnlock(TMutex * const mutexP) {
+ return (pthread_mutex_unlock(&mutexP->pthreadMutex) == 0);
+}
+
+
+
+bool
+MutexTryLock(TMutex * const mutexP) {
+ return (pthread_mutex_trylock(&mutexP->pthreadMutex) == 0);
+}
+
+
+
+void
+MutexDestroy(TMutex * const mutexP) {
+ pthread_mutex_destroy(&mutexP->pthreadMutex);
+
+ free(mutexP);
+}
Added: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/thread_windows.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/thread_windows.c Fri May 23 16:56:24 2008
@@ -0,0 +1,231 @@
+/* This code is just a first draft by someone who doesn't know anything
+ about Windows. It has never been compiled. It is just a framework
+ for someone who knows Windows to pick and finish.
+
+ Bryan Henderson redesigned the threading structure for Abyss in
+ April 2006 and wrote this file then. He use the former
+ threading code, which did work on Windows, as a basis.
+*/
+
+
+#include <process.h>
+#include <windows.h>
+
+#include "xmlrpc_config.h"
+
+#include "bool.h"
+#include "int.h"
+#include "mallocvar.h"
+#include "xmlrpc-c/string_int.h"
+
+#include "xmlrpc-c/abyss.h"
+#include "trace.h"
+
+#include "thread.h"
+
+
+
+struct abyss_thread {
+ HANDLE handle;
+ void * userHandle;
+ TThreadProc * func;
+ TThreadDoneFn * threadDone;
+};
+
+#define THREAD_STACK_SIZE (16*1024L)
+
+
+typedef uint32_t (WINAPI WinThreadProc)(void *);
+
+
+static WinThreadProc threadRun;
+
+static uint32_t WINAPI
+threadRun(void * const arg) {
+
+ struct abyss_thread * const threadP = arg;
+
+ threadP->func(threadP->userHandle);
+
+ threadP->threadDone(threadP->userHandle);
+
+ return 0;
+}
+
+
+
+void
+ThreadCreate(TThread ** const threadPP,
+ void * const userHandle,
+ TThreadProc * const func,
+ TThreadDoneFn * const threadDone,
+ bool const useSigchld,
+ const char ** const errorP) {
+
+ TThread * threadP;
+
+ MALLOCVAR(threadP);
+
+ if (threadP == NULL)
+ xmlrpc_asprintf(errorP,
+ "Can't allocate memory for thread descriptor.");
+ else {
+ DWORD z;
+
+ threadP->userHandle = userHandle;
+ threadP->func = func;
+ threadP->threadDone = threadDone;
+
+ threadP->handle = (HANDLE)_beginthreadex(NULL,
+ THREAD_STACK_SIZE,
+ threadRun,
+ threadP,
+ CREATE_SUSPENDED,
+ &z);
+
+ if (threadP->handle == NULL)
+ xmlrpc_asprintf(errorP, "_beginthreadex() failed.");
+ else {
+ *errorP = NULL;
+ *threadPP = threadP;
+ }
+ if (*errorP)
+ free(threadP);
+ }
+}
+
+
+
+bool
+ThreadRun(TThread * const threadP) {
+ return (ResumeThread(threadP->handle) != 0xFFFFFFFF);
+}
+
+
+
+bool
+ThreadStop(TThread * const threadP) {
+
+ return (SuspendThread(threadP->handle) != 0xFFFFFFFF);
+}
+
+
+
+bool
+ThreadKill(TThread * const threadP) {
+ return (TerminateThread(threadP->handle, 0) != 0);
+}
+
+
+
+void
+ThreadWaitAndRelease(TThread * const threadP) {
+
+ ThreadRelease(threadP);
+}
+
+
+
+void
+ThreadExit(int const retValue) {
+
+ _endthreadex(retValue);
+}
+
+
+
+void
+ThreadRelease(TThread * const threadP) {
+
+ CloseHandle(threadP->handle);
+}
+
+
+
+bool
+ThreadForks(void) {
+
+ return FALSE;
+}
+
+
+
+void
+ThreadUpdateStatus(TThread * const threadP ATTR_UNUSED) {
+
+ /* Threads keep their own statuses up to date, so there's nothing
+ to do here.
+ */
+}
+
+
+
+/*********************************************************************
+** Mutex
+*********************************************************************/
+
+struct abyss_mutex {
+ HANDLE winMutex;
+};
+
+
+bool
+MutexCreate(TMutex ** const mutexPP) {
+
+ TMutex * mutexP;
+ bool succeeded;
+
+ MALLOCVAR(mutexP);
+
+ if (mutexP) {
+
+ mutexP->winMutex = CreateMutex(NULL, FALSE, NULL);
+
+ succeeded = (mutexP->winMutex != NULL);
+ } else
+ succeeded = FALSE;
+
+ if (!succeeded)
+ free(mutexP);
+
+ *mutexPP = mutexP;
+
+ TraceMsg( "Created Mutex %s\n", (succeeded ? "ok" : "FAILED") );
+
+ return succeeded;
+}
+
+
+
+bool
+MutexLock(TMutex * const mutexP) {
+
+ return (WaitForSingleObject(mutexP->winMutex, INFINITE) != WAIT_TIMEOUT);
+}
+
+
+
+bool
+MutexUnlock(TMutex * const mutexP) {
+
+ return ReleaseMutex(mutexP->winMutex);
+}
+
+
+bool
+MutexTryLock(TMutex * const mutexP) {
+
+ return (WaitForSingleObject(mutexP->winMutex, 0) != WAIT_TIMEOUT);
+}
+
+
+
+void
+MutexDestroy(TMutex * const mutexP) {
+
+ CloseHandle(mutexP->winMutex);
+
+ free(mutexP);
+}
+
+
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/token.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/token.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/token.c Fri May 23 16:56:24 2008
@@ -1,19 +1,21 @@
#include "xmlrpc-c/abyss.h"
+#include "bool.h"
+
#include "token.h"
void
-NextToken(char ** const p) {
+NextToken(const char ** const pP) {
- abyss_bool gotToken;
+ bool gotToken;
gotToken = FALSE;
while (!gotToken) {
- switch (**p) {
+ switch (**pP) {
case '\t':
case ' ':
- ++(*p);
+ ++(*pP);
break;
default:
gotToken = TRUE;
@@ -24,30 +26,39 @@
char *
-GetToken(char ** const p) {
+GetToken(char ** const pP) {
char * p0;
- p0 = *p;
+ p0 = *pP;
while (1) {
- switch (**p) {
+ switch (**pP) {
case '\t':
case ' ':
case CR:
case LF:
case '\0':
- if (p0 == *p)
+ if (p0 == *pP)
return NULL;
- if (**p) {
- **p = '\0';
- ++(*p);
+ if (**pP) {
+ **pP = '\0';
+ ++(*pP);
};
return p0;
default:
- ++(*p);
+ ++(*pP);
};
}
}
+
+
+
+void
+GetTokenConst(char ** const pP,
+ const char ** const tokenP) {
+
+ *tokenP = GetToken(pP);
+}
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/token.h
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/token.h (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/token.h Fri May 23 16:56:24 2008
@@ -2,10 +2,13 @@
#define ABYSS_TOKEN_H_INCLUDED
void
-NextToken(char ** const p);
+NextToken(const char ** const pP);
char *
-GetToken(char ** const p);
+GetToken(char ** const pP);
+void
+GetTokenConst(char ** const pP,
+ const char ** const tokenP);
#endif
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/trace.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/trace.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/trace.c Fri May 23 16:56:24 2008
@@ -35,20 +35,27 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
-#include "xmlrpc-c/abyss.h"
+
+#include "trace.h"
/*********************************************************************
** Tracing functions
*********************************************************************/
static void
-TraceVMsg(char *fmt,va_list argptr) {
+TraceVMsg(const char * const fmt,
+ va_list argptr) {
+
vprintf(fmt,argptr);
+
printf("\n");
}
-void TraceMsg(char *fmt,...)
-{
+
+
+void
+TraceMsg(const char * const fmt, ...) {
+
va_list argptr;
va_start(argptr,fmt);
@@ -56,12 +63,16 @@
va_end(argptr);
}
-void TraceExit(char *fmt,...)
-{
+
+
+void
+TraceExit(const char * const fmt, ...) {
+
va_list argptr;
va_start(argptr,fmt);
TraceVMsg(fmt,argptr);
va_end(argptr);
- abort();
+
+ exit(1);
}
Added: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/trace.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/trace.h Fri May 23 16:56:24 2008
@@ -0,0 +1,11 @@
+#ifndef TRACE_H_INCLUDED
+#define TRACE_H_INCLUDED
+
+void
+TraceMsg(const char * const fmt, ...);
+
+void
+TraceExit(const char * const fmt, ...);
+
+#endif
+
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/curl_transport/Makefile
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/curl_transport/Makefile (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/curl_transport/Makefile Fri May 23 16:56:24 2008
@@ -1,8 +1,26 @@
-ifeq ($(SRCDIR)x,x)
-SRCDIR = $(CURDIR)/../..
+ifeq ($(SRCDIR),)
+ updir = $(shell echo $(dir $(1)) | sed 's/.$$//')
+ LIBDIR := $(call updir,$(CURDIR))
+ SRCDIR := $(call updir,$(LIBDIR))
+ BLDDIR := $(SRCDIR)
endif
+SUBDIR := lib/curl_transport
-include $(SRCDIR)/Makefile.config
+include $(BLDDIR)/config.mk
+
+default: all
+
+.PHONY: all
+all: xmlrpc_curl_transport.o xmlrpc_curl_transport.osh
+
+# Rules for the above dependencies are in common.mk,
+# courtesy of TARGET_MODS.
+
+TARGET_MODS = xmlrpc_curl_transport
+
+OMIT_CURL_TRANSPORT_RULE=Y
+
+include $(SRCDIR)/common.mk
CURL_INCLUDES := $(shell curl-config --cflags)
# We expect that curl-config --cflags just gives us -I options, because
@@ -10,16 +28,14 @@
# of what any other compiler flag would do to our compile.
CFLAGS = $(CFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD)
-LDFLAGS = -lpthread $(LADD)
-INCLUDES = -I$(SRCDIR) -I$(SRCDIR)/include -I$(SRCDIR)/lib/util/include \
+INCLUDES = \
+ -I$(BLDDIR) \
+ -I$(BLDDIR)/include \
+ -I$(SRCDIR)/include \
+ -I$(SRCDIR)/lib/util/include \
$(CURL_INCLUDES)
-default: all
-
-.PHONY: all
-all: xmlrpc_curl_transport.lo
-
.PHONY: clean
clean: clean-common
@@ -38,9 +54,8 @@
.PHONY: dep
dep: dep-common
-include $(SRCDIR)/Makefile.common
-
include Makefile.depend
-xmlrpc_curl_transport.lo:%.lo:%.c
- $(LIBTOOL) --mode=compile $(CC) -c $(INCLUDES) $(CFLAGS) $<
+# Need this dependency for those who don't use Makefile.depend.
+# Without it, version.h doesn't get created.
+xmlrpc_curl_transport.o xmlrpc_curl_transport.osh: version.h
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/curl_transport/xmlrpc_curl_transport.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/curl_transport/xmlrpc_curl_transport.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/curl_transport/xmlrpc_curl_transport.c Fri May 23 16:56:24 2008
@@ -13,87 +13,137 @@
Curl maintains some minor information in process-global variables.
One must call curl_global_init() to initialize them before calling
- any other Curl library function.
-
- But note that one of those global variables tells that
- curl_global_init() has been called, and if you call it again,
- it's just a no-op. So we can call it for each of many transport
- object constructors.
-
- The actual global variables appear to be constant so that it's OK
- for them to be shared among multiple objects and threads. And we never
- want other than the defaults. They're things like the identity of
- the malloc routine.
-
- Note that not only could many Xmlrpc-c Curl XML transport
- objects be using Curl in the same process, but the Xmlrpc-c user may
- have uses of his own. So this whole fragile thing works only as long
- as the user doesn't need to set these global variables to something
- different from the defaults (because those are what we use).
-
- curl_global_cleanup() reverts the process back to a state in which
- nobody can use the Curl library. So we can't ever call it. This
- means there will be some memory leakage, but since curl_global_init
- only ever has effect once, the amount of leakage is trivial. The
- user can do his own curl_global_cleanup() if he really cares.
-
- Some of the Curl global variables are actually the SSL library global
- variables. The SSL library has the same disease.
+ any other Curl library function. This is not state information --
+ it is constants. They just aren't the kind of constants that the
+ library loader knows how to set, so there has to be this explicit
+ call to set them up. The matching function curl_global_cleanup()
+ returns resources these use (to wit, the constants live in
+ malloc'ed storage and curl_global_cleanup() frees the storage).
+
+ So our setup_global_const transport operation calls
+ curl_global_init() and our teardown_global_const calls
+ curl_global_cleanup().
+
+ The Curl library is supposed to maintain a reference count for the
+ global constants so that multiple modules using the library and
+ independently calling curl_global_init() and curl_global_cleanup()
+ are not a problem. But today, it just keeps a flag "I have been
+ initialized" and the first call to curl_global_cleanup() destroys
+ the constants for everybody. Therefore, the user of the Xmlrpc-c
+ Curl client XML transport must make sure not to call
+ teardownGlobalConstants until everything else in his program is
+ done using the Curl library.
+
+ Note that curl_global_init() is not threadsafe (with or without the
+ reference count), therefore our setup_global_const is not, and must
+ be called when no other thread in the process is running.
+ Typically, one calls it right at the beginning of the program.
+
+ There are actually two other classes of global variables in the
+ Curl library, which we are ignoring: debug options and custom
+ memory allocator function identities. Our code never changes these
+ global variables from default. If something else in the user's
+ program does, User is responsible for making sure it doesn't
+ interfere with our use of the library.
+
+ Note that when we say what the Curl library does, we're also
+ talking about various other libraries Curl uses internally, and in
+ fact much of what we're saying about global variables springs from
+ such subordinate libraries as OpenSSL and Winsock.
-----------------------------------------------------------------------------*/
+#include "xmlrpc_config.h"
#include <string.h>
#include <stdlib.h>
#include <errno.h>
+#include <assert.h>
+#include <limits.h>
+#if !MSVCRT
+#include <sys/select.h>
+#endif
+#include <signal.h>
-#include "xmlrpc_config.h"
+#ifdef WIN32
+#include "curllink.h"
+#endif
#include "bool.h"
+#include "girmath.h"
#include "mallocvar.h"
#include "linklist.h"
-#include "sstring.h"
-#include "casprintf.h"
+#include "girstring.h"
#include "pthreadx.h"
-#include "xmlrpc-c/base.h"
-#include "xmlrpc-c/base_int.h"
-#include "xmlrpc-c/client.h"
+
+#include "xmlrpc-c/string_int.h"
+#include "xmlrpc-c/select_int.h"
#include "xmlrpc-c/client_int.h"
+#include "xmlrpc-c/transport.h"
+#include "xmlrpc-c/time_int.h"
#include "version.h"
#include <curl/curl.h>
#include <curl/types.h>
#include <curl/easy.h>
+#include <curl/multi.h>
-#if defined (WIN32) && defined(_DEBUG)
+#if MSVCRT
+#if defined(_DEBUG)
# include <crtdbg.h>
# define new DEBUG_NEW
# define malloc(size) _malloc_dbg( size, _NORMAL_BLOCK, __FILE__, __LINE__)
# undef THIS_FILE
static char THIS_FILE[] = __FILE__;
-#endif /*WIN32 && _DEBUG*/
+#endif
+#endif
+#define CMAJOR LIBCURL_VERSION_MAJOR
+#define CMINOR LIBCURL_VERSION_MINOR
+#if CMAJOR > 7 || (CMAJOR == 7 && CMINOR >= 10)
+ #define HAVE_CURL_NOSIGNAL 1
+#else
+ #define HAVE_CURL_NOSIGNAL 0
+#endif
+#if CMAJOR > 7 || (CMAJOR == 7 && CMINOR >= 12)
+ #define HAVE_CURL_STRERROR 1
+#else
+ #define HAVE_CURL_STRERROR 0
+#endif
+
+#undef CMAJOR
+#undef CMINOR
+
+
+
+typedef struct rpc rpc;
+
+typedef struct curlTransaction curlTransaction;
+
+
+
+struct curlSetup {
+
+ /* This is all client transport properties that are implemented as
+ simple Curl session properties (i.e. the transport basically just
+ passes them through to Curl without looking at them).
+
+ People occasionally want to replace all this with something where
+ the Xmlrpc-c user simply does the curl_easy_setopt() call and this
+ code need not know about all these options. Unfortunately, that's
+ a significant modularity violation. Either the Xmlrpc-c user
+ controls the Curl object or he doesn't. If he does, then he
+ shouldn't use libxmlrpc_client -- he should just copy some of this
+ code into his own program. If he doesn't, then he should never see
+ the Curl library.
+
+ Speaking of modularity: the only reason this is a separate struct
+ is to make the code easier to manage. Ideally, the fact that these
+ particular properties of the transport are implemented by simple
+ Curl session setup would be known only at the lowest level code
+ that does that setup.
+ */
-struct xmlrpc_client_transport {
- pthread_mutex_t listLock;
- struct list_head rpcList;
- /* List of all RPCs that exist for this transport. An RPC exists
- from the time the user requests it until the time the user
- acknowledges it is done.
- */
- CURL * syncCurlSessionP;
- /* Handle for a Curl library session object that we use for
- all synchronous RPCs. An async RPC has one of its own,
- and consequently does not share things such as persistent
- connections and cookies with any other RPC.
- */
- pthread_mutex_t syncCurlSessionLock;
- /* Hold this lock while accessing or using *syncCurlSessionP.
- You're using the session from the time you set any
- attributes in it or start a transaction with it until any
- transaction has finished and you've lost interest in any
- attributes of the session.
- */
const char * networkInterface;
/* This identifies the network interface on the local side to
use for the session. It is an ASCIIZ string in the form
@@ -116,312 +166,194 @@
authentic) indicates the host name that is in the URL we
are using for the server.
*/
- const char * userAgent;
- /* Prefix for the User-Agent HTTP header, reflecting facilities
- outside of Xmlrpc-c. The actual User-Agent header consists
- of this prefix plus information about Xmlrpc-c. NULL means
- none.
- */
-};
-
-typedef struct {
- /* This is all stuff that really ought to be in a Curl object,
- but the Curl library is a little too simple for that. So we
- build a layer on top of Curl, and define this "transaction," as
- an object subordinate to a Curl "session."
- */
- CURL * curlSessionP;
- /* Handle for the Curl session that hosts this transaction */
- char curlError[CURL_ERROR_SIZE];
- /* Error message from Curl */
- struct curl_slist * headerList;
- /* The HTTP headers for the transaction */
- const char * serverUrl; /* malloc'ed - belongs to this object */
-} curlTransaction;
-
-
-
-typedef struct {
- struct list_head link; /* link in transport's list of RPCs */
- CURL * curlSessionP;
- /* The Curl session we use for this transaction. Note that only
- one RPC at a time can use a particular Curl session, so this
- had better not be a session that some other RPC is using
- simultaneously.
- */
- curlTransaction * curlTransactionP;
- /* The object which does the HTTP transaction, with no knowledge
- of XML-RPC or Xmlrpc-c.
- */
- xmlrpc_mem_block * responseXmlP;
- xmlrpc_bool threadExists;
- pthread_t thread;
- xmlrpc_transport_asynch_complete complete;
- /* Routine to call to complete the RPC after it is complete HTTP-wise.
- NULL if none.
- */
- struct xmlrpc_call_info * callInfoP;
- /* User's identifier for this RPC */
-} rpc;
+ const char * sslCert;
+ const char * sslCertType;
+ const char * sslCertPasswd;
+ const char * sslKey;
+ const char * sslKeyType;
+ const char * sslKeyPasswd;
+ const char * sslEngine;
+ bool sslEngineDefault;
+ unsigned int sslVersion;
+ const char * caInfo;
+ const char * caPath;
+ const char * randomFile;
+ const char * egdSocket;
+ const char * sslCipherList;
+ unsigned int timeout;
+ /* 0 = no Curl timeout. This is in milliseconds. */
+};
-static size_t
-collect(void * const ptr,
- size_t const size,
- size_t const nmemb,
- FILE * const stream) {
-/*----------------------------------------------------------------------------
- This is a Curl output function. Curl calls this to deliver the
- HTTP response body. Curl thinks it's writing to a POSIX stream.
------------------------------------------------------------------------------*/
- xmlrpc_mem_block * const responseXmlP = (xmlrpc_mem_block *) stream;
- char * const buffer = ptr;
- size_t const length = nmemb * size;
+static int
+timeDiffMillisec(xmlrpc_timespec const minuend,
+ xmlrpc_timespec const subtractor) {
- size_t retval;
- xmlrpc_env env;
+ unsigned int const million = 1000000;
- xmlrpc_env_init(&env);
- xmlrpc_mem_block_append(&env, responseXmlP, buffer, length);
- if (env.fault_occurred)
- retval = (size_t)-1;
- else
- /* Really? Shouldn't it be like fread() and return 'nmemb'? */
- retval = length;
-
- return retval;
+ return (minuend.tv_sec - subtractor.tv_sec) * 1000 +
+ (minuend.tv_nsec - subtractor.tv_nsec + million/2) / million;
}
-static void
-initWindowsStuff(xmlrpc_env * const envP) {
+static bool
+timeIsAfter(xmlrpc_timespec const comparator,
+ xmlrpc_timespec const comparand) {
-#if defined (WIN32)
- /* This is CRITICAL so that cURL-Win32 works properly! */
- WORD wVersionRequested;
- WSADATA wsaData;
- int err;
- wVersionRequested = MAKEWORD(1, 1);
-
- err = WSAStartup(wVersionRequested, &wsaData);
- if (err)
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR,
- "Winsock startup failed. WSAStartup returned rc %d", err);
+ if (comparator.tv_sec > comparand.tv_sec)
+ return true;
+ else if (comparator.tv_sec < comparand.tv_sec)
+ return false;
else {
- if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) {
- /* Tell the user that we couldn't find a useable */
- /* winsock.dll. */
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR, "Winsock reported that "
- "it does not implement the requested version 1.1.");
- }
- if (envP->fault_occurred)
- WSACleanup();
+ /* Seconds are equal */
+ if (comparator.tv_nsec > comparand.tv_nsec)
+ return true;
+ else
+ return false;
}
-#else
- if (0)
- envP->fault_occurred = TRUE; /* Avoid unused parm warning */
-#endif
}
static void
-getXportParms(xmlrpc_env * const envP,
- const struct xmlrpc_curl_xportparms * const curlXportParmsP,
- size_t const parmSize,
- const char ** const networkInterfaceP,
- xmlrpc_bool * const sslVerifyPeerP,
- xmlrpc_bool * const sslVerifyHostP,
- const char ** const userAgentP) {
-
- if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(user_agent))
- *userAgentP = NULL;
- else if (curlXportParmsP->user_agent == NULL)
- *userAgentP = NULL;
- else
- *userAgentP = strdup(curlXportParmsP->user_agent);
-
- if (!curlXportParmsP ||
- parmSize < XMLRPC_CXPSIZE(no_ssl_verifypeer))
- *sslVerifyPeerP = TRUE;
- else
- *sslVerifyPeerP = !curlXportParmsP->no_ssl_verifypeer;
-
- if (!curlXportParmsP ||
- parmSize < XMLRPC_CXPSIZE(no_ssl_verifyhost))
- *sslVerifyHostP = TRUE;
- else
- *sslVerifyHostP = !curlXportParmsP->no_ssl_verifyhost;
+addMilliseconds(xmlrpc_timespec const addend,
+ unsigned int const adder,
+ xmlrpc_timespec * const sumP) {
- if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(network_interface))
- *networkInterfaceP = NULL;
- else if (curlXportParmsP->network_interface == NULL)
- *networkInterfaceP = NULL;
- else {
- *networkInterfaceP = strdup(curlXportParmsP->network_interface);
- if (*networkInterfaceP == NULL)
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR,
- "Unable to allocate space for network interface name.");
- if (envP->fault_occurred)
- strfree(*networkInterfaceP);
- }
-}
-
-
+ unsigned int const million = 1000000;
+ unsigned int const billion = 1000000000;
-static void
-createSyncCurlSession(xmlrpc_env * const envP,
- CURL ** const curlSessionPP) {
-/*----------------------------------------------------------------------------
- Create a Curl session to be used for multiple serial transactions.
- The Curl session we create is not complete -- it still has to be
- further set up for each particular transaction.
+ xmlrpc_timespec sum;
- We can't set up anything here that changes from one transaction to the
- next.
+ sum.tv_sec = addend.tv_sec + adder / 1000;
+ sum.tv_nsec = addend.tv_nsec + (adder % 1000) * million;
- We don't bother setting up anything that has to be set up for an
- asynchronous transaction because code that is common between synchronous
- and asynchronous transactions takes care of that anyway.
+ if ((uint32_t)sum.tv_nsec >= billion) {
+ sum.tv_sec += 1;
+ sum.tv_nsec -= billion;
+ }
+ *sumP = sum;
+}
- That leaves things such as cookies that don't exist for asynchronous
- transactions, and are common to multiple serial synchronous
- transactions.
------------------------------------------------------------------------------*/
- CURL * const curlSessionP = curl_easy_init();
- if (curlSessionP == NULL)
- xmlrpc_faultf(envP, "Could not create Curl session. "
- "curl_easy_init() failed.");
- else {
- /* The following is a trick. CURLOPT_COOKIEFILE is the name
- of the file containing the initial cookies for the Curl
- session. But setting it is also what turns on the cookie
- function itself, whereby the Curl library accepts and
- stores cookies from the server and sends them back on
- future requests. We don't have a file of initial cookies, but
- we want to turn on cookie function, so we set the option to
- something we know does not validly name a file. Curl will
- ignore the error and just start up cookie function with no
- initial cookies.
- */
- curl_easy_setopt(curlSessionP, CURLOPT_COOKIEFILE, "");
- *curlSessionPP = curlSessionP;
- }
-}
+/*============================================================================
+ locks
+==============================================================================
+ This is the beginnings of a lock abstraction that will allow this
+ transport to be used with locks other than pthread locks
+============================================================================*/
+struct lock {
+ pthread_mutex_t theLock;
+ void (*lock)(struct lock *);
+ void (*unlock)(struct lock *);
+ void (*destroy)(struct lock *);
+};
+typedef struct lock lock;
static void
-destroySyncCurlSession(CURL * const curlSessionP) {
+lock_pthread(struct lock * const lockP) {
+ pthread_mutex_lock(&lockP->theLock);
+}
- curl_easy_cleanup(curlSessionP);
+static void
+unlock_pthread(struct lock * const lockP) {
+ pthread_mutex_unlock(&lockP->theLock);
}
+static void
+destroyLock_pthread(struct lock * const lockP) {
+ pthread_mutex_destroy(&lockP->theLock);
+ free(lockP);
+}
-static void
-create(xmlrpc_env * const envP,
- int const flags ATTR_UNUSED,
- const char * const appname ATTR_UNUSED,
- const char * const appversion ATTR_UNUSED,
- const struct xmlrpc_xportparms * const transportparmsP,
- size_t const parm_size,
- struct xmlrpc_client_transport ** const handlePP) {
-/*----------------------------------------------------------------------------
- This does the 'create' operation for a Curl client transport.
------------------------------------------------------------------------------*/
- struct xmlrpc_curl_xportparms * const curlXportParmsP =
- (struct xmlrpc_curl_xportparms *) transportparmsP;
+static struct lock *
+createLock_pthread(void) {
+ struct lock * lockP;
+ MALLOCVAR(lockP);
+ if (lockP) {
+ pthread_mutex_init(&lockP->theLock, NULL);
+ lockP->lock = &lock_pthread;
+ lockP->unlock = &unlock_pthread;
+ lockP->destroy = &destroyLock_pthread;
+ }
+ return lockP;
+}
- struct xmlrpc_client_transport * transportP;
- initWindowsStuff(envP);
- MALLOCVAR(transportP);
- if (transportP == NULL)
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR,
- "Unable to allocate transport descriptor.");
- else {
- pthread_mutex_init(&transportP->listLock, NULL);
-
- list_make_empty(&transportP->rpcList);
+/*=============================================================================
+ curlTransaction
+=============================================================================*/
- /*
- * This is the main global constructor for the app. Call this before
- * _any_ libcurl usage. If this fails, *NO* libcurl functions may be
- * used, or havoc may be the result.
- */
- curl_global_init(CURL_GLOBAL_ALL);
+typedef void finishCurlTransactionFn(xmlrpc_env * const, curlTransaction * const);
- /* The above makes it look like Curl is not re-entrant. We should
- check into that.
+struct curlTransaction {
+ /* This is all stuff that really ought to be in a Curl object, but
+ the Curl library is a little too simple for that. So we build
+ a layer on top of Curl, and define this "transaction," as an
+ object subordinate to a Curl "session." A Curl session has
+ zero or one transactions in progress. The Curl session
+ "private data" is a pointer to the CurlTransaction object for
+ the current transaction.
+ */
+ CURL * curlSessionP;
+ /* Handle for the Curl session that hosts this transaction.
+ Note that only one transaction at a time can use a particular
+ Curl session, so this had better not be a session that some other
+ transaction is using simultaneously.
*/
-
- getXportParms(envP, curlXportParmsP, parm_size,
- &transportP->networkInterface,
- &transportP->sslVerifyPeer,
- &transportP->sslVerifyHost,
- &transportP->userAgent);
-
- if (!envP->fault_occurred) {
- pthread_mutex_init(&transportP->syncCurlSessionLock, NULL);
- createSyncCurlSession(envP, &transportP->syncCurlSessionP);
-
- if (envP->fault_occurred)
- strfree(transportP->networkInterface);
- }
- if (envP->fault_occurred)
- free(transportP);
- }
- *handlePP = transportP;
-}
+ finishCurlTransactionFn * finish;
+ rpc * rpcP;
+ /* The RPC which this transaction serves. (If this structure
+ were a true extension of the Curl library as described above,
+ this would be a void *, since the Curl library doesn't know what
+ an RPC is, but since we use it only for that, we might as well
+ use the specific type here).
+ */
+ CURLcode result;
+ /* Result of the transaction (succeeded, TCP connect failed, etc.).
+ A properly executed HTTP transaction (request & response) counts
+ as a successful transaction. When 'result' show success,
+ curl_easy_get_info() tells you whether the transaction succeeded
+ at the HTTP level.
+ */
+ char curlError[CURL_ERROR_SIZE];
+ /* Error message from Curl */
+ struct curl_slist * headerList;
+ /* The HTTP headers for the transaction */
+ const char * serverUrl; /* malloc'ed - belongs to this object */
+};
static void
-termWindowStuff(void) {
+interpretCurlEasyError(const char ** const descriptionP,
+ CURLcode const code) {
-#if defined (WIN32)
- WSACleanup();
+#if HAVE_CURL_STRERROR
+ *descriptionP = strdup(curl_easy_strerror(code));
+#else
+ xmlrpc_asprintf(descriptionP, "Curl error code (CURLcode) %d", code);
#endif
}
-static void
-destroy(struct xmlrpc_client_transport * const clientTransportP) {
-/*----------------------------------------------------------------------------
- This does the 'destroy' operation for a Curl client transport.
------------------------------------------------------------------------------*/
- XMLRPC_ASSERT(clientTransportP != NULL);
-
- XMLRPC_ASSERT(list_is_empty(&clientTransportP->rpcList));
-
- destroySyncCurlSession(clientTransportP->syncCurlSessionP);
- pthread_mutex_destroy(&clientTransportP->syncCurlSessionLock);
-
- if (clientTransportP->networkInterface)
- strfree(clientTransportP->networkInterface);
- if (clientTransportP->userAgent)
- strfree(clientTransportP->userAgent);
-
- /* We want to call curl_global_cleanup() now, but can't. See
- explanation of Curl global variables at the top of this file.
- */
-
- pthread_mutex_destroy(&clientTransportP->listLock);
-
- termWindowStuff();
+static void
+interpretCurlMultiError(const char ** const descriptionP,
+ CURLMcode const code) {
- free(clientTransportP);
+#if HAVE_CURL_STRERROR
+ *descriptionP = strdup(curl_multi_strerror(code));
+#else
+ xmlrpc_asprintf(descriptionP, "Curl error code (CURLMcode) %d", code);
+#endif
}
@@ -456,8 +388,13 @@
addUserAgentHeader(xmlrpc_env * const envP,
struct curl_slist ** const headerListP,
const char * const userAgent) {
-
+
if (userAgent) {
+ /* Note: Curl has a CURLOPT_USERAGENT option that does some of this
+ work. We prefer to be totally in control, though, so we build
+ the header explicitly.
+ */
+
curl_version_info_data * const curlInfoP =
curl_version_info(CURLVERSION_NOW);
char curlVersion[32];
@@ -469,17 +406,17 @@
(curlInfoP->version_num >> 0) && 0xff
);
- casprintf(&userAgentHeader,
- "User-Agent: %s Xmlrpc-c/%s Curl/%s",
- userAgent, XMLRPC_C_VERSION, curlVersion);
+ xmlrpc_asprintf(&userAgentHeader,
+ "User-Agent: %s Xmlrpc-c/%s Curl/%s",
+ userAgent, XMLRPC_C_VERSION, curlVersion);
- if (userAgentHeader == NULL)
+ if (userAgentHeader == xmlrpc_strsol)
xmlrpc_faultf(envP, "Couldn't allocate memory for "
"User-Agent header");
else {
addHeader(envP, headerListP, userAgentHeader);
- strfree(userAgentHeader);
+ xmlrpc_strfree(userAgentHeader);
}
}
}
@@ -487,251 +424,1647 @@
static void
-addAuthorizationHeader(xmlrpc_env * const envP,
- struct curl_slist ** const headerListP,
- const char * const basicAuthInfo) {
+addAuthorizationHeader(xmlrpc_env * const envP,
+ struct curl_slist ** const headerListP,
+ const char * const hdrValue) {
+
+ const char * authorizationHeader;
+
+ xmlrpc_asprintf(&authorizationHeader, "Authorization: %s", hdrValue);
+
+ if (authorizationHeader == xmlrpc_strsol)
+ xmlrpc_faultf(envP, "Couldn't allocate memory for "
+ "Authorization header");
+ else {
+ addHeader(envP, headerListP, authorizationHeader);
+
+ xmlrpc_strfree(authorizationHeader);
+ }
+}
+
+
+
+static void
+createCurlHeaderList(xmlrpc_env * const envP,
+ const char * const authHdrValue,
+ const char * const userAgent,
+ struct curl_slist ** const headerListP) {
+
+ struct curl_slist * headerList;
+
+ headerList = NULL; /* initial value - empty list */
+
+ addContentTypeHeader(envP, &headerList);
+ if (!envP->fault_occurred) {
+ addUserAgentHeader(envP, &headerList, userAgent);
+ if (!envP->fault_occurred) {
+ if (authHdrValue)
+ addAuthorizationHeader(envP, &headerList, authHdrValue);
+ }
+ }
+ if (envP->fault_occurred)
+ curl_slist_free_all(headerList);
+ else
+ *headerListP = headerList;
+}
+
+
+
+static void
+assertConstantsMatch(void) {
+/*----------------------------------------------------------------------------
+ There are some constants that we define as part of the Xmlrpc-c
+ interface that are identical to constants in the Curl interface to
+ make curl option setting work. This function asserts such
+ formally.
+-----------------------------------------------------------------------------*/
+ assert(XMLRPC_SSLVERSION_DEFAULT == CURL_SSLVERSION_DEFAULT);
+ assert(XMLRPC_SSLVERSION_TLSv1 == CURL_SSLVERSION_TLSv1);
+ assert(XMLRPC_SSLVERSION_SSLv2 == CURL_SSLVERSION_SSLv2);
+ assert(XMLRPC_SSLVERSION_SSLv3 == CURL_SSLVERSION_SSLv3);
+}
+
+
+
+static size_t
+collect(void * const ptr,
+ size_t const size,
+ size_t const nmemb,
+ FILE * const stream) {
+/*----------------------------------------------------------------------------
+ This is a Curl output function. Curl calls this to deliver the
+ HTTP response body to the Curl client. Curl thinks it's writing to
+ a POSIX stream.
+-----------------------------------------------------------------------------*/
+ xmlrpc_mem_block * const responseXmlP = (xmlrpc_mem_block *) stream;
+ char * const buffer = ptr;
+ size_t const length = nmemb * size;
+
+ size_t retval;
+ xmlrpc_env env;
+
+ xmlrpc_env_init(&env);
+ xmlrpc_mem_block_append(&env, responseXmlP, buffer, length);
+ if (env.fault_occurred)
+ retval = (size_t)-1;
+ else
+ /* Really? Shouldn't it be like fread() and return 'nmemb'? */
+ retval = length;
+
+ return retval;
+}
+
+
+
+static int
+curlProgress(void * const contextP,
+ double const dltotal ATTR_UNUSED,
+ double const dlnow ATTR_UNUSED,
+ double const ultotal ATTR_UNUSED,
+ double const ulnow ATTR_UNUSED) {
+/*----------------------------------------------------------------------------
+ This is a Curl "progress function." It's something various Curl
+ functions call every so often, including whenever something gets
+ interrupted by the process receiving, and catching, a signal.
+ There are two purposes of a Curl progress function: 1) lets us log
+ the progress of a long-running transaction such as a big download,
+ e.g. by displaying a progress bar somewhere. In Xmlrpc-c, we don't
+ implement this purpose. 2) allows us to tell the Curl function,
+ via our return code, that calls it that we don't want to wait
+ anymore for the operation to complete.
+
+ In Curl versions before March 2007, we get called once per second
+ and signals have no effect. In current Curl, we usually get called
+ immediately after a signal gets caught while Curl is waiting to
+ receive a response from the server. But Curl doesn't properly
+ synchronize with signals, so it may miss one and then we don't get
+ called until the next scheduled one-per-second call.
+
+ All we do is tell Caller it's time to give up if the transport's
+ client says it is via his "interrupt" flag.
+
+ This function is not as important as it once was. This module used
+ to use curl_easy_perform(), which can be interrupted only via this
+ progress function. But because of the above-mentioned failure of
+ Curl to properly synchronize signals (and Bryan's failure to get
+ Curl developers to accept code to fix it), we now use the Curl
+ "multi" facility instead and do our own pselect(). But
+ This function still normally gets called by curl_multi_perform(),
+ which the transport tries to call even when the user has requested
+ interruption, because we don't trust our ability to abort a running
+ Curl transaction. curl_multi_perform() reliably winds up a Curl
+ transaction when this function tells it to.
+-----------------------------------------------------------------------------*/
+ unsigned int * const interruptP = contextP;
+
+ /* We require anyone setting us up as the Curl progress function to
+ supply an interrupt flag:
+ */
+ assert(contextP);
+
+ return *interruptP != 0 ? 1 : 0;
+}
+
+
+
+static void
+setupAuth(xmlrpc_env * const envP ATTR_UNUSED,
+ CURL * const curlSessionP,
+ const xmlrpc_server_info * const serverInfoP,
+ const char ** const authHdrValueP) {
+/*----------------------------------------------------------------------------
+ Set the options in the Curl session 'curlSessionP' to set up the HTTP
+ authentication described by *serverInfoP.
+
+ But we have an odd special function for backward compatibility, because
+ this code dates to a time when libcurl did not have the ability to
+ handle authentication, but we provided such function nonetheless by
+ building our own Authorization: header. But we did this only for
+ HTTP basic authentication.
+
+ So the special function is this: if libcurl is too old to have
+ authorization options and *serverInfoP allows basic authentication,
+ return as *basicAuthHdrParamP an appropriate parameter for the
+ Authorization: Basic: HTTP header. Otherwise, return
+ *basicAuthHdrParamP == NULL.
+-----------------------------------------------------------------------------*/
+ if (serverInfoP->allowedAuth.basic) {
+ CURLcode rc;
+ rc = curl_easy_setopt(curlSessionP, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
+
+ if (rc == CURLE_OK)
+ *authHdrValueP = NULL;
+ else {
+ *authHdrValueP = strdup(serverInfoP->basicAuthHdrValue);
+ if (*authHdrValueP == NULL)
+ xmlrpc_faultf(envP, "Unable to allocate memory for basic "
+ "authentication header");
+ }
+ } else
+ *authHdrValueP = NULL;
+
+ /* We don't worry if libcurl is too old for these other kinds of
+ authentication; they're only defined as _allowed_
+ authentication methods, for when client and server are capable
+ of using it, and unlike with basic authentication, we have no
+ historical commitment to consider an old libcurl as capable of
+ doing these.
+ */
+
+ if (serverInfoP->userNamePw)
+ curl_easy_setopt(curlSessionP, CURLOPT_USERPWD,
+ serverInfoP->userNamePw);
+
+ if (serverInfoP->allowedAuth.digest)
+ curl_easy_setopt(
+ curlSessionP, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
+ if (serverInfoP->allowedAuth.gssnegotiate)
+ curl_easy_setopt(
+ curlSessionP, CURLOPT_HTTPAUTH, CURLAUTH_GSSNEGOTIATE);
+ if (serverInfoP->allowedAuth.ntlm)
+ curl_easy_setopt(
+ curlSessionP, CURLOPT_HTTPAUTH, CURLAUTH_NTLM);
+}
+
+
+static void
+setCurlTimeout(CURL * const curlSessionP ATTR_UNUSED,
+ unsigned int const timeout ATTR_UNUSED) {
+
+#if HAVE_CURL_NOSIGNAL
+ unsigned int const timeoutMs = (timeout + 999)/1000;
+
+ curl_easy_setopt(curlSessionP, CURLOPT_NOSIGNAL, 1);
+
+ assert((long)timeoutMs == (int)timeoutMs);
+ /* Calling requirement */
+ curl_easy_setopt(curlSessionP, CURLOPT_TIMEOUT, (long)timeoutMs);
+#else
+ abort();
+#endif
+}
+
+
+
+static void
+setupCurlSession(xmlrpc_env * const envP,
+ curlTransaction * const curlTransactionP,
+ xmlrpc_mem_block * const callXmlP,
+ xmlrpc_mem_block * const responseXmlP,
+ const xmlrpc_server_info * const serverInfoP,
+ const char * const userAgent,
+ int * const interruptP,
+ const struct curlSetup * const curlSetupP) {
+/*----------------------------------------------------------------------------
+ Set up the Curl session for the transaction *curlTransactionP so that
+ a subsequent curl_easy_perform() would perform said transaction.
+
+ The data curl_easy_perform() would send for that transaction would
+ be the contents of *callXmlP; the data curl_easy_perform() gets back
+ would go into *responseXmlP.
+
+ 'interruptP' is a pointer to an interrupt flag -- a flag that becomes
+ nonzero when the user wants to abandon this Curl session. NULL means
+ there is no interrupt flag; user will never want to abandon the session.
+-----------------------------------------------------------------------------*/
+ CURL * const curlSessionP = curlTransactionP->curlSessionP;
+
+ assertConstantsMatch();
+
+ curl_easy_setopt(curlSessionP, CURLOPT_POST, 1);
+ curl_easy_setopt(curlSessionP, CURLOPT_URL, curlTransactionP->serverUrl);
+
+ XMLRPC_MEMBLOCK_APPEND(char, envP, callXmlP, "\0", 1);
+ if (!envP->fault_occurred) {
+ curl_easy_setopt(curlSessionP, CURLOPT_POSTFIELDS,
+ XMLRPC_MEMBLOCK_CONTENTS(char, callXmlP));
+ curl_easy_setopt(curlSessionP, CURLOPT_WRITEFUNCTION, collect);
+ curl_easy_setopt(curlSessionP, CURLOPT_FILE, responseXmlP);
+ curl_easy_setopt(curlSessionP, CURLOPT_HEADER, 0);
+ curl_easy_setopt(curlSessionP, CURLOPT_ERRORBUFFER,
+ curlTransactionP->curlError);
+ if (interruptP) {
+ curl_easy_setopt(curlSessionP, CURLOPT_NOPROGRESS, 0);
+ curl_easy_setopt(curlSessionP, CURLOPT_PROGRESSFUNCTION,
+ curlProgress);
+ curl_easy_setopt(curlSessionP, CURLOPT_PROGRESSDATA, interruptP);
+ } else
+ curl_easy_setopt(curlSessionP, CURLOPT_NOPROGRESS, 1);
+
+ curl_easy_setopt(curlSessionP, CURLOPT_SSL_VERIFYPEER,
+ curlSetupP->sslVerifyPeer);
+ curl_easy_setopt(curlSessionP, CURLOPT_SSL_VERIFYHOST,
+ curlSetupP->sslVerifyHost ? 2 : 0);
+
+ if (curlSetupP->networkInterface)
+ curl_easy_setopt(curlSessionP, CURLOPT_INTERFACE,
+ curlSetupP->networkInterface);
+ if (curlSetupP->sslCert)
+ curl_easy_setopt(curlSessionP, CURLOPT_SSLCERT,
+ curlSetupP->sslCert);
+ if (curlSetupP->sslCertType)
+ curl_easy_setopt(curlSessionP, CURLOPT_SSLCERTTYPE,
+ curlSetupP->sslCertType);
+ if (curlSetupP->sslCertPasswd)
+ curl_easy_setopt(curlSessionP, CURLOPT_SSLCERTPASSWD,
+ curlSetupP->sslCertPasswd);
+ if (curlSetupP->sslKey)
+ curl_easy_setopt(curlSessionP, CURLOPT_SSLKEY,
+ curlSetupP->sslKey);
+ if (curlSetupP->sslKeyType)
+ curl_easy_setopt(curlSessionP, CURLOPT_SSLKEYTYPE,
+ curlSetupP->sslKeyType);
+ if (curlSetupP->sslKeyPasswd)
+ curl_easy_setopt(curlSessionP, CURLOPT_SSLKEYPASSWD,
+ curlSetupP->sslKeyPasswd);
+ if (curlSetupP->sslEngine)
+ curl_easy_setopt(curlSessionP, CURLOPT_SSLENGINE,
+ curlSetupP->sslEngine);
+ if (curlSetupP->sslEngineDefault)
+ /* 3rd argument seems to be required by some Curl */
+ curl_easy_setopt(curlSessionP, CURLOPT_SSLENGINE_DEFAULT, 1l);
+ if (curlSetupP->sslVersion != XMLRPC_SSLVERSION_DEFAULT)
+ curl_easy_setopt(curlSessionP, CURLOPT_SSLVERSION,
+ curlSetupP->sslVersion);
+ if (curlSetupP->caInfo)
+ curl_easy_setopt(curlSessionP, CURLOPT_CAINFO,
+ curlSetupP->caInfo);
+ if (curlSetupP->caPath)
+ curl_easy_setopt(curlSessionP, CURLOPT_CAPATH,
+ curlSetupP->caPath);
+ if (curlSetupP->randomFile)
+ curl_easy_setopt(curlSessionP, CURLOPT_RANDOM_FILE,
+ curlSetupP->randomFile);
+ if (curlSetupP->egdSocket)
+ curl_easy_setopt(curlSessionP, CURLOPT_EGDSOCKET,
+ curlSetupP->egdSocket);
+ if (curlSetupP->sslCipherList)
+ curl_easy_setopt(curlSessionP, CURLOPT_SSL_CIPHER_LIST,
+ curlSetupP->sslCipherList);
+
+ if (curlSetupP->timeout)
+ setCurlTimeout(curlSessionP, curlSetupP->timeout);
+
+ {
+ const char * authHdrValue;
+ /* NULL means we don't have to construct an explicit
+ Authorization: header. non-null means we have to
+ construct one with this as its value.
+ */
+
+ setupAuth(envP, curlSessionP, serverInfoP, &authHdrValue);
+ if (!envP->fault_occurred) {
+ struct curl_slist * headerList;
+ createCurlHeaderList(envP, authHdrValue, userAgent,
+ &headerList);
+ if (!envP->fault_occurred) {
+ curl_easy_setopt(
+ curlSessionP, CURLOPT_HTTPHEADER, headerList);
+ curlTransactionP->headerList = headerList;
+ }
+ if (authHdrValue)
+ xmlrpc_strfree(authHdrValue);
+ }
+ }
+ }
+}
+
+
+
+static void
+curlTransaction_create(xmlrpc_env * const envP,
+ CURL * const curlSessionP,
+ const xmlrpc_server_info * const serverP,
+ xmlrpc_mem_block * const callXmlP,
+ xmlrpc_mem_block * const responseXmlP,
+ const char * const userAgent,
+ const struct curlSetup * const curlSetupStuffP,
+ rpc * const rpcP,
+ int * const interruptP,
+ curlTransaction ** const curlTransactionPP) {
+
+ curlTransaction * curlTransactionP;
+
+ MALLOCVAR(curlTransactionP);
+ if (curlTransactionP == NULL)
+ xmlrpc_faultf(envP, "No memory to create Curl transaction.");
+ else {
+ curlTransactionP->finish = NULL;
+ curlTransactionP->curlSessionP = curlSessionP;
+ curlTransactionP->rpcP = rpcP;
+
+ curlTransactionP->serverUrl = strdup(serverP->serverUrl);
+ if (curlTransactionP->serverUrl == NULL)
+ xmlrpc_faultf(envP, "Out of memory to store server URL.");
+ else {
+ setupCurlSession(envP, curlTransactionP,
+ callXmlP, responseXmlP,
+ serverP, userAgent, interruptP,
+ curlSetupStuffP);
+
+ if (envP->fault_occurred)
+ xmlrpc_strfree(curlTransactionP->serverUrl);
+ }
+ if (envP->fault_occurred)
+ free(curlTransactionP);
+ }
+ *curlTransactionPP = curlTransactionP;
+}
+
+
+
+static void
+curlTransaction_destroy(curlTransaction * const curlTransactionP) {
+
+ curl_slist_free_all(curlTransactionP->headerList);
+ xmlrpc_strfree(curlTransactionP->serverUrl);
+
+ free(curlTransactionP);
+}
+
+
+
+/*=============================================================================
+ curlMulti
+=============================================================================*/
+
+typedef struct {
+/*----------------------------------------------------------------------------
+ This is an extension to Curl's CURLM object. The extensions are:
+
+ 1) It has a lock so multiple threads can use it simultaneously.
+
+ 2) Its "select" file descriptor vectors are self-contained. CURLM
+ requires the user to maintain them separately.
+
+ Plus, it manages Curl transactions (curlTransaction) instead of Curl
+ sessions (CURL).
+-----------------------------------------------------------------------------*/
+ CURLM * curlMultiP;
+ lock * lockP;
+ /* Hold this lock while accessing or using *curlMultiP. You're
+ using the multi manager whenever you're calling a Curl
+ library multi manager function.
+ */
+ /* The following file descriptor sets are an integral part of the
+ CURLM object; Our curlMulti_fdset() routine binds them to the
+ CURLM object, and said object expects us to use them in a very
+ specific way, including doing a select() on them. It is very,
+ very messy.
+ */
+ fd_set readFdSet;
+ fd_set writeFdSet;
+ fd_set exceptFdSet;
+} curlMulti;
+
+
+
+static curlMulti *
+curlMulti_create(void) {
+
+ curlMulti * retval;
+ curlMulti * curlMultiP;
+
+ MALLOCVAR(curlMultiP);
+
+ if (curlMultiP == NULL)
+ retval = NULL;
+ else {
+ curlMultiP->lockP = createLock_pthread();
+
+ if (curlMultiP->lockP == NULL)
+ retval = NULL;
+ else {
+ curlMultiP->curlMultiP = curl_multi_init();
+ if (curlMultiP->curlMultiP == NULL)
+ retval = NULL;
+ else
+ retval = curlMultiP;
+
+ if (retval == NULL)
+ curlMultiP->lockP->destroy(curlMultiP->lockP);
+ }
+ if (retval == NULL)
+ free(curlMultiP);
+ }
+ return retval;
+}
+
+
+
+static void
+curlMulti_destroy(curlMulti * const curlMultiP) {
+
+ curl_multi_cleanup(curlMultiP->curlMultiP);
+
+ curlMultiP->lockP->destroy(curlMultiP->lockP);
+
+ free(curlMultiP);
+}
+
+
+
+static void
+curlMulti_perform(xmlrpc_env * const envP,
+ curlMulti * const curlMultiP,
+ bool * const immediateWorkToDoP,
+ int * const runningHandlesP) {
+/*----------------------------------------------------------------------------
+ Do whatever work is ready to be done under the control of multi
+ manager 'curlMultiP'. E.g. if HTTP response data has recently arrived
+ from the network, process it as an HTTP response.
+
+ Iff this results in some work being finished from our point of view,
+ return *immediateWorkToDoP. (Caller can query the multi manager for
+ messages and find out what it is).
+
+ Return as *runningHandlesP the number of Curl easy handles under the
+ multi manager's control that are still running -- yet to finish.
+-----------------------------------------------------------------------------*/
+ CURLMcode rc;
+
+ curlMultiP->lockP->lock(curlMultiP->lockP);
+
+ rc = curl_multi_perform(curlMultiP->curlMultiP, runningHandlesP);
+
+ curlMultiP->lockP->unlock(curlMultiP->lockP);
+
+ if (rc == CURLM_CALL_MULTI_PERFORM) {
+ *immediateWorkToDoP = true;
+ } else {
+ *immediateWorkToDoP = false;
+
+ if (rc != CURLM_OK) {
+ const char * reason;
+ interpretCurlMultiError(&reason, rc);
+ xmlrpc_faultf(envP, "Impossible failure of curl_multi_perform(): "
+ "%s", reason);
+ xmlrpc_strfree(reason);
+ }
+ }
+}
+
+
+
+static void
+curlMulti_addHandle(xmlrpc_env * const envP,
+ curlMulti * const curlMultiP,
+ curlTransaction * const curlTransactionP) {
+
+ CURLMcode rc;
+
+ curlMultiP->lockP->lock(curlMultiP->lockP);
+
+ rc = curl_multi_add_handle(curlMultiP->curlMultiP,
+ curlTransactionP->curlSessionP);
+
+ curlMultiP->lockP->unlock(curlMultiP->lockP);
+
+ if (rc != CURLM_OK) {
+ const char * reason;
+ interpretCurlMultiError(&reason, rc);
+ xmlrpc_faultf(envP, "Could not add Curl session to the "
+ "curl multi manager. curl_multi_add_handle() "
+ "failed: %s", reason);
+ xmlrpc_strfree(reason);
+ }
+}
+
+
+static void
+curlMulti_removeHandle(curlMulti * const curlMultiP,
+ curlTransaction * const curlTransactionP) {
+
+ curlMultiP->lockP->lock(curlMultiP->lockP);
+
+ curl_multi_remove_handle(curlMultiP->curlMultiP,
+ curlTransactionP->curlSessionP);
+
+ curlMultiP->lockP->unlock(curlMultiP->lockP);
+}
+
+
+
+static void
+curlMulti_getMessage(curlMulti * const curlMultiP,
+ bool * const endOfMessagesP,
+ CURLMsg * const curlMsgP) {
+/*----------------------------------------------------------------------------
+ Get the next message from the queue of things the Curl multi manager
+ wants to say to us.
+
+ Return the message as *curlMsgP.
+
+ Iff there are no messages in the queue, return *endOfMessagesP == true.
+-----------------------------------------------------------------------------*/
+ int remainingMsgCount;
+ CURLMsg * privateCurlMsgP;
+ /* Note that this is a pointer into the multi manager's memory,
+ so we have to use it under lock.
+ */
+
+ curlMultiP->lockP->lock(curlMultiP->lockP);
+
+ privateCurlMsgP = curl_multi_info_read(curlMultiP->curlMultiP,
+ &remainingMsgCount);
+
+ if (privateCurlMsgP == NULL)
+ *endOfMessagesP = true;
+ else {
+ *endOfMessagesP = false;
+ *curlMsgP = *privateCurlMsgP;
+ }
+ curlMultiP->lockP->unlock(curlMultiP->lockP);
+}
+
+
+
+static void
+curlMulti_fdset(xmlrpc_env * const envP,
+ curlMulti * const curlMultiP,
+ fd_set * const readFdSetP,
+ fd_set * const writeFdSetP,
+ fd_set * const exceptFdSetP,
+ int * const maxFdP) {
+/*----------------------------------------------------------------------------
+ Set the CURLM object's file descriptor sets to those in the
+ curlMulti object, update those file descriptor sets with the
+ current needs of the multi manager, and return the resulting values
+ of the file descriptor sets.
+
+ This is a bizarre operation, but is necessary because of the nonmodular
+ way in which the Curl multi interface works with respect to waiting
+ for work with select().
+-----------------------------------------------------------------------------*/
+ CURLMcode rc;
+
+ curlMultiP->lockP->lock(curlMultiP->lockP);
+
+ /* curl_multi_fdset() doesn't _set_ the fdsets. It adds to existing
+ ones (so you can easily do a select() on other fds and Curl
+ fds at the same time). So we have to clear first:
+ */
+ FD_ZERO(&curlMultiP->readFdSet);
+ FD_ZERO(&curlMultiP->writeFdSet);
+ FD_ZERO(&curlMultiP->exceptFdSet);
+
+ /* WARNING: curl_multi_fdset() doesn't just update the fdsets pointed
+ to by its arguments. It makes the CURLM object remember those
+ pointers and refer back to them later! In fact, curl_multi_perform
+ expects its caller to have done a select() on those masks. No,
+ really. The man page even admits it.
+
+ Inspection of the Libcurl code in March 2007 indicates that
+ this isn't actually true -- curl_multi_fdset() updates your
+ fdset and doesn't remember the pointer at all. I.e. it's just
+ what you would expect. The man pages still says it's as
+ described above. My guess is that Libcurl was fixed at some
+ time and the man page not updated. In any case, we have to
+ work with old Libcurl if at all possible, so we still maintain
+ these fdsets as if they belong to the CURLM object.
+ */
+
+ rc = curl_multi_fdset(curlMultiP->curlMultiP,
+ &curlMultiP->readFdSet,
+ &curlMultiP->writeFdSet,
+ &curlMultiP->exceptFdSet,
+ maxFdP);
+
+ *readFdSetP = curlMultiP->readFdSet;
+ *writeFdSetP = curlMultiP->writeFdSet;
+ *exceptFdSetP = curlMultiP->exceptFdSet;
+
+ curlMultiP->lockP->unlock(curlMultiP->lockP);
+
+ if (rc != CURLM_OK) {
+ const char * reason;
+ interpretCurlMultiError(&reason, rc);
+ xmlrpc_faultf(envP, "Impossible failure of curl_multi_fdset(): %s",
+ reason);
+ xmlrpc_strfree(reason);
+ }
+}
+
+
+
+static void
+curlMulti_updateFdSet(curlMulti * const curlMultiP,
+ fd_set const readFdSet,
+ fd_set const writeFdSet,
+ fd_set const exceptFdSet) {
+/*----------------------------------------------------------------------------
+ curl_multi_perform() expects the file descriptor sets, which were bound
+ to the CURLM object via a prior curlMulti_fdset(), to contain the results
+ of a recent select(). This subroutine provides you a way to supply those.
+-----------------------------------------------------------------------------*/
+ curlMultiP->readFdSet = readFdSet;
+ curlMultiP->writeFdSet = writeFdSet;
+ curlMultiP->exceptFdSet = exceptFdSet;
+}
+
+
+
+static xmlrpc_timespec
+pselectTimeout(xmlrpc_timeoutType const timeoutType,
+ xmlrpc_timespec const timeoutDt) {
+/*----------------------------------------------------------------------------
+ Return the value that should be used in the select() call to wait for
+ there to be work for the Curl multi manager to do, given that the user
+ wants to timeout according to 'timeoutType' and 'timeoutDt'.
+-----------------------------------------------------------------------------*/
+ unsigned int const million = 1000000;
+ unsigned int selectTimeoutMillisec;
+ xmlrpc_timespec retval;
+
+ selectTimeoutMillisec = 0; /* quiet compiler warning */
+
+ /* We assume there is work to do at least every 3 seconds, because
+ the Curl multi manager often has retries and other scheduled work
+ that doesn't involve file handles on which we can select().
+ */
+ switch (timeoutType) {
+ case timeout_no:
+ selectTimeoutMillisec = 3000;
+ break;
+ case timeout_yes: {
+ xmlrpc_timespec nowTime;
+ int timeLeft;
+
+ xmlrpc_gettimeofday(&nowTime);
+ timeLeft = timeDiffMillisec(timeoutDt, nowTime);
+
+ selectTimeoutMillisec = MIN(3000, MAX(0, timeLeft));
+ }
+ break;
+ }
+ retval.tv_sec = selectTimeoutMillisec / 1000;
+ retval.tv_nsec = (uint32_t)((selectTimeoutMillisec % 1000) * million);
+
+ return retval;
+}
+
+
+
+static void
+processCurlMessages(xmlrpc_env * const envP,
+ curlMulti * const curlMultiP) {
+
+ bool endOfMessages;
+
+ endOfMessages = false; /* initial assumption */
+
+ while (!endOfMessages && !envP->fault_occurred) {
+ CURLMsg curlMsg;
+
+ curlMulti_getMessage(curlMultiP, &endOfMessages, &curlMsg);
+
+ if (!endOfMessages) {
+ if (curlMsg.msg == CURLMSG_DONE) {
+ curlTransaction * curlTransactionP;
+
+ curl_easy_getinfo(curlMsg.easy_handle, CURLINFO_PRIVATE,
+ &curlTransactionP);
+
+ curlTransactionP->result = curlMsg.data.result;
+
+ if (curlTransactionP->finish)
+ curlTransactionP->finish(envP, curlTransactionP);
+ }
+ }
+ }
+}
+
+
+
+static void
+waitForWork(xmlrpc_env * const envP,
+ curlMulti * const curlMultiP,
+ xmlrpc_timeoutType const timeoutType,
+ xmlrpc_timespec const deadline,
+ sigset_t * const sigmaskP) {
+/*----------------------------------------------------------------------------
+ Wait for the Curl multi manager to have work to do, time to run out,
+ or a signal to be received (and caught), whichever comes first.
+
+ Update the Curl multi manager's file descriptor sets to indicate what
+ work we found for it to do.
+
+ Wait under signal mask *sigmaskP. The point of this is that Caller
+ can make sure that arrival of a signal of a certain class
+ interrupts our wait, even if the signal arrives shortly before we
+ begin waiting. Caller blocks that signal class, then checks
+ whether a signal of that class has already been received. If not,
+ he calls us with *sigmaskP indicating that class NOT blocked.
+ Thus, if a signal of that class arrived any time after Caller
+ checked, we will return immediately or when the signal arrives,
+ whichever is sooner. Note that we can provide this service only
+ because pselect() has the same atomic unblock/wait feature.
+
+ If sigmaskP is NULL, wait under whatever the current signal mask
+ is.
+-----------------------------------------------------------------------------*/
+ fd_set readFdSet;
+ fd_set writeFdSet;
+ fd_set exceptFdSet;
+ int maxFd;
+
+ curlMulti_fdset(envP, curlMultiP,
+ &readFdSet, &writeFdSet, &exceptFdSet, &maxFd);
+ if (!envP->fault_occurred) {
+ if (maxFd == -1) {
+ /* There are no Curl file descriptors on which to wait.
+ So either there's work to do right now or all transactions
+ are already complete.
+ */
+ } else {
+ xmlrpc_timespec const pselectTimeoutArg =
+ pselectTimeout(timeoutType, deadline);
+
+ int rc;
+
+ rc = xmlrpc_pselect(maxFd+1, &readFdSet, &writeFdSet, &exceptFdSet,
+ &pselectTimeoutArg, sigmaskP);
+
+ if (rc < 0 && errno != EINTR)
+ xmlrpc_faultf(envP, "Impossible failure of pselect() "
+ "with errno %d (%s)",
+ errno, strerror(errno));
+ else {
+ /* Believe it or not, the Curl multi manager needs the
+ results of our pselect(). So hand them over:
+ */
+ curlMulti_updateFdSet(curlMultiP,
+ readFdSet, writeFdSet, exceptFdSet);
+ }
+ }
+ }
+}
+
+
+
+static void
+waitForWorkInt(xmlrpc_env * const envP,
+ curlMulti * const curlMultiP,
+ xmlrpc_timeoutType const timeoutType,
+ xmlrpc_timespec const deadline,
+ int * const interruptP) {
+/*----------------------------------------------------------------------------
+ Same as waitForWork(), except we guarantee to return if a signal handler
+ sets or has set *interruptP, whereas waitForWork() can miss a signal
+ that happens before or just after it starts.
+
+ We mess with global state -- the signal mask -- so we might mess up
+ a multithreaded program. Therefore, don't call this if
+ waitForWork() will suffice.
+-----------------------------------------------------------------------------*/
+ sigset_t callerBlockSet;
+#ifdef WIN32
+ waitForWork(envP, curlMultiP, timeoutType, deadline, &callerBlockSet);
+#else
+ sigset_t allSignals;
+
+ assert(interruptP != NULL);
+
+ sigfillset(&allSignals);
+
+ sigprocmask(SIG_BLOCK, &allSignals, &callerBlockSet);
+
+ if (*interruptP == 0)
+ waitForWork(envP, curlMultiP, timeoutType, deadline, &callerBlockSet);
+
+ sigprocmask(SIG_SETMASK, &callerBlockSet, NULL);
+#endif
+}
+
+
+
+static void
+doCurlWork(xmlrpc_env * const envP,
+ curlMulti * const curlMultiP,
+ bool * const transStillRunningP) {
+/*----------------------------------------------------------------------------
+ Do whatever work is ready to be done by the Curl multi manager
+ identified by 'curlMultiP'. This typically is transferring data on
+ an HTTP connection because the server is ready.
+
+ For each transaction for which the multi manager finishes all the
+ required work, complete the transaction by calling its
+ "finish" routine.
+
+ Return *transStillRunningP false if this work completes all of the
+ manager's transactions so that there is no reason to call us ever
+ again.
+-----------------------------------------------------------------------------*/
+ bool immediateWorkToDo;
+ int runningHandles;
+
+ immediateWorkToDo = true; /* initial assumption */
+
+ while (immediateWorkToDo && !envP->fault_occurred) {
+ curlMulti_perform(envP, curlMultiP,
+ &immediateWorkToDo, &runningHandles);
+ }
+
+ /* We either did all the work that's ready to do or hit an error. */
+
+ if (!envP->fault_occurred) {
+ /* The work we did may have resulted in asynchronous messages
+ (asynchronous to the thing they refer to, not to us, of course).
+ In particular the message "Curl transaction has completed".
+ So we process those now.
+ */
+ processCurlMessages(envP, curlMultiP);
+
+ *transStillRunningP = runningHandles > 0;
+ }
+}
+
+
+
+static void
+curlMulti_finish(xmlrpc_env * const envP,
+ curlMulti * const curlMultiP,
+ xmlrpc_timeoutType const timeoutType,
+ xmlrpc_timespec const deadline,
+ int * const interruptP) {
+/*----------------------------------------------------------------------------
+ Prosecute all the Curl transactions under the control of
+ *curlMultiP. E.g. send data if server is ready to take it, get
+ data if server has sent some, wind up the transaction if it is
+ done.
+
+ Don't return until all the Curl transactions are done or we time out.
+
+ The *interruptP flag alone will not interrupt us. We will wait in
+ spite of it for all Curl transactions to complete. *interruptP
+ just gives us a hint that the Curl transactions are being
+ interrupted, so we know there is work to do for them. (The way it
+ works is Caller sets up a "progress" function that checks the same
+ interrupt flag and reports "kill me." When we see the interrupt
+ flag, we call that progress function and get the message).
+-----------------------------------------------------------------------------*/
+ bool rpcStillRunning;
+ bool timedOut;
+
+ rpcStillRunning = true; /* initial assumption */
+ timedOut = false;
+
+ while (rpcStillRunning && !timedOut && !envP->fault_occurred) {
+
+ if (interruptP) {
+ waitForWorkInt(envP, curlMultiP, timeoutType, deadline,
+ interruptP);
+ } else
+ waitForWork(envP, curlMultiP, timeoutType, deadline, NULL);
+
+ if (!envP->fault_occurred) {
+ xmlrpc_timespec nowTime;
+
+ /* doCurlWork() (among other things) finds Curl
+ transactions that user wants to abort and finishes
+ them.
+ */
+ doCurlWork(envP, curlMultiP, &rpcStillRunning);
+
+ xmlrpc_gettimeofday(&nowTime);
+
+ timedOut = (timeoutType == timeout_yes &&
+ timeIsAfter(nowTime, deadline));
+ }
+ }
+}
+
+
+
+/*===========================================================================*/
+
+
+static void
+startCurlTransaction(xmlrpc_env * const envP,
+ curlTransaction * const curlTransactionP,
+ curlMulti * const curlMultiP,
+ finishCurlTransactionFn finish) {
+
+ curlTransactionP->finish = finish;
+
+ /* A Curl session is serial -- it processes zero or one transaction
+ at a time. We use the "private" attribute of the Curl session to
+ indicate which transaction it is presently processing. This is
+ important when the transaction finishes, because libcurl will just
+ tell us that something finished on a particular session, not that
+ a particular transaction finished.
+ */
+ curl_easy_setopt(curlTransactionP->curlSessionP, CURLOPT_PRIVATE,
+ curlTransactionP);
+
+ curlMulti_addHandle(envP, curlMultiP, curlTransactionP);
+}
+
+
+
+static void
+getCurlTransactionError(curlTransaction * const curlTransactionP,
+ xmlrpc_env * const envP) {
+
+ if (curlTransactionP->result != CURLE_OK) {
+ /* We've seen Curl just return a null string for an explanation
+ (e.g. when TCP connect() fails because IP address doesn't exist).
+ */
+ const char * explanation;
+
+ if (strlen(curlTransactionP->curlError) == 0)
+ interpretCurlEasyError(&explanation, curlTransactionP->result);
+ else
+ xmlrpc_asprintf(&explanation, "%s", curlTransactionP->curlError);
+
+ xmlrpc_env_set_fault_formatted(
+ envP, XMLRPC_NETWORK_ERROR, "libcurl failed to execute the "
+ "HTTP POST transaction. %s", explanation);
+
+ xmlrpc_strfree(explanation);
+ } else {
+ CURLcode res;
+ long http_result;
+
+ res = curl_easy_getinfo(curlTransactionP->curlSessionP,
+ CURLINFO_HTTP_CODE, &http_result);
+
+ if (res != CURLE_OK)
+ xmlrpc_env_set_fault_formatted(
+ envP, XMLRPC_INTERNAL_ERROR,
+ "Curl performed the HTTP POST request, but was "
+ "unable to say what the HTTP result code was. "
+ "curl_easy_getinfo(CURLINFO_HTTP_CODE) says: %s",
+ curlTransactionP->curlError);
+ else {
+ if (http_result != 200)
+ xmlrpc_env_set_fault_formatted(
+ envP, XMLRPC_NETWORK_ERROR,
+ "HTTP response code is %ld, not 200",
+ http_result);
+ }
+ }
+}
+
+
+
+static void
+performCurlTransaction(xmlrpc_env * const envP,
+ curlTransaction * const curlTransactionP,
+ curlMulti * const curlMultiP,
+ int * const interruptP) {
+
+ void * const finish = NULL;
+ /* We don't need a finish function because we're going to wait here
+ for the transaction to complete and then do the next step
+ ourselves.
+ */
+
+ startCurlTransaction(envP, curlTransactionP, curlMultiP, finish);
+
+ /* Failure here just means something screwy in the multi manager;
+ Above does not even begin to perform the HTTP transaction
+ */
+
+ if (!envP->fault_occurred) {
+ xmlrpc_timespec const dummy = {0,0};
+
+ curlMulti_finish(envP, curlMultiP, timeout_no, dummy, interruptP);
+
+ /* Failure here just means something screwy in the multi
+ manager; any failure of the HTTP transaction would have been
+ recorded in *curlTransactionP.
+ */
+
+ if (!envP->fault_occurred) {
+ /* Curl session completed OK. But did HTTP transaction
+ work?
+ */
+ getCurlTransactionError(curlTransactionP, envP);
+ }
+ /* If the CURL transaction is still going, removing the handle
+ here aborts it. At least it's supposed to. From what I've
+ seen in the Curl code in 2007, I don't think it does. I
+ couldn't get Curl maintainers interested in the problem,
+ except to say, "If you're right, there's a bug."
+ */
+ curlMulti_removeHandle(curlMultiP, curlTransactionP);
+ }
+}
+
+
+
+struct xmlrpc_client_transport {
+ CURL * syncCurlSessionP;
+ /* Handle for a Curl library session object that we use for
+ all synchronous RPCs. An async RPC has one of its own,
+ and consequently does not share things such as persistent
+ connections and cookies with any other RPC.
+ */
+ lock * syncCurlSessionLockP;
+ /* Hold this lock while accessing or using *syncCurlSessionP.
+ You're using the session from the time you set any
+ attributes in it or start a transaction with it until any
+ transaction has finished and you've lost interest in any
+ attributes of the session.
+ */
+ curlMulti * syncCurlMultiP;
+ /* The Curl multi manager that this transport uses to execute
+ Curl transactions for RPCs requested via the synchronous
+ interface. The fact that there is never more than one such
+ transaction going at a time might make you wonder why a
+ "multi" manager is needed. The reason is that it is the only
+ interface in libcurl that gives us the flexibility to execute
+ the transaction with proper interruptibility. The only Curl
+ transaction ever attached to this multi manager is
+ 'syncCurlSessionP'.
+
+ This is constant (the handle, not the object).
+ */
+ curlMulti * asyncCurlMultiP;
+ /* The Curl multi manager that this transport uses to execute
+ Curl transactions for RPCs requested via the asynchronous
+ interface. Note that there may be multiple such Curl transactions
+ simultaneously and one can't wait for a particular one to finish;
+ the collection of asynchronous RPCs are an indivisible mass.
+
+ This is constant (the handle, not the object).
+ */
+ const char * userAgent;
+ /* Prefix for the User-Agent HTTP header, reflecting facilities
+ outside of Xmlrpc-c. The actual User-Agent header consists
+ of this prefix plus information about Xmlrpc-c. NULL means
+ none.
+
+ This is constant.
+ */
+ struct curlSetup curlSetupStuff;
+ /* This is constant */
+ int * interruptP;
+ /* Pointer to a value that user sets to nonzero to indicate he wants
+ the transport to give up on whatever it is doing and return ASAP.
+
+ NULL means none -- transport never gives up.
+ */
+};
+
+
+
+struct rpc {
+ struct xmlrpc_client_transport * transportP;
+ /* The client XML transport that transports this RPC */
+ curlTransaction * curlTransactionP;
+ /* The object which does the HTTP transaction, with no knowledge
+ of XML-RPC or Xmlrpc-c.
+ */
+ xmlrpc_mem_block * responseXmlP;
+ /* Where the response XML for this RPC should go or has gone. */
+ xmlrpc_transport_asynch_complete complete;
+ /* Routine to call to complete the RPC after it is complete HTTP-wise.
+ NULL if none.
+ */
+ struct xmlrpc_call_info * callInfoP;
+ /* User's identifier for this RPC */
+};
+
+
+static void
+lockSyncCurlSession(struct xmlrpc_client_transport * const transportP) {
+ transportP->syncCurlSessionLockP->lock(transportP->syncCurlSessionLockP);
+}
+
+
+
+static void
+unlockSyncCurlSession(struct xmlrpc_client_transport * const transportP) {
+ transportP->syncCurlSessionLockP->unlock(transportP->syncCurlSessionLockP);
+}
+
+
+
+static void
+initWindowsStuff(xmlrpc_env * const envP ATTR_UNUSED) {
+
+#if defined (WIN32)
+ /* This is CRITICAL so that cURL-Win32 works properly! */
+
+ /* So this commenter says, but I wonder why. libcurl should do the
+ required WSAStartup() itself, and it looks to me like it does.
+ -Bryan 06.01.01
+ */
+ WORD wVersionRequested;
+ WSADATA wsaData;
+ int err;
+ wVersionRequested = MAKEWORD(1, 1);
+
+ err = WSAStartup(wVersionRequested, &wsaData);
+ if (err)
+ xmlrpc_env_set_fault_formatted(
+ envP, XMLRPC_INTERNAL_ERROR,
+ "Winsock startup failed. WSAStartup returned rc %d", err);
+ else {
+ if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) {
+ /* Tell the user that we couldn't find a useable */
+ /* winsock.dll. */
+ xmlrpc_env_set_fault_formatted(
+ envP, XMLRPC_INTERNAL_ERROR, "Winsock reported that "
+ "it does not implement the requested version 1.1.");
+ }
+ if (envP->fault_occurred)
+ WSACleanup();
+ }
+#endif
+}
+
+
+
+static void
+termWindowsStuff(void) {
+
+#if defined (WIN32)
+ WSACleanup();
+#endif
+}
+
+
+
+static bool
+curlHasNosignal(void) {
+
+ bool retval;
+
+#if HAVE_CURL_NOSIGNAL
+ curl_version_info_data * const curlInfoP =
+ curl_version_info(CURLVERSION_NOW);
+
+ retval = (curlInfoP->version_num >= 0x070A00); /* 7.10.0 */
+#else
+ retval = false;
+#endif
+ return retval;
+}
+
+
+
+static void
+getTimeoutParm(xmlrpc_env * const envP,
+ const struct xmlrpc_curl_xportparms * const curlXportParmsP,
+ size_t const parmSize,
+ unsigned int * const timeoutP) {
+
+ if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(timeout))
+ *timeoutP = 0;
+ else {
+ if (curlHasNosignal()) {
+ /* libcurl takes a 'long' in milliseconds for the timeout value */
+ if ((curlXportParmsP->timeout + 999) / 1000 > LONG_MAX)
+ xmlrpc_faultf(envP, "Timeout value %u is too large.",
+ curlXportParmsP->timeout);
+ else
+ *timeoutP = curlXportParmsP->timeout;
+ } else
+ xmlrpc_faultf(envP, "You cannot specify a 'timeout' parameter "
+ "because the Curl library is too old and is not "
+ "capable of doing timeouts except by using "
+ "signals. You need at least Curl 7.10");
+ }
+}
+
+
+
+static void
+getXportParms(xmlrpc_env * const envP,
+ const struct xmlrpc_curl_xportparms * const curlXportParmsP,
+ size_t const parmSize,
+ struct xmlrpc_client_transport * const transportP) {
+/*----------------------------------------------------------------------------
+ Get the parameters out of *curlXportParmsP and update *transportP
+ to reflect them.
+
+ *curlXportParmsP is a 'parmSize' bytes long prefix of
+ struct xmlrpc_curl_xportparms.
+
+ curlXportParmsP is something the user created. It's designed to be
+ friendly to the user, not to this program, and is encumbered by
+ lots of backward compatibility constraints. In particular, the
+ user may have coded and/or compiled it at a time that struct
+ xmlrpc_curl_xportparms was smaller than it is now!
+
+ Also, the user might have specified something invalid.
+
+ So that's why we don't simply attach a copy of *curlXportParmsP to
+ *transportP.
+
+ To the extent that *curlXportParmsP is too small to contain a parameter,
+ we return the default value for that parameter.
+
+ Special case: curlXportParmsP == NULL means there is no input at all.
+ In that case, we return default values for everything.
+-----------------------------------------------------------------------------*/
+ struct curlSetup * const curlSetupP = &transportP->curlSetupStuff;
+
+ if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(user_agent))
+ transportP->userAgent = NULL;
+ else if (curlXportParmsP->user_agent == NULL)
+ transportP->userAgent = NULL;
+ else
+ transportP->userAgent = strdup(curlXportParmsP->user_agent);
+
+ if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(network_interface))
+ curlSetupP->networkInterface = NULL;
+ else if (curlXportParmsP->network_interface == NULL)
+ curlSetupP->networkInterface = NULL;
+ else
+ curlSetupP->networkInterface =
+ strdup(curlXportParmsP->network_interface);
+
+ if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(no_ssl_verifypeer))
+ curlSetupP->sslVerifyPeer = true;
+ else
+ curlSetupP->sslVerifyPeer = !curlXportParmsP->no_ssl_verifypeer;
+
+ if (!curlXportParmsP ||
+ parmSize < XMLRPC_CXPSIZE(no_ssl_verifyhost))
+ curlSetupP->sslVerifyHost = true;
+ else
+ curlSetupP->sslVerifyHost = !curlXportParmsP->no_ssl_verifyhost;
+
+ if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(ssl_cert))
+ curlSetupP->sslCert = NULL;
+ else if (curlXportParmsP->ssl_cert == NULL)
+ curlSetupP->sslCert = NULL;
+ else
+ curlSetupP->sslCert = strdup(curlXportParmsP->ssl_cert);
+
+ if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(sslcerttype))
+ curlSetupP->sslCertType = NULL;
+ else if (curlXportParmsP->sslcerttype == NULL)
+ curlSetupP->sslCertType = NULL;
+ else
+ curlSetupP->sslCertType = strdup(curlXportParmsP->sslcerttype);
+
+ if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(sslcertpasswd))
+ curlSetupP->sslCertPasswd = NULL;
+ else if (curlXportParmsP->sslcertpasswd == NULL)
+ curlSetupP->sslCertPasswd = NULL;
+ else
+ curlSetupP->sslCertPasswd = strdup(curlXportParmsP->sslcertpasswd);
+
+ if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(sslkey))
+ curlSetupP->sslKey = NULL;
+ else if (curlXportParmsP->sslkey == NULL)
+ curlSetupP->sslKey = NULL;
+ else
+ curlSetupP->sslKey = strdup(curlXportParmsP->sslkey);
+
+ if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(sslkeytype))
+ curlSetupP->sslKeyType = NULL;
+ else if (curlXportParmsP->sslkeytype == NULL)
+ curlSetupP->sslKeyType = NULL;
+ else
+ curlSetupP->sslKeyType = strdup(curlXportParmsP->sslkeytype);
+
+ if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(sslkeypasswd))
+ curlSetupP->sslKeyPasswd = NULL;
+ else if (curlXportParmsP->sslkeypasswd == NULL)
+ curlSetupP->sslKeyPasswd = NULL;
+ else
+ curlSetupP->sslKeyPasswd = strdup(curlXportParmsP->sslkeypasswd);
+
+ if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(sslengine))
+ curlSetupP->sslEngine = NULL;
+ else if (curlXportParmsP->sslengine == NULL)
+ curlSetupP->sslEngine = NULL;
+ else
+ curlSetupP->sslEngine = strdup(curlXportParmsP->sslengine);
+
+ if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(sslengine_default))
+ curlSetupP->sslEngineDefault = false;
+ else
+ curlSetupP->sslEngineDefault = !!curlXportParmsP->sslengine_default;
+
+ if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(sslversion))
+ curlSetupP->sslVersion = XMLRPC_SSLVERSION_DEFAULT;
+ else
+ curlSetupP->sslVersion = curlXportParmsP->sslversion;
+
+ if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(cainfo))
+ curlSetupP->caInfo = NULL;
+ else if (curlXportParmsP->cainfo == NULL)
+ curlSetupP->caInfo = NULL;
+ else
+ curlSetupP->caInfo = strdup(curlXportParmsP->cainfo);
+
+ if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(capath))
+ curlSetupP->caPath = NULL;
+ else if (curlXportParmsP->capath == NULL)
+ curlSetupP->caPath = NULL;
+ else
+ curlSetupP->caPath = strdup(curlXportParmsP->capath);
+
+ if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(randomfile))
+ curlSetupP->randomFile = NULL;
+ else if (curlXportParmsP->randomfile == NULL)
+ curlSetupP->randomFile = NULL;
+ else
+ curlSetupP->randomFile = strdup(curlXportParmsP->randomfile);
+
+ if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(egdsocket))
+ curlSetupP->egdSocket = NULL;
+ else if (curlXportParmsP->egdsocket == NULL)
+ curlSetupP->egdSocket = NULL;
+ else
+ curlSetupP->egdSocket = strdup(curlXportParmsP->egdsocket);
+
+ if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(ssl_cipher_list))
+ curlSetupP->sslCipherList = NULL;
+ else if (curlXportParmsP->ssl_cipher_list == NULL)
+ curlSetupP->sslCipherList = NULL;
+ else
+ curlSetupP->sslCipherList = strdup(curlXportParmsP->ssl_cipher_list);
+
+ getTimeoutParm(envP, curlXportParmsP, parmSize, &curlSetupP->timeout);
+}
+
+
+
+static void
+freeXportParms(const struct xmlrpc_client_transport * const transportP) {
- if (basicAuthInfo) {
- const char * authorizationHeader;
-
- casprintf(&authorizationHeader, "Authorization: %s", basicAuthInfo);
-
- if (authorizationHeader == NULL)
- xmlrpc_faultf(envP, "Couldn't allocate memory for "
- "Authorization header");
- else {
- addHeader(envP, headerListP, authorizationHeader);
+ const struct curlSetup * const curlSetupP = &transportP->curlSetupStuff;
- strfree(authorizationHeader);
- }
- }
+ if (curlSetupP->sslCipherList)
+ xmlrpc_strfree(curlSetupP->sslCipherList);
+ if (curlSetupP->egdSocket)
+ xmlrpc_strfree(curlSetupP->egdSocket);
+ if (curlSetupP->randomFile)
+ xmlrpc_strfree(curlSetupP->randomFile);
+ if (curlSetupP->caPath)
+ xmlrpc_strfree(curlSetupP->caPath);
+ if (curlSetupP->caInfo)
+ xmlrpc_strfree(curlSetupP->caInfo);
+ if (curlSetupP->sslEngine)
+ xmlrpc_strfree(curlSetupP->sslEngine);
+ if (curlSetupP->sslKeyPasswd)
+ xmlrpc_strfree(curlSetupP->sslKeyPasswd);
+ if (curlSetupP->sslKeyType)
+ xmlrpc_strfree(curlSetupP->sslKeyType);
+ if (curlSetupP->sslKey)
+ xmlrpc_strfree(curlSetupP->sslKey);
+ if (curlSetupP->sslCertPasswd)
+ xmlrpc_strfree(curlSetupP->sslCertPasswd);
+ if (curlSetupP->sslCertType)
+ xmlrpc_strfree(curlSetupP->sslCertType);
+ if (curlSetupP->sslCert)
+ xmlrpc_strfree(curlSetupP->sslCert);
+ if (curlSetupP->networkInterface)
+ xmlrpc_strfree(curlSetupP->networkInterface);
+ if (transportP->userAgent)
+ xmlrpc_strfree(transportP->userAgent);
}
static void
-createCurlHeaderList(xmlrpc_env * const envP,
- const xmlrpc_server_info * const serverP,
- const char * const userAgent,
- struct curl_slist ** const headerListP) {
+createSyncCurlSession(xmlrpc_env * const envP,
+ CURL ** const curlSessionPP) {
+/*----------------------------------------------------------------------------
+ Create a Curl session to be used for multiple serial transactions.
+ The Curl session we create is not complete -- it still has to be
+ further set up for each particular transaction.
- struct curl_slist * headerList;
+ We can't set up anything here that changes from one transaction to the
+ next.
- headerList = NULL; /* initial value - empty list */
+ We don't bother setting up anything that has to be set up for an
+ asynchronous transaction because code that is common between synchronous
+ and asynchronous transactions takes care of that anyway.
- addContentTypeHeader(envP, &headerList);
- if (!envP->fault_occurred) {
- addUserAgentHeader(envP, &headerList, userAgent);
- if (!envP->fault_occurred) {
- addAuthorizationHeader(envP, &headerList,
- serverP->_http_basic_auth);
- }
+ That leaves things, such as cookies, that don't exist for
+ asynchronous transactions, and are common to multiple serial
+ synchronous transactions.
+-----------------------------------------------------------------------------*/
+ CURL * const curlSessionP = curl_easy_init();
+
+ if (curlSessionP == NULL)
+ xmlrpc_faultf(envP, "Could not create Curl session. "
+ "curl_easy_init() failed.");
+ else {
+ /* The following is a trick. CURLOPT_COOKIEFILE is the name
+ of the file containing the initial cookies for the Curl
+ session. But setting it is also what turns on the cookie
+ function itself, whereby the Curl library accepts and
+ stores cookies from the server and sends them back on
+ future requests. We don't have a file of initial cookies, but
+ we want to turn on cookie function, so we set the option to
+ something we know does not validly name a file. Curl will
+ ignore the error and just start up cookie function with no
+ initial cookies.
+ */
+ curl_easy_setopt(curlSessionP, CURLOPT_COOKIEFILE, "");
+
+ *curlSessionPP = curlSessionP;
}
- if (envP->fault_occurred)
- curl_slist_free_all(headerList);
- else
- *headerListP = headerList;
}
static void
-setupCurlSession(xmlrpc_env * const envP,
- curlTransaction * const curlTransactionP,
- xmlrpc_mem_block * const callXmlP,
- xmlrpc_mem_block * const responseXmlP,
- const char * const networkInterface,
- xmlrpc_bool const sslVerifyPeer,
- xmlrpc_bool const sslVerifyHost) {
-
- CURL * const curlSessionP = curlTransactionP->curlSessionP;
+destroySyncCurlSession(CURL * const curlSessionP) {
- curl_easy_setopt(curlSessionP, CURLOPT_POST, 1);
- if (networkInterface)
- curl_easy_setopt(curlSessionP, CURLOPT_INTERFACE, networkInterface);
- curl_easy_setopt(curlSessionP, CURLOPT_URL, curlTransactionP->serverUrl);
- curl_easy_setopt(curlSessionP, CURLOPT_SSL_VERIFYPEER, sslVerifyPeer);
- curl_easy_setopt(curlSessionP, CURLOPT_SSL_VERIFYHOST,
- sslVerifyHost ? 2 : 0);
- XMLRPC_MEMBLOCK_APPEND(char, envP, callXmlP, "\0", 1);
- if (!envP->fault_occurred) {
- curl_easy_setopt(curlSessionP, CURLOPT_POSTFIELDS,
- XMLRPC_MEMBLOCK_CONTENTS(char, callXmlP));
-
- curl_easy_setopt(curlSessionP, CURLOPT_FILE, responseXmlP);
- curl_easy_setopt(curlSessionP, CURLOPT_HEADER, 0 );
- curl_easy_setopt(curlSessionP, CURLOPT_WRITEFUNCTION, collect);
- curl_easy_setopt(curlSessionP, CURLOPT_ERRORBUFFER,
- curlTransactionP->curlError);
- curl_easy_setopt(curlSessionP, CURLOPT_NOPROGRESS, 1);
-
- curl_easy_setopt(curlSessionP, CURLOPT_HTTPHEADER,
- curlTransactionP->headerList);
- }
+ curl_easy_cleanup(curlSessionP);
}
static void
-createCurlTransaction(xmlrpc_env * const envP,
- CURL * const curlSessionP,
- const xmlrpc_server_info * const serverP,
- xmlrpc_mem_block * const callXmlP,
- xmlrpc_mem_block * const responseXmlP,
- const char * const networkInterface,
- xmlrpc_bool const sslVerifyPeer,
- xmlrpc_bool const sslVerifyHost,
- const char * const userAgent,
- curlTransaction ** const curlTransactionPP) {
-
- curlTransaction * curlTransactionP;
+makeSyncCurlSession(xmlrpc_env * const envP,
+ struct xmlrpc_client_transport * const transportP) {
- MALLOCVAR(curlTransactionP);
- if (curlTransactionP == NULL)
- xmlrpc_faultf(envP, "No memory to create Curl transaction.");
+ transportP->syncCurlSessionLockP = createLock_pthread();
+ if (transportP->syncCurlSessionLockP == NULL)
+ xmlrpc_faultf(envP, "Unable to create lock for "
+ "synchronous Curl session.");
else {
- curlTransactionP->curlSessionP = curlSessionP;
+ createSyncCurlSession(envP, &transportP->syncCurlSessionP);
+
+ if (!envP->fault_occurred) {
+ /* We'll need a multi manager to actually execute this session: */
+ transportP->syncCurlMultiP = curlMulti_create();
+
+ if (transportP->syncCurlMultiP == NULL)
+ xmlrpc_faultf(envP, "Unable to create Curl multi manager for "
+ "synchronous RPCs");
- curlTransactionP->serverUrl = strdup(serverP->_server_url);
- if (curlTransactionP->serverUrl == NULL)
- xmlrpc_faultf(envP, "Out of memory to store server URL.");
- else {
- createCurlHeaderList(envP, serverP, userAgent,
- &curlTransactionP->headerList);
-
- if (!envP->fault_occurred)
- setupCurlSession(envP, curlTransactionP,
- callXmlP, responseXmlP,
- networkInterface,
- sslVerifyPeer, sslVerifyHost);
-
if (envP->fault_occurred)
- strfree(curlTransactionP->serverUrl);
+ destroySyncCurlSession(transportP->syncCurlSessionP);
}
if (envP->fault_occurred)
- free(curlTransactionP);
+ transportP->syncCurlSessionLockP->destroy(
+ transportP->syncCurlSessionLockP);
}
- *curlTransactionPP = curlTransactionP;
}
static void
-destroyCurlTransaction(curlTransaction * const curlTransactionP) {
+unmakeSyncCurlSession(struct xmlrpc_client_transport * const transportP) {
- curl_slist_free_all(curlTransactionP->headerList);
- strfree(curlTransactionP->serverUrl);
+ curlMulti_destroy(transportP->syncCurlMultiP);
- free(curlTransactionP);
+ destroySyncCurlSession(transportP->syncCurlSessionP);
+
+ transportP->syncCurlSessionLockP->destroy(
+ transportP->syncCurlSessionLockP);
}
-static void
-performCurlTransaction(xmlrpc_env * const envP,
- curlTransaction * const curlTransactionP) {
+static void
+create(xmlrpc_env * const envP,
+ int const flags ATTR_UNUSED,
+ const char * const appname ATTR_UNUSED,
+ const char * const appversion ATTR_UNUSED,
+ const void * const transportparmsP,
+ size_t const parm_size,
+ struct xmlrpc_client_transport ** const handlePP) {
+/*----------------------------------------------------------------------------
+ This does the 'create' operation for a Curl client transport.
+-----------------------------------------------------------------------------*/
+ const struct xmlrpc_curl_xportparms * const curlXportParmsP =
+ transportparmsP;
- CURL * const curlSessionP = curlTransactionP->curlSessionP;
+ struct xmlrpc_client_transport * transportP;
- CURLcode res;
+ assertConstantsMatch();
- res = curl_easy_perform(curlSessionP);
-
- if (res != CURLE_OK)
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_NETWORK_ERROR, "Curl failed to perform "
- "HTTP POST request. curl_easy_perform() says: %s",
- curlTransactionP->curlError);
+ MALLOCVAR(transportP);
+ if (transportP == NULL)
+ xmlrpc_faultf(envP, "Unable to allocate transport descriptor.");
else {
- CURLcode res;
- long http_result;
- res = curl_easy_getinfo(curlSessionP, CURLINFO_HTTP_CODE,
- &http_result);
+ transportP->interruptP = NULL;
- if (res != CURLE_OK)
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR,
- "Curl performed the HTTP POST request, but was "
- "unable to say what the HTTP result code was. "
- "curl_easy_getinfo(CURLINFO_HTTP_CODE) says: %s",
- curlTransactionP->curlError);
+ transportP->asyncCurlMultiP = curlMulti_create();
+
+ if (transportP->asyncCurlMultiP == NULL)
+ xmlrpc_faultf(envP, "Unable to create Curl multi manager for "
+ "asynchronous RPCs");
else {
- if (http_result != 200)
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_NETWORK_ERROR, "HTTP response: %ld",
- http_result);
+ getXportParms(envP, curlXportParmsP, parm_size, transportP);
+
+ if (!envP->fault_occurred) {
+ makeSyncCurlSession(envP, transportP);
+
+ if (envP->fault_occurred)
+ freeXportParms(transportP);
+ }
+ if (envP->fault_occurred)
+ curlMulti_destroy(transportP->asyncCurlMultiP);
}
+ if (envP->fault_occurred)
+ free(transportP);
}
+ *handlePP = transportP;
}
static void
-doAsyncRpc2(void * const arg) {
-
- rpc * const rpcP = arg;
+setInterrupt(struct xmlrpc_client_transport * const clientTransportP,
+ int * const interruptP) {
- xmlrpc_env env;
+ clientTransportP->interruptP = interruptP;
+}
- xmlrpc_env_init(&env);
- performCurlTransaction(&env, rpcP->curlTransactionP);
- rpcP->complete(rpcP->callInfoP, rpcP->responseXmlP, env);
+static void
+assertNoOutstandingCurlWork(curlMulti * const curlMultiP) {
+ xmlrpc_env env;
+ bool immediateWorkToDo;
+ int runningHandles;
+
+ xmlrpc_env_init(&env);
+
+ curlMulti_perform(&env, curlMultiP, &immediateWorkToDo, &runningHandles);
+
+ /* We know the above was a no-op, since we're asserting that there
+ is no outstanding work.
+ */
+ XMLRPC_ASSERT(!env.fault_occurred);
+ XMLRPC_ASSERT(!immediateWorkToDo);
+ XMLRPC_ASSERT(runningHandles == 0);
xmlrpc_env_clean(&env);
}
-#ifdef WIN32
-
-static unsigned __stdcall
-doAsyncRpc(void * arg) {
- doAsyncRpc2(arg);
- return 0;
-}
-
-#else
-static void *
-doAsyncRpc(void * arg) {
- doAsyncRpc2(arg);
- return NULL;
-}
-
-#endif
+static void
+destroy(struct xmlrpc_client_transport * const clientTransportP) {
+/*----------------------------------------------------------------------------
+ This does the 'destroy' operation for a Curl client transport.
+-----------------------------------------------------------------------------*/
+ XMLRPC_ASSERT(clientTransportP != NULL);
+ assertNoOutstandingCurlWork(clientTransportP->asyncCurlMultiP);
+ /* We know this is true because a condition of destroying the
+ transport is that there be no outstanding asynchronous RPCs.
+ */
+ assertNoOutstandingCurlWork(clientTransportP->syncCurlMultiP);
+ /* This is because a condition of destroying the transport is
+ that no transport method be running. The only way a
+ synchronous RPC can be in progress is for the 'perform' method
+ to be running.
+ */
+ unmakeSyncCurlSession(clientTransportP);
-static void
-createThread(xmlrpc_env * const envP,
- void * (*threadRoutine)(void *),
- rpc * const rpcP,
- pthread_t * const threadP) {
+ curlMulti_destroy(clientTransportP->asyncCurlMultiP);
- int rc;
+ freeXportParms(clientTransportP);
- rc = pthread_create(threadP, NULL, threadRoutine, rpcP);
- switch (rc) {
- case 0:
- break;
- case EAGAIN:
- xmlrpc_faultf(envP, "pthread_create() failed. "
- "System resources exceeded.");
- break;
- case EINVAL:
- xmlrpc_faultf(envP, "pthread_create() failed. "
- "Parameter error");
- break;
- case ENOMEM:
- xmlrpc_faultf(envP, "pthread_create() failed. "
- "No memory for new thread.");
- break;
- default:
- xmlrpc_faultf(envP, "pthread_create() failed. "
- "Unrecognized error code %d.", rc);
- break;
- }
+ free(clientTransportP);
}
@@ -751,33 +2084,25 @@
MALLOCVAR(rpcP);
if (rpcP == NULL)
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR,
- "Couldn't allocate memory for rpc object");
+ xmlrpc_faultf(envP, "Couldn't allocate memory for rpc object");
else {
- rpcP->callInfoP = callInfoP;
- rpcP->complete = complete;
+ rpcP->transportP = clientTransportP;
+ rpcP->callInfoP = callInfoP;
+ rpcP->complete = complete;
rpcP->responseXmlP = responseXmlP;
- rpcP->threadExists = FALSE;
- rpcP->curlSessionP = curlSessionP;
- createCurlTransaction(envP,
- curlSessionP,
- serverP,
- callXmlP, responseXmlP,
- clientTransportP->networkInterface,
- clientTransportP->sslVerifyPeer,
- clientTransportP->sslVerifyHost,
- clientTransportP->userAgent,
- &rpcP->curlTransactionP);
+ curlTransaction_create(envP,
+ curlSessionP,
+ serverP,
+ callXmlP, responseXmlP,
+ clientTransportP->userAgent,
+ &clientTransportP->curlSetupStuff,
+ rpcP,
+ clientTransportP->interruptP,
+ &rpcP->curlTransactionP);
if (!envP->fault_occurred) {
- list_init_header(&rpcP->link, rpcP);
- pthread_mutex_lock(&clientTransportP->listLock);
- list_add_head(&clientTransportP->rpcList, &rpcP->link);
- pthread_mutex_unlock(&clientTransportP->listLock);
-
if (envP->fault_occurred)
- destroyCurlTransaction(rpcP->curlTransactionP);
+ curlTransaction_destroy(rpcP->curlTransactionP);
}
if (envP->fault_occurred)
free(rpcP);
@@ -791,11 +2116,8 @@
destroyRpc(rpc * const rpcP) {
XMLRPC_ASSERT_PTR_OK(rpcP);
- XMLRPC_ASSERT(!rpcP->threadExists);
-
- destroyCurlTransaction(rpcP->curlTransactionP);
- list_remove(&rpcP->link);
+ curlTransaction_destroy(rpcP->curlTransactionP);
free(rpcP);
}
@@ -804,9 +2126,52 @@
static void
performRpc(xmlrpc_env * const envP,
- rpc * const rpcP) {
+ rpc * const rpcP,
+ curlMulti * const curlMultiP,
+ int * const interruptP) {
+
+ performCurlTransaction(envP, rpcP->curlTransactionP, curlMultiP,
+ interruptP);
+}
+
+
+
+static finishCurlTransactionFn finishRpcCurlTransaction;
+
+static void
+finishRpcCurlTransaction(xmlrpc_env * const envP ATTR_UNUSED,
+ curlTransaction * const curlTransactionP) {
+/*----------------------------------------------------------------------------
+ Handle the event that a Curl transaction for an asynchronous RPC has
+ completed on the Curl session identified by 'curlSessionP'.
+
+ Tell the requester of the RPC the results.
+
+ Remove the Curl session from its Curl multi manager and destroy the
+ Curl session, the XML response buffer, the Curl transaction, and the RPC.
+-----------------------------------------------------------------------------*/
+ rpc * const rpcP = curlTransactionP->rpcP;
+ struct xmlrpc_client_transport * const transportP = rpcP->transportP;
+
+ {
+ xmlrpc_env env;
+
+ xmlrpc_env_init(&env);
+
+ getCurlTransactionError(curlTransactionP, &env);
+
+ rpcP->complete(rpcP->callInfoP, rpcP->responseXmlP, env);
+
+ xmlrpc_env_clean(&env);
+ }
+
+ curlMulti_removeHandle(transportP->asyncCurlMultiP, curlTransactionP);
- performCurlTransaction(envP, rpcP->curlTransactionP);
+ curl_easy_cleanup(curlTransactionP->curlSessionP);
+
+ XMLRPC_MEMBLOCK_FREE(char, rpcP->responseXmlP);
+
+ destroyRpc(rpcP);
}
@@ -815,9 +2180,10 @@
startRpc(xmlrpc_env * const envP,
rpc * const rpcP) {
- createThread(envP, &doAsyncRpc, rpcP, &rpcP->thread);
- if (!envP->fault_occurred)
- rpcP->threadExists = TRUE;
+ startCurlTransaction(envP,
+ rpcP->curlTransactionP,
+ rpcP->transportP->asyncCurlMultiP,
+ &finishRpcCurlTransaction);
}
@@ -850,10 +2216,9 @@
"curl_easy_init() failed.");
else {
createRpc(envP, clientTransportP, curlSessionP, serverP,
- callXmlP, responseXmlP,
- complete, callInfoP,
+ callXmlP, responseXmlP, complete, callInfoP,
&rpcP);
-
+
if (!envP->fault_occurred) {
startRpc(envP, rpcP);
@@ -866,59 +2231,86 @@
if (envP->fault_occurred)
XMLRPC_MEMBLOCK_FREE(char, responseXmlP);
}
- /* The user's eventual finish_asynch call will destroy this RPC,
- Curl session, and response buffer
+ /* If we're returning success, the user's eventual finish_asynch
+ call will destroy this RPC, Curl session, and response buffer
+ and remove the Curl session from the Curl multi manager.
+ (If we're returning failure, we didn't create any of those).
*/
}
-static void *
-finishRpc(struct list_head * const headerP,
- void * const context ATTR_UNUSED) {
-
- rpc * const rpcP = headerP->itemP;
-
- if (rpcP->threadExists) {
- void *status;
- int result;
-
- result = pthread_join(rpcP->thread, &status);
-
- rpcP->threadExists = FALSE;
- }
-
- XMLRPC_MEMBLOCK_FREE(char, rpcP->responseXmlP);
+static void
+finishAsynch(
+ struct xmlrpc_client_transport * const clientTransportP,
+ xmlrpc_timeoutType const timeoutType,
+ xmlrpc_timeout const timeout) {
+/*----------------------------------------------------------------------------
+ Wait for the Curl multi manager to finish the Curl transactions for
+ all outstanding RPCs and destroy those RPCs.
- curl_easy_cleanup(rpcP->curlSessionP);
+ But give up if a) too much time passes as defined by 'timeoutType'
+ and 'timeout'; or b) the transport client requests interruption
+ (i.e. the transport's interrupt flag becomes nonzero). Normally, a
+ signal must get our attention for us to notice the interrupt flag.
- destroyRpc(rpcP);
+ This does the 'finish_asynch' operation for a Curl client transport.
- return NULL;
-}
+ It would be cool to replace this with something analogous to the
+ Curl asynchronous interface: Have something like curl_multi_fdset()
+ that returns a bunch of file descriptors on which the user can wait
+ (along with possibly other file descriptors of his own) and
+ something like curl_multi_perform() to finish whatever RPCs are
+ ready to finish at that moment. The implementation would be little
+ more than wrapping curl_multi_fdset() and curl_multi_perform().
+
+ Note that the user can call this multiple times, due to timeouts,
+ but must eventually call it once with no timeout so he
+ knows that all the RPCs are finished. Either that or terminate the
+ process so it doesn't matter if RPCs are still going.
+-----------------------------------------------------------------------------*/
+ xmlrpc_env env;
+ xmlrpc_timespec waitTimeoutTime;
+ /* The datetime after which we should quit waiting */
+ xmlrpc_env_init(&env);
+
+ if (timeoutType == timeout_yes) {
+ xmlrpc_timespec waitStartTime;
+ xmlrpc_gettimeofday(&waitStartTime);
+ addMilliseconds(waitStartTime, timeout, &waitTimeoutTime);
+ }
-static void
-finishAsynch(
- struct xmlrpc_client_transport * const clientTransportP ATTR_UNUSED,
- xmlrpc_timeoutType const timeoutType ATTR_UNUSED,
- xmlrpc_timeout const timeout ATTR_UNUSED) {
-/*----------------------------------------------------------------------------
- Wait for the threads of all outstanding RPCs to exit and destroy those
- RPCs.
+ curlMulti_finish(&env, clientTransportP->asyncCurlMultiP,
+ timeoutType, waitTimeoutTime,
+ clientTransportP->interruptP);
+
+ /* If the above fails, it is catastrophic, because it means there is
+ no way to complete outstanding Curl transactions and RPCs, and
+ no way to release their resources.
+
+ We should at least expand this interface some day to push the
+ problem back up the user, but for now we just do this Hail Mary
+ response.
+
+ Note that a failure of curlMult_finish() does not mean that
+ a session completed with an error or an RPC completed with an
+ error. Those things are reported up through the user's
+ xmlrpc_transport_asynch_complete routine. A failure here is
+ something that stopped us from calling that.
- This does the 'finish_asynch' operation for a Curl client transport.
------------------------------------------------------------------------------*/
- /* We ignore any timeout request. Some day, we should figure out how
- to set an alarm and interrupt running threads.
+ Note that a timeout causes a successful completion,
+ but without finishing all the RPCs!
*/
- pthread_mutex_lock(&clientTransportP->listLock);
-
- list_foreach(&clientTransportP->rpcList, finishRpc, NULL);
+ if (env.fault_occurred)
+ fprintf(stderr, "finishAsync() failed. Xmlrpc-c Curl transport "
+ "is now in an unknown state and may not be able to "
+ "continue functioning. Specifics of the failure: %s\n",
+ env.fault_string);
- pthread_mutex_unlock(&clientTransportP->listLock);
+ xmlrpc_env_clean(&env);
}
@@ -928,7 +2320,7 @@
struct xmlrpc_client_transport * const clientTransportP,
const xmlrpc_server_info * const serverP,
xmlrpc_mem_block * const callXmlP,
- xmlrpc_mem_block ** const responsePP) {
+ xmlrpc_mem_block ** const responseXmlPP) {
xmlrpc_mem_block * responseXmlP;
rpc * rpcP;
@@ -936,11 +2328,14 @@
XMLRPC_ASSERT_ENV_OK(envP);
XMLRPC_ASSERT_PTR_OK(serverP);
XMLRPC_ASSERT_PTR_OK(callXmlP);
- XMLRPC_ASSERT_PTR_OK(responsePP);
+ XMLRPC_ASSERT_PTR_OK(responseXmlPP);
responseXmlP = XMLRPC_MEMBLOCK_NEW(char, envP, 0);
if (!envP->fault_occurred) {
- pthread_mutex_lock(&clientTransportP->syncCurlSessionLock);
+ /* Only one RPC at a time can use a Curl session, so we have to
+ hold the lock as long as our RPC exists.
+ */
+ lockSyncCurlSession(clientTransportP);
createRpc(envP, clientTransportP, clientTransportP->syncCurlSessionP,
serverP,
callXmlP, responseXmlP,
@@ -948,13 +2343,14 @@
&rpcP);
if (!envP->fault_occurred) {
- performRpc(envP, rpcP);
+ performRpc(envP, rpcP, clientTransportP->syncCurlMultiP,
+ clientTransportP->interruptP);
+
+ *responseXmlPP = responseXmlP;
- *responsePP = responseXmlP;
-
destroyRpc(rpcP);
}
- pthread_mutex_unlock(&clientTransportP->syncCurlSessionLock);
+ unlockSyncCurlSession(clientTransportP);
if (envP->fault_occurred)
XMLRPC_MEMBLOCK_FREE(char, responseXmlP);
}
@@ -962,10 +2358,46 @@
+static void
+setupGlobalConstants(xmlrpc_env * const envP) {
+/*----------------------------------------------------------------------------
+ See longwinded discussion of the global constant issue at the top of
+ this file.
+-----------------------------------------------------------------------------*/
+ initWindowsStuff(envP);
+
+ if (!envP->fault_occurred) {
+ CURLcode rc;
+
+ rc = curl_global_init(CURL_GLOBAL_ALL);
+
+ if (rc != CURLE_OK)
+ xmlrpc_faultf(envP, "curl_global_init() failed with code %d", rc);
+ }
+}
+
+
+
+static void
+teardownGlobalConstants(void) {
+/*----------------------------------------------------------------------------
+ See longwinded discussionof the global constant issue at the top of
+ this file.
+-----------------------------------------------------------------------------*/
+ curl_global_cleanup();
+
+ termWindowsStuff();
+}
+
+
+
struct xmlrpc_client_transport_ops xmlrpc_curl_transport_ops = {
+ &setupGlobalConstants,
+ &teardownGlobalConstants,
&create,
&destroy,
&sendRequest,
&call,
&finishAsynch,
+ &setInterrupt,
};
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/expat/expat.html
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/expat/expat.html (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/expat/expat.html Fri May 23 16:56:24 2008
@@ -9,6 +9,9 @@
<H1>expat - XML Parser Toolkit</H1>
+<p>This is outdated stuff from the independently developed Expat which
+was forked in 2001 to make the Xmlrpc-c embedded version.
+
<H3>Version 1.2</H3>
<P>Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center
@@ -23,6 +26,10 @@
option. See the comment above <CODE>XML_SetParamEntityParsing</CODE>
in <CODE>xmlparse.h</CODE> for the API addition that enables this.</P>
+<p>For Xmlrpc-c, we find no reason to exclude this function from the
+library, and ifdefs make code harder to maintain, so we include the
+function unconditionally. (i.e. -DXML_DTD does nothing).
+
<P>Expat is an <A
HREF="http://www.w3.org/TR/1998/REC-xml-19980210">XML 1.0</A> parser
written in C. It aims to be fully conforming. It is currently not a
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/expat/gennmtab/Makefile
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/expat/gennmtab/Makefile (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/expat/gennmtab/Makefile Fri May 23 16:56:24 2008
@@ -1,18 +1,23 @@
-ifeq ($(SRCDIR)x,x)
-SRCDIR = $(CURDIR)/../../..
+ifeq ($(SRCDIR),)
+ updir = $(shell echo $(dir $(1)) | sed 's/.$$//')
+ EXPATDIR := $(call updir,$(CURDIR))
+ LIBDIR := $(call updir,$(EXPATDIR))
+ SRCDIR := $(call updir,$(LIBDIR))
+ BLDDIR := $(SRCDIR)
endif
+SUBDIR := lib/expat/gennmtab
-include $(SRCDIR)/Makefile.config
+include $(BLDDIR)/config.mk
CFLAGS = $(CFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD)
LDFLAGS = $(LADD)
-INCLUDES = -I$(SRCDIR) -I$(SRCDIR)/lib/util/include
+INCLUDES = -I$(BLDDIR) -I$(SRCDIR)/lib/util/include
default: all
-include $(SRCDIR)/Makefile.common
+include $(SRCDIR)/common.mk
.PHONY: all
all: gennmtab
@@ -37,9 +42,9 @@
dep: dep-common
gennmtab.o:%.o:%.c
- $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES)
+ $(BUILDTOOL_CC) -c $< -o $@ $(CFLAGS) $(INCLUDES)
gennmtab:%:%.o
- $(LINK) -o $@ $(LDFLAGS) $(CFLAGS) $^
+ $(BUILDTOOL_CCLD) -o $@ $(LDFLAGS) $^
include Makefile.depend
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmlparse/xmlparse.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmlparse/xmlparse.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmlparse/xmlparse.c Fri May 23 16:56:24 2008
@@ -3,24 +3,55 @@
See the file copying.txt for copying permission.
*/
+/* In 2001, this was part of the Expat package. We copied it into
+ Xmlrpc-c because it's easier on the user than making him get and
+ link Expat separately, and we don't expect to benefit from separate
+ maintenance of Expat.
+
+ But we changed all the external symbols that in Expat are named
+ "XML_xxxx" to "xmlrpc_XML_xxxx" because people do link Xmlrpc-c
+ libraries into programs that also link Expat (a good example is
+ where an Apache module uses Xmlrpc-c). We don't want our names to
+ collide with Expat's.
+*/
+
+#include <stddef.h>
+#include <assert.h>
+
+#include "xmlrpc_config.h"
+#include "c_util.h"
+#include "girmath.h"
+#include "mallocvar.h"
+#include "xmlrpc-c/string_int.h"
#include "xmldef.h"
#include "xmlparse.h"
-#include <stddef.h>
+
+static const char *
+extractXmlSample(const char * const start,
+ const char * const end,
+ size_t const maximumLen) {
+
+ size_t const len = MIN(maximumLen, (size_t)(end - start));
+
+ return xmlrpc_makePrintable_lp(start, len);
+}
+
+
#ifdef XML_UNICODE
#define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX
#define XmlConvert XmlUtf16Convert
-#define XmlGetInternalEncoding XmlGetUtf16InternalEncoding
-#define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS
-#define XmlEncode XmlUtf16Encode
+#define XmlGetInternalEncoding xmlrpc_XmlGetUtf16InternalEncoding
+#define XmlGetInternalEncodingNS xmlrpc_XmlGetUtf16InternalEncodingNS
+#define XmlEncode xmlrpc_XmlUtf16Encode
#define MUST_CONVERT(enc, s) (!(enc)->isUtf16 || (((unsigned long)s) & 1))
typedef unsigned short ICHAR;
#else
#define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX
#define XmlConvert XmlUtf8Convert
-#define XmlGetInternalEncoding XmlGetUtf8InternalEncoding
-#define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS
-#define XmlEncode XmlUtf8Encode
+#define XmlGetInternalEncoding xmlrpc_XmlGetUtf8InternalEncoding
+#define XmlGetInternalEncodingNS xmlrpc_XmlGetUtf8InternalEncodingNS
+#define XmlEncode xmlrpc_XmlUtf8Encode
#define MUST_CONVERT(enc, s) (!(enc)->isUtf8)
typedef char ICHAR;
#endif
@@ -162,9 +193,7 @@
STRING_POOL pool;
int complete;
int standalone;
-#ifdef XML_DTD
HASH_TABLE paramEntities;
-#endif /* XML_DTD */
PREFIX defaultPrefix;
} DTD;
@@ -175,94 +204,13 @@
ENTITY *entity;
} OPEN_INTERNAL_ENTITY;
-typedef enum XML_Error Processor(XML_Parser parser,
- const char *start,
- const char *end,
- const char **endPtr);
-
-static Processor prologProcessor;
-static Processor prologInitProcessor;
-static Processor contentProcessor;
-static Processor cdataSectionProcessor;
-#ifdef XML_DTD
-static Processor ignoreSectionProcessor;
-#endif /* XML_DTD */
-static Processor epilogProcessor;
-static Processor errorProcessor;
-static Processor externalEntityInitProcessor;
-static Processor externalEntityInitProcessor2;
-static Processor externalEntityInitProcessor3;
-static Processor externalEntityContentProcessor;
-
-static enum XML_Error
-handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName);
-static enum XML_Error
-processXmlDecl(XML_Parser parser, int isGeneralTextEntity, const char *, const char *);
-static enum XML_Error
-initializeEncoding(XML_Parser parser);
-static enum XML_Error
-doProlog(XML_Parser parser, const ENCODING *enc, const char *s,
- const char *end, int tok, const char *next, const char **nextPtr);
-static enum XML_Error
-processInternalParamEntity(XML_Parser parser, ENTITY *entity);
-static enum XML_Error
-doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
- const char *start, const char *end, const char **endPtr);
-static enum XML_Error
-doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr, const char *end, const char **nextPtr);
-#ifdef XML_DTD
-static enum XML_Error
-doIgnoreSection(XML_Parser parser, const ENCODING *, const char **startPtr, const char *end, const char **nextPtr);
-#endif /* XML_DTD */
-static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *, const char *s,
- TAG_NAME *tagNamePtr, BINDING **bindingsPtr);
-static
-int addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, const XML_Char *uri, BINDING **bindingsPtr);
-static int
-defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, int isCdata, int isId, const XML_Char *dfltValue);
-static enum XML_Error
-storeAttributeValue(XML_Parser parser, const ENCODING *, int isCdata, const char *, const char *,
- STRING_POOL *);
-static enum XML_Error
-appendAttributeValue(XML_Parser parser, const ENCODING *, int isCdata, const char *, const char *,
- STRING_POOL *);
-static ATTRIBUTE_ID *
-getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
-static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *);
-static enum XML_Error
-storeEntityValue(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
-static int
-reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
-static int
-reportComment(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
-static void
-reportDefault(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
+typedef void Processor(XML_Parser parser,
+ const char * const start,
+ const char * const end,
+ const char ** const endPtr,
+ enum XML_Error * const errorCodeP,
+ const char ** const errorP);
-static const XML_Char *getContext(XML_Parser parser);
-static int setContext(XML_Parser parser, const XML_Char *context);
-static void normalizePublicId(XML_Char *s);
-static int dtdInit(DTD *);
-static void dtdDestroy(DTD *);
-static int dtdCopy(DTD *newDtd, const DTD *oldDtd);
-static int copyEntityTable(HASH_TABLE *, STRING_POOL *, const HASH_TABLE *);
-#ifdef XML_DTD
-static void dtdSwap(DTD *, DTD *);
-#endif /* XML_DTD */
-static NAMED *lookup(HASH_TABLE *table, KEY name, size_t createSize);
-static void hashTableInit(HASH_TABLE *);
-static void hashTableDestroy(HASH_TABLE *);
-static void hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *);
-static NAMED *hashTableIterNext(HASH_TABLE_ITER *);
-static void poolInit(STRING_POOL *);
-static void poolClear(STRING_POOL *);
-static void poolDestroy(STRING_POOL *);
-static XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc,
- const char *ptr, const char *end);
-static XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc,
- const char *ptr, const char *end);
-static int poolGrow(STRING_POOL *pool);
-static const XML_Char *poolCopyString(STRING_POOL *pool, const XML_Char *s);
-static const XML_Char *poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n);
#define poolStart(pool) ((pool)->start)
#define poolEnd(pool) ((pool)->ptr)
@@ -322,7 +270,18 @@
void (*m_unknownEncodingRelease)(void *);
PROLOG_STATE m_prologState;
Processor *m_processor;
+ /* The next processor to run */
enum XML_Error m_errorCode;
+ /* Explanation of the failure of the most recent call to Expat.
+ XML_ERROR_NONE means it didn't fail. This is redundant with
+ m_errorString if the latter is non-null.
+ The latter is newer and better.
+ */
+ const char * m_errorString;
+ /* malloc'ed string describing the failure of the most recent call
+ to Expat. NULL means m_errorCode is the only error information
+ available.
+ */
const char *m_eventPtr;
const char *m_eventEndPtr;
const char *m_positionPtr;
@@ -353,10 +312,8 @@
unsigned m_groupSize;
int m_hadExternalDoctype;
XML_Char m_namespaceSeparator;
-#ifdef XML_DTD
enum XML_ParamEntityParsing m_paramEntityParsing;
XML_Parser m_parentParser;
-#endif
} Parser;
#define userData (((Parser *)parser)->m_userData)
@@ -381,7 +338,6 @@
#define externalEntityRefHandler (((Parser *)parser)->m_externalEntityRefHandler)
#define externalEntityRefHandlerArg (((Parser *)parser)->m_externalEntityRefHandlerArg)
#define unknownEncodingHandler (((Parser *)parser)->m_unknownEncodingHandler)
-#define encoding (((Parser *)parser)->m_encoding)
#define initEncoding (((Parser *)parser)->m_initEncoding)
#define internalEncoding (((Parser *)parser)->m_internalEncoding)
#define unknownEncodingMem (((Parser *)parser)->m_unknownEncodingMem)
@@ -394,6 +350,7 @@
#define prologState (((Parser *)parser)->m_prologState)
#define processor (((Parser *)parser)->m_processor)
#define errorCode (((Parser *)parser)->m_errorCode)
+#define errorString (((Parser *)parser)->m_errorString)
#define eventPtr (((Parser *)parser)->m_eventPtr)
#define eventEndPtr (((Parser *)parser)->m_eventEndPtr)
#define positionPtr (((Parser *)parser)->m_positionPtr)
@@ -432,1183 +389,1414 @@
#define groupSize (((Parser *)parser)->m_groupSize)
#define hadExternalDoctype (((Parser *)parser)->m_hadExternalDoctype)
#define namespaceSeparator (((Parser *)parser)->m_namespaceSeparator)
-#ifdef XML_DTD
#define parentParser (((Parser *)parser)->m_parentParser)
#define paramEntityParsing (((Parser *)parser)->m_paramEntityParsing)
-#endif /* XML_DTD */
-#ifdef _MSC_VER
-#ifdef _DEBUG
-Parser *asParser(XML_Parser parser)
+
+
+static
+void poolInit(STRING_POOL *pool)
{
- return parser;
+ pool->blocks = 0;
+ pool->freeBlocks = 0;
+ pool->start = 0;
+ pool->ptr = 0;
+ pool->end = 0;
}
-#endif
-#endif
-XML_Parser XML_ParserCreate(const XML_Char *encodingName)
+static
+void poolClear(STRING_POOL *pool)
{
- XML_Parser parser = malloc(sizeof(Parser));
- if (!parser)
- return parser;
- processor = prologInitProcessor;
- XmlPrologStateInit(&prologState);
- userData = 0;
- handlerArg = 0;
- startElementHandler = 0;
- endElementHandler = 0;
- characterDataHandler = 0;
- processingInstructionHandler = 0;
- commentHandler = 0;
- startCdataSectionHandler = 0;
- endCdataSectionHandler = 0;
- defaultHandler = 0;
- startDoctypeDeclHandler = 0;
- endDoctypeDeclHandler = 0;
- unparsedEntityDeclHandler = 0;
- notationDeclHandler = 0;
- externalParsedEntityDeclHandler = 0;
- internalParsedEntityDeclHandler = 0;
- startNamespaceDeclHandler = 0;
- endNamespaceDeclHandler = 0;
- notStandaloneHandler = 0;
- externalEntityRefHandler = 0;
- externalEntityRefHandlerArg = parser;
- unknownEncodingHandler = 0;
- buffer = 0;
- bufferPtr = 0;
- bufferEnd = 0;
- parseEndByteIndex = 0;
- parseEndPtr = 0;
- bufferLim = 0;
- declElementType = 0;
- declAttributeId = 0;
- declEntity = 0;
- declNotationName = 0;
- declNotationPublicId = 0;
- memset(&position, 0, sizeof(POSITION));
- errorCode = XML_ERROR_NONE;
- eventPtr = 0;
- eventEndPtr = 0;
- positionPtr = 0;
- openInternalEntities = 0;
- tagLevel = 0;
- tagStack = 0;
- freeTagList = 0;
- freeBindingList = 0;
- inheritedBindings = 0;
- attsSize = INIT_ATTS_SIZE;
- atts = malloc(attsSize * sizeof(ATTRIBUTE));
- nSpecifiedAtts = 0;
- dataBuf = malloc(INIT_DATA_BUF_SIZE * sizeof(XML_Char));
- groupSize = 0;
- groupConnector = 0;
- hadExternalDoctype = 0;
- unknownEncodingMem = 0;
- unknownEncodingRelease = 0;
- unknownEncodingData = 0;
- unknownEncodingHandlerData = 0;
- namespaceSeparator = '!';
-#ifdef XML_DTD
- parentParser = 0;
- paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
-#endif
- ns = 0;
- poolInit(&tempPool);
- poolInit(&temp2Pool);
- protocolEncodingName = encodingName ? poolCopyString(&tempPool, encodingName) : 0;
- curBase = 0;
- if (!dtdInit(&dtd) || !atts || !dataBuf
- || (encodingName && !protocolEncodingName)) {
- XML_ParserFree(parser);
- return 0;
+ if (!pool->freeBlocks)
+ pool->freeBlocks = pool->blocks;
+ else {
+ BLOCK *p = pool->blocks;
+ while (p) {
+ BLOCK *tem = p->next;
+ p->next = pool->freeBlocks;
+ pool->freeBlocks = p;
+ p = tem;
+ }
}
- dataBufEnd = dataBuf + INIT_DATA_BUF_SIZE;
- XmlInitEncoding(&initEncoding, &encoding, 0);
- internalEncoding = XmlGetInternalEncoding();
- return parser;
+ pool->blocks = 0;
+ pool->start = 0;
+ pool->ptr = 0;
+ pool->end = 0;
}
-XML_Parser XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep)
+static
+void poolDestroy(STRING_POOL *pool)
{
- static
- const XML_Char implicitContext[] = {
- XML_T('x'), XML_T('m'), XML_T('l'), XML_T('='),
- XML_T('h'), XML_T('t'), XML_T('t'), XML_T('p'), XML_T(':'),
- XML_T('/'), XML_T('/'), XML_T('w'), XML_T('w'), XML_T('w'),
- XML_T('.'), XML_T('w'), XML_T('3'),
- XML_T('.'), XML_T('o'), XML_T('r'), XML_T('g'),
- XML_T('/'), XML_T('X'), XML_T('M'), XML_T('L'),
- XML_T('/'), XML_T('1'), XML_T('9'), XML_T('9'), XML_T('8'),
- XML_T('/'), XML_T('n'), XML_T('a'), XML_T('m'), XML_T('e'),
- XML_T('s'), XML_T('p'), XML_T('a'), XML_T('c'), XML_T('e'),
- XML_T('\0')
- };
-
- XML_Parser parser = XML_ParserCreate(encodingName);
- if (parser) {
- XmlInitEncodingNS(&initEncoding, &encoding, 0);
- ns = 1;
- internalEncoding = XmlGetInternalEncodingNS();
- namespaceSeparator = nsSep;
+ BLOCK *p = pool->blocks;
+ while (p) {
+ BLOCK *tem = p->next;
+ free(p);
+ p = tem;
}
- if (!setContext(parser, implicitContext)) {
- XML_ParserFree(parser);
- return 0;
+ pool->blocks = 0;
+ p = pool->freeBlocks;
+ while (p) {
+ BLOCK *tem = p->next;
+ free(p);
+ p = tem;
}
- return parser;
+ pool->freeBlocks = 0;
+ pool->ptr = 0;
+ pool->start = 0;
+ pool->end = 0;
}
-int XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName)
+static
+int poolGrow(STRING_POOL *pool)
{
- if (!encodingName)
- protocolEncodingName = 0;
+ if (pool->freeBlocks) {
+ if (pool->start == 0) {
+ pool->blocks = pool->freeBlocks;
+ pool->freeBlocks = pool->freeBlocks->next;
+ pool->blocks->next = 0;
+ pool->start = pool->blocks->s;
+ pool->end = pool->start + pool->blocks->size;
+ pool->ptr = pool->start;
+ return 1;
+ }
+ if (pool->end - pool->start < pool->freeBlocks->size) {
+ BLOCK *tem = pool->freeBlocks->next;
+ pool->freeBlocks->next = pool->blocks;
+ pool->blocks = pool->freeBlocks;
+ pool->freeBlocks = tem;
+ memcpy(pool->blocks->s, pool->start,
+ (pool->end - pool->start) * sizeof(XML_Char));
+ pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
+ pool->start = pool->blocks->s;
+ pool->end = pool->start + pool->blocks->size;
+ return 1;
+ }
+ }
+ if (pool->blocks && pool->start == pool->blocks->s) {
+ int blockSize = (pool->end - pool->start)*2;
+ pool->blocks = realloc(pool->blocks, offsetof(BLOCK, s) +
+ blockSize * sizeof(XML_Char));
+ if (!pool->blocks)
+ return 0;
+ pool->blocks->size = blockSize;
+ pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
+ pool->start = pool->blocks->s;
+ pool->end = pool->start + blockSize;
+ }
else {
- protocolEncodingName = poolCopyString(&tempPool, encodingName);
- if (!protocolEncodingName)
+ BLOCK *tem;
+ int blockSize = pool->end - pool->start;
+ if (blockSize < INIT_BLOCK_SIZE)
+ blockSize = INIT_BLOCK_SIZE;
+ else
+ blockSize *= 2;
+ tem = malloc(offsetof(BLOCK, s) + blockSize * sizeof(XML_Char));
+ if (!tem)
return 0;
+ tem->size = blockSize;
+ tem->next = pool->blocks;
+ pool->blocks = tem;
+ if (pool->ptr != pool->start)
+ memcpy(tem->s, pool->start,
+ (pool->ptr - pool->start) * sizeof(XML_Char));
+ pool->ptr = tem->s + (pool->ptr - pool->start);
+ pool->start = tem->s;
+ pool->end = tem->s + blockSize;
}
return 1;
}
-XML_Parser XML_ExternalEntityParserCreate(XML_Parser oldParser,
- const XML_Char *context,
- const XML_Char *encodingName)
+
+
+static
+XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc,
+ const char *ptr, const char *end)
{
- XML_Parser parser = oldParser;
- DTD *oldDtd = &dtd;
- XML_StartElementHandler oldStartElementHandler = startElementHandler;
- XML_EndElementHandler oldEndElementHandler = endElementHandler;
- XML_CharacterDataHandler oldCharacterDataHandler = characterDataHandler;
- XML_ProcessingInstructionHandler oldProcessingInstructionHandler = processingInstructionHandler;
- XML_CommentHandler oldCommentHandler = commentHandler;
- XML_StartCdataSectionHandler oldStartCdataSectionHandler = startCdataSectionHandler;
- XML_EndCdataSectionHandler oldEndCdataSectionHandler = endCdataSectionHandler;
- XML_DefaultHandler oldDefaultHandler = defaultHandler;
- XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler = unparsedEntityDeclHandler;
- XML_NotationDeclHandler oldNotationDeclHandler = notationDeclHandler;
- XML_ExternalParsedEntityDeclHandler oldExternalParsedEntityDeclHandler = externalParsedEntityDeclHandler;
- XML_InternalParsedEntityDeclHandler oldInternalParsedEntityDeclHandler = internalParsedEntityDeclHandler;
- XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler = startNamespaceDeclHandler;
- XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler = endNamespaceDeclHandler;
- XML_NotStandaloneHandler oldNotStandaloneHandler = notStandaloneHandler;
- XML_ExternalEntityRefHandler oldExternalEntityRefHandler = externalEntityRefHandler;
- XML_UnknownEncodingHandler oldUnknownEncodingHandler = unknownEncodingHandler;
- void *oldUserData = userData;
- void *oldHandlerArg = handlerArg;
- int oldDefaultExpandInternalEntities = defaultExpandInternalEntities;
- void *oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg;
-#ifdef XML_DTD
- int oldParamEntityParsing = paramEntityParsing;
-#endif
- parser = (ns
- ? XML_ParserCreateNS(encodingName, namespaceSeparator)
- : XML_ParserCreate(encodingName));
- if (!parser)
+ if (!pool->ptr && !poolGrow(pool))
return 0;
- startElementHandler = oldStartElementHandler;
- endElementHandler = oldEndElementHandler;
- characterDataHandler = oldCharacterDataHandler;
- processingInstructionHandler = oldProcessingInstructionHandler;
- commentHandler = oldCommentHandler;
- startCdataSectionHandler = oldStartCdataSectionHandler;
- endCdataSectionHandler = oldEndCdataSectionHandler;
- defaultHandler = oldDefaultHandler;
- unparsedEntityDeclHandler = oldUnparsedEntityDeclHandler;
- notationDeclHandler = oldNotationDeclHandler;
- externalParsedEntityDeclHandler = oldExternalParsedEntityDeclHandler;
- internalParsedEntityDeclHandler = oldInternalParsedEntityDeclHandler;
- startNamespaceDeclHandler = oldStartNamespaceDeclHandler;
- endNamespaceDeclHandler = oldEndNamespaceDeclHandler;
- notStandaloneHandler = oldNotStandaloneHandler;
- externalEntityRefHandler = oldExternalEntityRefHandler;
- unknownEncodingHandler = oldUnknownEncodingHandler;
- userData = oldUserData;
- if (oldUserData == oldHandlerArg)
- handlerArg = userData;
- else
- handlerArg = parser;
- if (oldExternalEntityRefHandlerArg != oldParser)
- externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg;
- defaultExpandInternalEntities = oldDefaultExpandInternalEntities;
-#ifdef XML_DTD
- paramEntityParsing = oldParamEntityParsing;
- if (context) {
-#endif /* XML_DTD */
- if (!dtdCopy(&dtd, oldDtd) || !setContext(parser, context)) {
- XML_ParserFree(parser);
+ for (;;) {
+ XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
+ if (ptr == end)
+ break;
+ if (!poolGrow(pool))
return 0;
- }
- processor = externalEntityInitProcessor;
-#ifdef XML_DTD
- }
- else {
- dtdSwap(&dtd, oldDtd);
- parentParser = oldParser;
- XmlPrologStateInitExternalEntity(&prologState);
- dtd.complete = 1;
- hadExternalDoctype = 1;
}
-#endif /* XML_DTD */
- return parser;
+ return pool->start;
}
-static
-void destroyBindings(BINDING *bindings)
+static const XML_Char *poolCopyString(STRING_POOL *pool, const XML_Char *s)
{
- for (;;) {
- BINDING *b = bindings;
- if (!b)
- break;
- bindings = b->nextTagBinding;
- free(b->uri);
- free(b);
- }
+ do {
+ if (!poolAppendChar(pool, *s))
+ return 0;
+ } while (*s++);
+ s = pool->start;
+ poolFinish(pool);
+ return s;
}
-void XML_ParserFree(XML_Parser parser)
+static const XML_Char *
+poolCopyStringN(STRING_POOL *pool,
+ const XML_Char *s,
+ int n)
{
- for (;;) {
- TAG *p;
- if (tagStack == 0) {
- if (freeTagList == 0)
- break;
- tagStack = freeTagList;
- freeTagList = 0;
- }
- p = tagStack;
- tagStack = tagStack->parent;
- free(p->buf);
- destroyBindings(p->bindings);
- free(p);
+ if (!pool->ptr && !poolGrow(pool))
+ return 0;
+ for (; n > 0; --n, s++) {
+ if (!poolAppendChar(pool, *s))
+ return 0;
+
}
- destroyBindings(freeBindingList);
- destroyBindings(inheritedBindings);
- poolDestroy(&tempPool);
- poolDestroy(&temp2Pool);
-#ifdef XML_DTD
- if (parentParser) {
- if (hadExternalDoctype)
- dtd.complete = 0;
- dtdSwap(&dtd, &((Parser *)parentParser)->m_dtd);
- }
-#endif /* XML_DTD */
- dtdDestroy(&dtd);
- free((void *)atts);
- free(groupConnector);
- free(buffer);
- free(dataBuf);
- free(unknownEncodingMem);
- if (unknownEncodingRelease)
- unknownEncodingRelease(unknownEncodingData);
- free(parser);
+ s = pool->start;
+ poolFinish(pool);
+ return s;
}
-void XML_UseParserAsHandlerArg(XML_Parser parser)
+static
+XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc,
+ const char *ptr, const char *end)
{
- handlerArg = parser;
+ if (!poolAppend(pool, enc, ptr, end))
+ return 0;
+ if (pool->ptr == pool->end && !poolGrow(pool))
+ return 0;
+ *(pool->ptr)++ = 0;
+ return pool->start;
}
-void XML_SetUserData(XML_Parser parser, void *p)
-{
- if (handlerArg == userData)
- handlerArg = userData = p;
- else
- userData = p;
-}
+#define INIT_SIZE 64
-int XML_SetBase(XML_Parser parser, const XML_Char *p)
+static
+int keyeq(KEY s1, KEY s2)
{
- if (p) {
- p = poolCopyString(&dtd.pool, p);
- if (!p)
- return 0;
- curBase = p;
- }
- else
- curBase = 0;
- return 1;
+ for (; *s1 == *s2; s1++, s2++)
+ if (*s1 == 0)
+ return 1;
+ return 0;
}
-const XML_Char *XML_GetBase(XML_Parser parser)
+static
+unsigned long hash(KEY s)
{
- return curBase;
+ unsigned long h = 0;
+ while (*s)
+ h = (h << 5) + h + (unsigned char)*s++;
+ return h;
}
-int XML_GetSpecifiedAttributeCount(XML_Parser parser)
+static
+NAMED *lookup(HASH_TABLE *table, KEY name, size_t createSize)
{
- return nSpecifiedAtts;
+ size_t i;
+ if (table->size == 0) {
+ if (!createSize)
+ return 0;
+ table->v = calloc(INIT_SIZE, sizeof(NAMED *));
+ if (!table->v)
+ return 0;
+ table->size = INIT_SIZE;
+ table->usedLim = INIT_SIZE / 2;
+ i = hash(name) & (table->size - 1);
+ }
+ else {
+ unsigned long h = hash(name);
+ for (i = h & (table->size - 1);
+ table->v[i];
+ i == 0 ? i = table->size - 1 : --i) {
+ if (keyeq(name, table->v[i]->name))
+ return table->v[i];
+ }
+ if (!createSize)
+ return 0;
+ if (table->used == table->usedLim) {
+ /* check for overflow */
+ size_t newSize = table->size * 2;
+ NAMED **newV = calloc(newSize, sizeof(NAMED *));
+ if (!newV)
+ return 0;
+ for (i = 0; i < table->size; i++)
+ if (table->v[i]) {
+ size_t j;
+ for (j = hash(table->v[i]->name) & (newSize - 1);
+ newV[j];
+ j == 0 ? j = newSize - 1 : --j)
+ ;
+ newV[j] = table->v[i];
+ }
+ free(table->v);
+ table->v = newV;
+ table->size = newSize;
+ table->usedLim = newSize/2;
+ for (i = h & (table->size - 1);
+ table->v[i];
+ i == 0 ? i = table->size - 1 : --i)
+ ;
+ }
+ }
+ table->v[i] = calloc(1, createSize);
+ if (!table->v[i])
+ return 0;
+ table->v[i]->name = name;
+ (table->used)++;
+ return table->v[i];
}
-int XML_GetIdAttributeIndex(XML_Parser parser)
+static
+void hashTableDestroy(HASH_TABLE *table)
{
- return idAttIndex;
+ size_t i;
+ for (i = 0; i < table->size; i++) {
+ NAMED *p = table->v[i];
+ if (p)
+ free(p);
+ }
+ if (table->v)
+ free(table->v);
}
-void XML_SetElementHandler(XML_Parser parser,
- XML_StartElementHandler start,
- XML_EndElementHandler end)
+static
+void hashTableInit(HASH_TABLE *p)
{
- startElementHandler = start;
- endElementHandler = end;
+ p->size = 0;
+ p->usedLim = 0;
+ p->used = 0;
+ p->v = 0;
}
-void XML_SetCharacterDataHandler(XML_Parser parser,
- XML_CharacterDataHandler handler)
+static
+void hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table)
{
- characterDataHandler = handler;
+ iter->p = table->v;
+ iter->end = iter->p + table->size;
}
-void XML_SetProcessingInstructionHandler(XML_Parser parser,
- XML_ProcessingInstructionHandler handler)
+static
+NAMED *hashTableIterNext(HASH_TABLE_ITER *iter)
{
- processingInstructionHandler = handler;
+ while (iter->p != iter->end) {
+ NAMED *tem = *(iter->p)++;
+ if (tem)
+ return tem;
+ }
+ return 0;
}
-void XML_SetCommentHandler(XML_Parser parser,
- XML_CommentHandler handler)
-{
- commentHandler = handler;
-}
-void XML_SetCdataSectionHandler(XML_Parser parser,
- XML_StartCdataSectionHandler start,
- XML_EndCdataSectionHandler end)
-{
- startCdataSectionHandler = start;
- endCdataSectionHandler = end;
-}
-void XML_SetDefaultHandler(XML_Parser parser,
- XML_DefaultHandler handler)
+static int dtdInit(DTD *p)
{
- defaultHandler = handler;
- defaultExpandInternalEntities = 0;
+ poolInit(&(p->pool));
+ hashTableInit(&(p->generalEntities));
+ hashTableInit(&(p->elementTypes));
+ hashTableInit(&(p->attributeIds));
+ hashTableInit(&(p->prefixes));
+ p->complete = 1;
+ p->standalone = 0;
+ hashTableInit(&(p->paramEntities));
+ p->defaultPrefix.name = 0;
+ p->defaultPrefix.binding = 0;
+ return 1;
}
-void XML_SetDefaultHandlerExpand(XML_Parser parser,
- XML_DefaultHandler handler)
-{
- defaultHandler = handler;
- defaultExpandInternalEntities = 1;
-}
-void XML_SetDoctypeDeclHandler(XML_Parser parser,
- XML_StartDoctypeDeclHandler start,
- XML_EndDoctypeDeclHandler end)
-{
- startDoctypeDeclHandler = start;
- endDoctypeDeclHandler = end;
-}
-void XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
- XML_UnparsedEntityDeclHandler handler)
+static void dtdSwap(DTD *p1, DTD *p2)
{
- unparsedEntityDeclHandler = handler;
+ DTD tem;
+ memcpy(&tem, p1, sizeof(DTD));
+ memcpy(p1, p2, sizeof(DTD));
+ memcpy(p2, &tem, sizeof(DTD));
}
-void XML_SetExternalParsedEntityDeclHandler(XML_Parser parser,
- XML_ExternalParsedEntityDeclHandler handler)
-{
- externalParsedEntityDeclHandler = handler;
-}
-void XML_SetInternalParsedEntityDeclHandler(XML_Parser parser,
- XML_InternalParsedEntityDeclHandler handler)
-{
- internalParsedEntityDeclHandler = handler;
-}
-void XML_SetNotationDeclHandler(XML_Parser parser,
- XML_NotationDeclHandler handler)
-{
- notationDeclHandler = handler;
-}
-void XML_SetNamespaceDeclHandler(XML_Parser parser,
- XML_StartNamespaceDeclHandler start,
- XML_EndNamespaceDeclHandler end)
+static void dtdDestroy(DTD *p)
{
- startNamespaceDeclHandler = start;
- endNamespaceDeclHandler = end;
+ HASH_TABLE_ITER iter;
+ hashTableIterInit(&iter, &(p->elementTypes));
+ for (;;) {
+ ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
+ if (!e)
+ break;
+ if (e->allocDefaultAtts != 0)
+ free(e->defaultAtts);
+ }
+ hashTableDestroy(&(p->generalEntities));
+ hashTableDestroy(&(p->paramEntities));
+ hashTableDestroy(&(p->elementTypes));
+ hashTableDestroy(&(p->attributeIds));
+ hashTableDestroy(&(p->prefixes));
+ poolDestroy(&(p->pool));
}
-void XML_SetNotStandaloneHandler(XML_Parser parser,
- XML_NotStandaloneHandler handler)
+static int copyEntityTable(HASH_TABLE *newTable,
+ STRING_POOL *newPool,
+ const HASH_TABLE *oldTable)
{
- notStandaloneHandler = handler;
-}
+ HASH_TABLE_ITER iter;
+ const XML_Char *cachedOldBase = 0;
+ const XML_Char *cachedNewBase = 0;
-void XML_SetExternalEntityRefHandler(XML_Parser parser,
- XML_ExternalEntityRefHandler handler)
-{
- externalEntityRefHandler = handler;
-}
+ hashTableIterInit(&iter, oldTable);
-void XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg)
-{
- if (arg)
- externalEntityRefHandlerArg = arg;
- else
- externalEntityRefHandlerArg = parser;
+ for (;;) {
+ ENTITY *newE;
+ const XML_Char *name;
+ const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter);
+ if (!oldE)
+ break;
+ name = poolCopyString(newPool, oldE->name);
+ if (!name)
+ return 0;
+ newE = (ENTITY *)lookup(newTable, name, sizeof(ENTITY));
+ if (!newE)
+ return 0;
+ if (oldE->systemId) {
+ const XML_Char *tem = poolCopyString(newPool, oldE->systemId);
+ if (!tem)
+ return 0;
+ newE->systemId = tem;
+ if (oldE->base) {
+ if (oldE->base == cachedOldBase)
+ newE->base = cachedNewBase;
+ else {
+ cachedOldBase = oldE->base;
+ tem = poolCopyString(newPool, cachedOldBase);
+ if (!tem)
+ return 0;
+ cachedNewBase = newE->base = tem;
+ }
+ }
+ }
+ else {
+ const XML_Char *tem =
+ poolCopyStringN(newPool, oldE->textPtr, oldE->textLen);
+ if (!tem)
+ return 0;
+ newE->textPtr = tem;
+ newE->textLen = oldE->textLen;
+ }
+ if (oldE->notation) {
+ const XML_Char *tem = poolCopyString(newPool, oldE->notation);
+ if (!tem)
+ return 0;
+ newE->notation = tem;
+ }
+ }
+ return 1;
}
-void XML_SetUnknownEncodingHandler(XML_Parser parser,
- XML_UnknownEncodingHandler handler,
- void *data)
-{
- unknownEncodingHandler = handler;
- unknownEncodingHandlerData = data;
-}
-int XML_SetParamEntityParsing(XML_Parser parser,
- enum XML_ParamEntityParsing parsing)
-{
-#ifdef XML_DTD
- paramEntityParsing = parsing;
- return 1;
-#else
- return parsing == XML_PARAM_ENTITY_PARSING_NEVER;
-#endif
-}
-int XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
+/* Do a deep copy of the DTD. Return 0 for out of memory; non-zero otherwise.
+The new DTD has already been initialized. */
+
+static int dtdCopy(DTD *newDtd, const DTD *oldDtd)
{
- if (len == 0) {
- if (!isFinal)
- return 1;
- positionPtr = bufferPtr;
- errorCode = processor(parser, bufferPtr, parseEndPtr = bufferEnd, 0);
- if (errorCode == XML_ERROR_NONE)
- return 1;
- eventEndPtr = eventPtr;
- processor = errorProcessor;
- return 0;
+ HASH_TABLE_ITER iter;
+
+ /* Copy the prefix table. */
+
+ hashTableIterInit(&iter, &(oldDtd->prefixes));
+ for (;;) {
+ const XML_Char *name;
+ const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter);
+ if (!oldP)
+ break;
+ name = poolCopyString(&(newDtd->pool), oldP->name);
+ if (!name)
+ return 0;
+ if (!lookup(&(newDtd->prefixes), name, sizeof(PREFIX)))
+ return 0;
}
- else if (bufferPtr == bufferEnd) {
- const char *end;
- int nLeftOver;
- parseEndByteIndex += len;
- positionPtr = s;
- if (isFinal) {
- errorCode = processor(parser, s, parseEndPtr = s + len, 0);
- if (errorCode == XML_ERROR_NONE)
- return 1;
- eventEndPtr = eventPtr;
- processor = errorProcessor;
- return 0;
- }
- errorCode = processor(parser, s, parseEndPtr = s + len, &end);
- if (errorCode != XML_ERROR_NONE) {
- eventEndPtr = eventPtr;
- processor = errorProcessor;
- return 0;
- }
- XmlUpdatePosition(encoding, positionPtr, end, &position);
- nLeftOver = s + len - end;
- if (nLeftOver) {
- if (buffer == 0 || nLeftOver > bufferLim - buffer) {
- /* FIXME avoid integer overflow */
- buffer = buffer == 0 ? malloc(len * 2) : realloc(buffer, len * 2);
- /* FIXME storage leak if realloc fails */
- if (!buffer) {
- errorCode = XML_ERROR_NO_MEMORY;
- eventPtr = eventEndPtr = 0;
- processor = errorProcessor;
- return 0;
- }
- bufferLim = buffer + len * 2;
+
+ hashTableIterInit(&iter, &(oldDtd->attributeIds));
+
+ /* Copy the attribute id table. */
+
+ for (;;) {
+ ATTRIBUTE_ID *newA;
+ const XML_Char *name;
+ const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter);
+
+ if (!oldA)
+ break;
+ /* Remember to allocate the scratch byte before the name. */
+ if (!poolAppendChar(&(newDtd->pool), XML_T('\0')))
+ return 0;
+ name = poolCopyString(&(newDtd->pool), oldA->name);
+ if (!name)
+ return 0;
+ ++name;
+ newA = (ATTRIBUTE_ID *)
+ lookup(&(newDtd->attributeIds), name, sizeof(ATTRIBUTE_ID));
+ if (!newA)
+ return 0;
+ newA->maybeTokenized = oldA->maybeTokenized;
+ if (oldA->prefix) {
+ newA->xmlns = oldA->xmlns;
+ if (oldA->prefix == &oldDtd->defaultPrefix)
+ newA->prefix = &newDtd->defaultPrefix;
+ else
+ newA->prefix = (PREFIX *)
+ lookup(&(newDtd->prefixes), oldA->prefix->name, 0);
+ }
+ }
+
+ /* Copy the element type table. */
+
+ hashTableIterInit(&iter, &(oldDtd->elementTypes));
+
+ for (;;) {
+ int i;
+ ELEMENT_TYPE *newE;
+ const XML_Char *name;
+ const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter);
+ if (!oldE)
+ break;
+ name = poolCopyString(&(newDtd->pool), oldE->name);
+ if (!name)
+ return 0;
+ newE = (ELEMENT_TYPE *)
+ lookup(&(newDtd->elementTypes), name, sizeof(ELEMENT_TYPE));
+ if (!newE)
+ return 0;
+ if (oldE->nDefaultAtts) {
+ newE->defaultAtts = (DEFAULT_ATTRIBUTE *)
+ malloc(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
+ if (!newE->defaultAtts)
+ return 0;
+ }
+ if (oldE->idAtt)
+ newE->idAtt = (ATTRIBUTE_ID *)
+ lookup(&(newDtd->attributeIds), oldE->idAtt->name, 0);
+ newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts;
+ if (oldE->prefix)
+ newE->prefix = (PREFIX *)
+ lookup(&(newDtd->prefixes), oldE->prefix->name, 0);
+ for (i = 0; i < newE->nDefaultAtts; i++) {
+ newE->defaultAtts[i].id = (ATTRIBUTE_ID *)
+ lookup(&(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
+ newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;
+ if (oldE->defaultAtts[i].value) {
+ newE->defaultAtts[i].value =
+ poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value);
+ if (!newE->defaultAtts[i].value)
+ return 0;
}
- memcpy(buffer, end, nLeftOver);
- bufferPtr = buffer;
- bufferEnd = buffer + nLeftOver;
+ else
+ newE->defaultAtts[i].value = 0;
}
- return 1;
+ }
+
+ /* Copy the entity tables. */
+ if (!copyEntityTable(&(newDtd->generalEntities),
+ &(newDtd->pool),
+ &(oldDtd->generalEntities)))
+ return 0;
+
+ if (!copyEntityTable(&(newDtd->paramEntities),
+ &(newDtd->pool),
+ &(oldDtd->paramEntities)))
+ return 0;
+
+ newDtd->complete = oldDtd->complete;
+ newDtd->standalone = oldDtd->standalone;
+ return 1;
+}
+
+
+
+static
+int addBinding(XML_Parser parser,
+ PREFIX *prefix,
+ const ATTRIBUTE_ID *attId,
+ const XML_Char *uri,
+ BINDING **bindingsPtr)
+{
+ BINDING *b;
+ int len;
+ for (len = 0; uri[len]; len++)
+ ;
+ if (namespaceSeparator)
+ len++;
+ if (freeBindingList) {
+ b = freeBindingList;
+ if (len > b->uriAlloc) {
+ b->uri = realloc(b->uri, sizeof(XML_Char) * (len + EXPAND_SPARE));
+ if (!b->uri)
+ return 0;
+ b->uriAlloc = len + EXPAND_SPARE;
+ }
+ freeBindingList = b->nextTagBinding;
}
else {
- memcpy(XML_GetBuffer(parser, len), s, len);
- return XML_ParseBuffer(parser, len, isFinal);
+ b = malloc(sizeof(BINDING));
+ if (!b)
+ return 0;
+ b->uri = malloc(sizeof(XML_Char) * (len + EXPAND_SPARE));
+ if (!b->uri) {
+ free(b);
+ return 0;
+ }
+ b->uriAlloc = len + EXPAND_SPARE;
}
+ b->uriLen = len;
+ memcpy(b->uri, uri, len * sizeof(XML_Char));
+ if (namespaceSeparator)
+ b->uri[len - 1] = namespaceSeparator;
+ b->prefix = prefix;
+ b->attId = attId;
+ b->prevPrefixBinding = prefix->binding;
+ if (*uri == XML_T('\0') && prefix == &dtd.defaultPrefix)
+ prefix->binding = 0;
+ else
+ prefix->binding = b;
+ b->nextTagBinding = *bindingsPtr;
+ *bindingsPtr = b;
+ if (startNamespaceDeclHandler)
+ startNamespaceDeclHandler(handlerArg, prefix->name,
+ prefix->binding ? uri : 0);
+ return 1;
}
-int XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
+
+
+#define CONTEXT_SEP XML_T('\f')
+
+static
+const XML_Char *getContext(XML_Parser parser)
{
- const char *start = bufferPtr;
- positionPtr = start;
- bufferEnd += len;
- parseEndByteIndex += len;
- errorCode = processor(parser, start, parseEndPtr = bufferEnd,
- isFinal ? (const char **)0 : &bufferPtr);
- if (errorCode == XML_ERROR_NONE) {
- if (!isFinal)
- XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
- return 1;
+ HASH_TABLE_ITER iter;
+ int needSep = 0;
+
+ if (dtd.defaultPrefix.binding) {
+ int i;
+ int len;
+ if (!poolAppendChar(&tempPool, XML_T('=')))
+ return 0;
+ len = dtd.defaultPrefix.binding->uriLen;
+ if (namespaceSeparator != XML_T('\0'))
+ len--;
+ for (i = 0; i < len; i++)
+ if (!poolAppendChar(&tempPool, dtd.defaultPrefix.binding->uri[i]))
+ return 0;
+ needSep = 1;
}
- else {
- eventEndPtr = eventPtr;
- processor = errorProcessor;
- return 0;
+
+ hashTableIterInit(&iter, &(dtd.prefixes));
+ for (;;) {
+ int i;
+ int len;
+ const XML_Char *s;
+ PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter);
+ if (!prefix)
+ break;
+ if (!prefix->binding)
+ continue;
+ if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
+ return 0;
+ for (s = prefix->name; *s; s++)
+ if (!poolAppendChar(&tempPool, *s))
+ return 0;
+ if (!poolAppendChar(&tempPool, XML_T('=')))
+ return 0;
+ len = prefix->binding->uriLen;
+ if (namespaceSeparator != XML_T('\0'))
+ len--;
+ for (i = 0; i < len; i++)
+ if (!poolAppendChar(&tempPool, prefix->binding->uri[i]))
+ return 0;
+ needSep = 1;
}
+
+
+ hashTableIterInit(&iter, &(dtd.generalEntities));
+ for (;;) {
+ const XML_Char *s;
+ ENTITY *e = (ENTITY *)hashTableIterNext(&iter);
+ if (!e)
+ break;
+ if (!e->open)
+ continue;
+ if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
+ return 0;
+ for (s = e->name; *s; s++)
+ if (!poolAppendChar(&tempPool, *s))
+ return 0;
+ needSep = 1;
+ }
+
+ if (!poolAppendChar(&tempPool, XML_T('\0')))
+ return 0;
+ return tempPool.start;
}
-void *XML_GetBuffer(XML_Parser parser, int len)
+static
+int setContext(XML_Parser parser, const XML_Char *context)
{
- if (len > bufferLim - bufferEnd) {
- /* FIXME avoid integer overflow */
- int neededSize = len + (bufferEnd - bufferPtr);
- if (neededSize <= bufferLim - buffer) {
- memmove(buffer, bufferPtr, bufferEnd - bufferPtr);
- bufferEnd = buffer + (bufferEnd - bufferPtr);
- bufferPtr = buffer;
+ const XML_Char *s = context;
+
+ while (*context != XML_T('\0')) {
+ if (*s == CONTEXT_SEP || *s == XML_T('\0')) {
+ ENTITY *e;
+ if (!poolAppendChar(&tempPool, XML_T('\0')))
+ return 0;
+ e = (ENTITY *)lookup(&dtd.generalEntities, poolStart(&tempPool), 0);
+ if (e)
+ e->open = 1;
+ if (*s != XML_T('\0'))
+ s++;
+ context = s;
+ poolDiscard(&tempPool);
+ }
+ else if (*s == '=') {
+ PREFIX *prefix;
+ if (poolLength(&tempPool) == 0)
+ prefix = &dtd.defaultPrefix;
+ else {
+ if (!poolAppendChar(&tempPool, XML_T('\0')))
+ return 0;
+ prefix = (PREFIX *)
+ lookup(&dtd.prefixes, poolStart(&tempPool), sizeof(PREFIX));
+ if (!prefix)
+ return 0;
+ if (prefix->name == poolStart(&tempPool)) {
+ prefix->name = poolCopyString(&dtd.pool, prefix->name);
+ if (!prefix->name)
+ return 0;
+ }
+ poolDiscard(&tempPool);
+ }
+ for (context = s + 1;
+ *context != CONTEXT_SEP && *context != XML_T('\0');
+ ++context)
+ if (!poolAppendChar(&tempPool, *context))
+ return 0;
+ if (!poolAppendChar(&tempPool, XML_T('\0')))
+ return 0;
+ if (!addBinding(parser, prefix, 0, poolStart(&tempPool),
+ &inheritedBindings))
+ return 0;
+ poolDiscard(&tempPool);
+ if (*context != XML_T('\0'))
+ ++context;
+ s = context;
}
else {
- char *newBuf;
- int bufferSize = bufferLim - bufferPtr;
- if (bufferSize == 0)
- bufferSize = INIT_BUFFER_SIZE;
- do {
- bufferSize *= 2;
- } while (bufferSize < neededSize);
- newBuf = malloc(bufferSize);
- if (newBuf == 0) {
- errorCode = XML_ERROR_NO_MEMORY;
- return 0;
- }
- bufferLim = newBuf + bufferSize;
- if (bufferPtr) {
- memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr);
- free(buffer);
- }
- bufferEnd = newBuf + (bufferEnd - bufferPtr);
- bufferPtr = buffer = newBuf;
+ if (!poolAppendChar(&tempPool, *s))
+ return 0;
+ s++;
}
}
- return bufferEnd;
+ return 1;
}
-enum XML_Error XML_GetErrorCode(XML_Parser parser)
-{
- return errorCode;
-}
-long XML_GetCurrentByteIndex(XML_Parser parser)
+
+static void
+normalizeLines(XML_Char *s)
{
- if (eventPtr)
- return parseEndByteIndex - (parseEndPtr - eventPtr);
- return -1;
+ XML_Char *p;
+ for (;; s++) {
+ if (*s == XML_T('\0'))
+ return;
+ if (*s == 0xD)
+ break;
+ }
+ p = s;
+ do {
+ if (*s == 0xD) {
+ *p++ = 0xA;
+ if (*++s == 0xA)
+ s++;
+ }
+ else
+ *p++ = *s++;
+ } while (*s);
+ *p = XML_T('\0');
}
-int XML_GetCurrentByteCount(XML_Parser parser)
-{
- if (eventEndPtr && eventPtr)
- return eventEndPtr - eventPtr;
- return 0;
+
+
+static void
+reportDefault(XML_Parser const xmlParserP,
+ const ENCODING * const enc,
+ const char * const startArg,
+ const char * const end) {
+
+ Parser * const parser = (Parser *)xmlParserP;
+
+ const char * s;
+
+ s = startArg;
+
+ if (MUST_CONVERT(enc, s)) {
+ const char **eventPP;
+ const char **eventEndPP;
+
+ if (enc == parser->m_encoding) {
+ eventPP = &eventPtr;
+ eventEndPP = &eventEndPtr;
+ }
+ else {
+ eventPP = &(openInternalEntities->internalEventPtr);
+ eventEndPP = &(openInternalEntities->internalEventEndPtr);
+ }
+ do {
+ ICHAR *dataPtr = (ICHAR *)dataBuf;
+ XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
+ *eventEndPP = s;
+ defaultHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf);
+ *eventPP = s;
+ } while (s != end);
+ } else
+ defaultHandler(handlerArg, (XML_Char *)s,
+ (XML_Char *)end - (XML_Char *)s);
}
-int XML_GetCurrentLineNumber(XML_Parser parser)
+
+
+static int
+reportProcessingInstruction(XML_Parser parser,
+ const ENCODING *enc,
+ const char *start,
+ const char *end)
{
- if (eventPtr) {
- XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
- positionPtr = eventPtr;
+ const XML_Char *target;
+ XML_Char *data;
+ const char *tem;
+ if (!processingInstructionHandler) {
+ if (defaultHandler)
+ reportDefault(parser, enc, start, end);
+ return 1;
}
- return position.lineNumber + 1;
+ start += enc->minBytesPerChar * 2;
+ tem = start + XmlNameLength(enc, start);
+ target = poolStoreString(&tempPool, enc, start, tem);
+ if (!target)
+ return 0;
+ poolFinish(&tempPool);
+ data = poolStoreString(&tempPool, enc,
+ XmlSkipS(enc, tem),
+ end - enc->minBytesPerChar*2);
+ if (!data)
+ return 0;
+ normalizeLines(data);
+ processingInstructionHandler(handlerArg, target, data);
+ poolClear(&tempPool);
+ return 1;
}
-int XML_GetCurrentColumnNumber(XML_Parser parser)
+static int
+reportComment(XML_Parser parser,
+ const ENCODING *enc,
+ const char *start,
+ const char *end)
{
- if (eventPtr) {
- XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
- positionPtr = eventPtr;
+ XML_Char *data;
+ if (!commentHandler) {
+ if (defaultHandler)
+ reportDefault(parser, enc, start, end);
+ return 1;
}
- return position.columnNumber;
+ data = poolStoreString(&tempPool,
+ enc,
+ start + enc->minBytesPerChar * 4,
+ end - enc->minBytesPerChar * 3);
+ if (!data)
+ return 0;
+ normalizeLines(data);
+ commentHandler(handlerArg, data);
+ poolClear(&tempPool);
+ return 1;
}
-void XML_DefaultCurrent(XML_Parser parser)
-{
- if (defaultHandler) {
- if (openInternalEntities)
- reportDefault(parser,
- internalEncoding,
- openInternalEntities->internalEventPtr,
- openInternalEntities->internalEventEndPtr);
- else
- reportDefault(parser, encoding, eventPtr, eventEndPtr);
- }
+
+
+static enum XML_Error
+handleUnknownEncoding(XML_Parser const xmlParserP,
+ const XML_Char * const encodingName) {
+
+ Parser * const parser = (Parser *) xmlParserP;
+
+ if (unknownEncodingHandler) {
+ XML_Encoding info;
+ int i;
+ for (i = 0; i < 256; i++)
+ info.map[i] = -1;
+ info.convert = 0;
+ info.data = 0;
+ info.release = 0;
+ if (unknownEncodingHandler(unknownEncodingHandlerData,
+ encodingName, &info)) {
+ ENCODING *enc;
+ unknownEncodingMem = malloc(xmlrpc_XmlSizeOfUnknownEncoding());
+ if (!unknownEncodingMem) {
+ if (info.release)
+ info.release(info.data);
+ return XML_ERROR_NO_MEMORY;
+ }
+ enc = (ns
+ ? xmlrpc_XmlInitUnknownEncodingNS
+ : xmlrpc_XmlInitUnknownEncoding)(unknownEncodingMem,
+ info.map,
+ info.convert,
+ info.data);
+ if (enc) {
+ unknownEncodingData = info.data;
+ unknownEncodingRelease = info.release;
+ parser->m_encoding = enc;
+ return XML_ERROR_NONE;
+ }
+ }
+ if (info.release)
+ info.release(info.data);
+ }
+ return XML_ERROR_UNKNOWN_ENCODING;
}
-const XML_LChar *XML_ErrorString(int code)
-{
- static const XML_LChar *message[] = {
- 0,
- XML_T("out of memory"),
- XML_T("syntax error"),
- XML_T("no element found"),
- XML_T("not well-formed"),
- XML_T("unclosed token"),
- XML_T("unclosed token"),
- XML_T("mismatched tag"),
- XML_T("duplicate attribute"),
- XML_T("junk after document element"),
- XML_T("illegal parameter entity reference"),
- XML_T("undefined entity"),
- XML_T("recursive entity reference"),
- XML_T("asynchronous entity"),
- XML_T("reference to invalid character number"),
- XML_T("reference to binary entity"),
- XML_T("reference to external entity in attribute"),
- XML_T("xml processing instruction not at start of external entity"),
- XML_T("unknown encoding"),
- XML_T("encoding specified in XML declaration is incorrect"),
- XML_T("unclosed CDATA section"),
- XML_T("error in processing external entity reference"),
- XML_T("document is not standalone")
- };
- if (code > 0 && code < sizeof(message)/sizeof(message[0]))
- return message[code];
- return 0;
+
+
+static enum XML_Error
+initializeEncoding(XML_Parser const xmlParserP) {
+
+ Parser * const parser = (Parser *) xmlParserP;
+
+ const char *s;
+#ifdef XML_UNICODE
+ char encodingBuf[128];
+ if (!protocolEncodingName)
+ s = 0;
+ else {
+ int i;
+ for (i = 0; protocolEncodingName[i]; i++) {
+ if (i == sizeof(encodingBuf) - 1
+ || (protocolEncodingName[i] & ~0x7f) != 0) {
+ encodingBuf[0] = '\0';
+ break;
+ }
+ encodingBuf[i] = (char)protocolEncodingName[i];
+ }
+ encodingBuf[i] = '\0';
+ s = encodingBuf;
+ }
+#else
+ s = protocolEncodingName;
+#endif
+ if ((ns ? xmlrpc_XmlInitEncodingNS : xmlrpc_XmlInitEncoding)(
+ &parser->m_initEncoding, &parser->m_encoding, s))
+ return XML_ERROR_NONE;
+ return handleUnknownEncoding(xmlParserP, protocolEncodingName);
}
-static
-enum XML_Error contentProcessor(XML_Parser parser,
- const char *start,
- const char *end,
- const char **endPtr)
+
+
+static enum XML_Error
+processXmlDecl(XML_Parser const xmlParserP,
+ int const isGeneralTextEntity,
+ const char * const s,
+ const char * const next) {
+
+ Parser * const parser = (Parser *) xmlParserP;
+
+ const char *encodingName = 0;
+ const ENCODING *newEncoding = 0;
+ const char *version;
+ int standalone = -1;
+ if (!(ns
+ ? xmlrpc_XmlParseXmlDeclNS
+ : xmlrpc_XmlParseXmlDecl)(isGeneralTextEntity,
+ parser->m_encoding,
+ s,
+ next,
+ &eventPtr,
+ &version,
+ &encodingName,
+ &newEncoding,
+ &standalone))
+ return XML_ERROR_SYNTAX;
+ if (!isGeneralTextEntity && standalone == 1) {
+ dtd.standalone = 1;
+ if (paramEntityParsing == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE)
+ paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
+ }
+ if (defaultHandler)
+ reportDefault(xmlParserP, parser->m_encoding, s, next);
+ if (!protocolEncodingName) {
+ if (newEncoding) {
+ if (newEncoding->minBytesPerChar !=
+ parser->m_encoding->minBytesPerChar) {
+ eventPtr = encodingName;
+ return XML_ERROR_INCORRECT_ENCODING;
+ }
+ parser->m_encoding = newEncoding;
+ }
+ else if (encodingName) {
+ enum XML_Error result;
+ const XML_Char * s =
+ poolStoreString(&tempPool,
+ parser->m_encoding,
+ encodingName,
+ encodingName
+ + XmlNameLength(parser->m_encoding,
+ encodingName));
+ if (!s)
+ return XML_ERROR_NO_MEMORY;
+ result = handleUnknownEncoding(xmlParserP, s);
+ poolDiscard(&tempPool);
+ if (result == XML_ERROR_UNKNOWN_ENCODING)
+ eventPtr = encodingName;
+ return result;
+ }
+ }
+ return XML_ERROR_NONE;
+}
+
+
+
+static ATTRIBUTE_ID *
+getAttributeId(XML_Parser parser,
+ const ENCODING *enc,
+ const char *start,
+ const char *end)
{
- return doContent(parser, 0, encoding, start, end, endPtr);
+ ATTRIBUTE_ID *id;
+ const XML_Char *name;
+ if (!poolAppendChar(&dtd.pool, XML_T('\0')))
+ return 0;
+ name = poolStoreString(&dtd.pool, enc, start, end);
+ if (!name)
+ return 0;
+ ++name;
+ id = (ATTRIBUTE_ID *)lookup(&dtd.attributeIds, name, sizeof(ATTRIBUTE_ID));
+ if (!id)
+ return 0;
+ if (id->name != name)
+ poolDiscard(&dtd.pool);
+ else {
+ poolFinish(&dtd.pool);
+ if (!ns)
+ ;
+ else if (name[0] == 'x'
+ && name[1] == 'm'
+ && name[2] == 'l'
+ && name[3] == 'n'
+ && name[4] == 's'
+ && (name[5] == XML_T('\0') || name[5] == XML_T(':'))) {
+ if (name[5] == '\0')
+ id->prefix = &dtd.defaultPrefix;
+ else
+ id->prefix = (PREFIX *)lookup(&dtd.prefixes, name + 6, sizeof(PREFIX));
+ id->xmlns = 1;
+ }
+ else {
+ int i;
+ for (i = 0; name[i]; i++) {
+ if (name[i] == XML_T(':')) {
+ int j;
+ for (j = 0; j < i; j++) {
+ if (!poolAppendChar(&dtd.pool, name[j]))
+ return 0;
+ }
+ if (!poolAppendChar(&dtd.pool, XML_T('\0')))
+ return 0;
+ id->prefix = (PREFIX *)
+ lookup(&dtd.prefixes, poolStart(&dtd.pool), sizeof(PREFIX));
+ if (id->prefix->name == poolStart(&dtd.pool))
+ poolFinish(&dtd.pool);
+ else
+ poolDiscard(&dtd.pool);
+ break;
+ }
+ }
+ }
+ }
+ return id;
}
static
-enum XML_Error externalEntityInitProcessor(XML_Parser parser,
- const char *start,
- const char *end,
- const char **endPtr)
+void normalizePublicId(XML_Char *publicId)
{
- enum XML_Error result = initializeEncoding(parser);
- if (result != XML_ERROR_NONE)
- return result;
- processor = externalEntityInitProcessor2;
- return externalEntityInitProcessor2(parser, start, end, endPtr);
+ XML_Char *p = publicId;
+ XML_Char *s;
+ for (s = publicId; *s; s++) {
+ switch (*s) {
+ case 0x20:
+ case 0xD:
+ case 0xA:
+ if (p != publicId && p[-1] != 0x20)
+ *p++ = 0x20;
+ break;
+ default:
+ *p++ = *s;
+ }
+ }
+ if (p != publicId && p[-1] == 0x20)
+ --p;
+ *p = XML_T('\0');
}
-static
-enum XML_Error externalEntityInitProcessor2(XML_Parser parser,
- const char *start,
- const char *end,
- const char **endPtr)
-{
- const char *next;
- int tok = XmlContentTok(encoding, start, end, &next);
- switch (tok) {
- case XML_TOK_BOM:
- start = next;
- break;
- case XML_TOK_PARTIAL:
- if (endPtr) {
- *endPtr = start;
- return XML_ERROR_NONE;
- }
- eventPtr = start;
- return XML_ERROR_UNCLOSED_TOKEN;
- case XML_TOK_PARTIAL_CHAR:
- if (endPtr) {
- *endPtr = start;
- return XML_ERROR_NONE;
+
+
+static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType)
+{
+ const XML_Char *name;
+ for (name = elementType->name; *name; name++) {
+ if (*name == XML_T(':')) {
+ PREFIX *prefix;
+ const XML_Char *s;
+ for (s = elementType->name; s != name; s++) {
+ if (!poolAppendChar(&dtd.pool, *s))
+ return 0;
+ }
+ if (!poolAppendChar(&dtd.pool, XML_T('\0')))
+ return 0;
+ prefix = (PREFIX *)
+ lookup(&dtd.prefixes, poolStart(&dtd.pool), sizeof(PREFIX));
+ if (!prefix)
+ return 0;
+ if (prefix->name == poolStart(&dtd.pool))
+ poolFinish(&dtd.pool);
+ else
+ poolDiscard(&dtd.pool);
+ elementType->prefix = prefix;
+
}
- eventPtr = start;
- return XML_ERROR_PARTIAL_CHAR;
}
- processor = externalEntityInitProcessor3;
- return externalEntityInitProcessor3(parser, start, end, endPtr);
+ return 1;
}
-static
-enum XML_Error externalEntityInitProcessor3(XML_Parser parser,
- const char *start,
- const char *end,
- const char **endPtr)
-{
- const char *next;
- int tok = XmlContentTok(encoding, start, end, &next);
- switch (tok) {
- case XML_TOK_XML_DECL:
- {
- enum XML_Error result = processXmlDecl(parser, 1, start, next);
- if (result != XML_ERROR_NONE)
- return result;
- start = next;
- }
- break;
- case XML_TOK_PARTIAL:
- if (endPtr) {
- *endPtr = start;
- return XML_ERROR_NONE;
- }
- eventPtr = start;
- return XML_ERROR_UNCLOSED_TOKEN;
- case XML_TOK_PARTIAL_CHAR:
- if (endPtr) {
- *endPtr = start;
- return XML_ERROR_NONE;
- }
- eventPtr = start;
- return XML_ERROR_PARTIAL_CHAR;
- }
- processor = externalEntityContentProcessor;
- tagLevel = 1;
- return doContent(parser, 1, encoding, start, end, endPtr);
-}
-static
-enum XML_Error externalEntityContentProcessor(XML_Parser parser,
- const char *start,
- const char *end,
- const char **endPtr)
-{
- return doContent(parser, 1, encoding, start, end, endPtr);
-}
static enum XML_Error
-doContent(XML_Parser parser,
- int startTagLevel,
- const ENCODING *enc,
- const char *s,
- const char *end,
- const char **nextPtr)
-{
- const char **eventPP;
- const char **eventEndPP;
- if (enc == encoding) {
- eventPP = &eventPtr;
- eventEndPP = &eventEndPtr;
- }
- else {
- eventPP = &(openInternalEntities->internalEventPtr);
- eventEndPP = &(openInternalEntities->internalEventEndPtr);
- }
- *eventPP = s;
+appendAttributeValue(XML_Parser const xmlParserP,
+ const ENCODING * const enc,
+ int const isCdata,
+ const char * const ptrArg,
+ const char * const end,
+ STRING_POOL * const pool) {
+
+ Parser * const parser = (Parser *) xmlParserP;
+
+ const char * ptr;
+
+ ptr = ptrArg;
+
for (;;) {
- const char *next = s; /* XmlContentTok doesn't always set the last arg */
- int tok = XmlContentTok(enc, s, end, &next);
- *eventEndPP = next;
+ const char *next;
+ int tok = XmlAttributeValueTok(enc, ptr, end, &next);
switch (tok) {
- case XML_TOK_TRAILING_CR:
- if (nextPtr) {
- *nextPtr = s;
- return XML_ERROR_NONE;
- }
- *eventEndPP = end;
- if (characterDataHandler) {
- XML_Char c = 0xA;
- characterDataHandler(handlerArg, &c, 1);
- }
- else if (defaultHandler)
- reportDefault(parser, enc, s, end);
- if (startTagLevel == 0)
- return XML_ERROR_NO_ELEMENTS;
- if (tagLevel != startTagLevel)
- return XML_ERROR_ASYNC_ENTITY;
- return XML_ERROR_NONE;
case XML_TOK_NONE:
- if (nextPtr) {
- *nextPtr = s;
- return XML_ERROR_NONE;
- }
- if (startTagLevel > 0) {
- if (tagLevel != startTagLevel)
- return XML_ERROR_ASYNC_ENTITY;
- return XML_ERROR_NONE;
- }
- return XML_ERROR_NO_ELEMENTS;
+ return XML_ERROR_NONE;
case XML_TOK_INVALID:
- *eventPP = next;
+ if (enc == parser->m_encoding)
+ eventPtr = next;
return XML_ERROR_INVALID_TOKEN;
case XML_TOK_PARTIAL:
- if (nextPtr) {
- *nextPtr = s;
- return XML_ERROR_NONE;
- }
- return XML_ERROR_UNCLOSED_TOKEN;
- case XML_TOK_PARTIAL_CHAR:
- if (nextPtr) {
- *nextPtr = s;
- return XML_ERROR_NONE;
- }
- return XML_ERROR_PARTIAL_CHAR;
- case XML_TOK_ENTITY_REF:
- {
- const XML_Char *name;
- ENTITY *entity;
- XML_Char ch = XmlPredefinedEntityName(enc,
- s + enc->minBytesPerChar,
- next - enc->minBytesPerChar);
- if (ch) {
- if (characterDataHandler)
- characterDataHandler(handlerArg, &ch, 1);
- else if (defaultHandler)
- reportDefault(parser, enc, s, next);
- break;
- }
- name = poolStoreString(&dtd.pool, enc,
- s + enc->minBytesPerChar,
- next - enc->minBytesPerChar);
- if (!name)
- return XML_ERROR_NO_MEMORY;
- entity = (ENTITY *)lookup(&dtd.generalEntities, name, 0);
- poolDiscard(&dtd.pool);
- if (!entity) {
- if (dtd.complete || dtd.standalone)
- return XML_ERROR_UNDEFINED_ENTITY;
- if (defaultHandler)
- reportDefault(parser, enc, s, next);
- break;
- }
- if (entity->open)
- return XML_ERROR_RECURSIVE_ENTITY_REF;
- if (entity->notation)
- return XML_ERROR_BINARY_ENTITY_REF;
- if (entity) {
- if (entity->textPtr) {
- enum XML_Error result;
- OPEN_INTERNAL_ENTITY openEntity;
- if (defaultHandler && !defaultExpandInternalEntities) {
- reportDefault(parser, enc, s, next);
- break;
- }
- entity->open = 1;
- openEntity.next = openInternalEntities;
- openInternalEntities = &openEntity;
- openEntity.entity = entity;
- openEntity.internalEventPtr = 0;
- openEntity.internalEventEndPtr = 0;
- result = doContent(parser,
- tagLevel,
- internalEncoding,
- (char *)entity->textPtr,
- (char *)(entity->textPtr + entity->textLen),
- 0);
- entity->open = 0;
- openInternalEntities = openEntity.next;
- if (result)
- return result;
- }
- else if (externalEntityRefHandler) {
- const XML_Char *context;
- entity->open = 1;
- context = getContext(parser);
- entity->open = 0;
- if (!context)
- return XML_ERROR_NO_MEMORY;
- if (!externalEntityRefHandler(externalEntityRefHandlerArg,
- context,
- entity->base,
- entity->systemId,
- entity->publicId))
- return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
- poolDiscard(&tempPool);
- }
- else if (defaultHandler)
- reportDefault(parser, enc, s, next);
- }
- break;
- }
- case XML_TOK_START_TAG_WITH_ATTS:
- if (!startElementHandler) {
- enum XML_Error result = storeAtts(parser, enc, s, 0, 0);
- if (result)
- return result;
- }
- /* fall through */
- case XML_TOK_START_TAG_NO_ATTS:
+ if (enc == parser->m_encoding)
+ eventPtr = ptr;
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_CHAR_REF:
{
- TAG *tag;
- if (freeTagList) {
- tag = freeTagList;
- freeTagList = freeTagList->parent;
- }
- else {
- tag = malloc(sizeof(TAG));
- if (!tag)
- return XML_ERROR_NO_MEMORY;
- tag->buf = malloc(INIT_TAG_BUF_SIZE);
- if (!tag->buf)
- return XML_ERROR_NO_MEMORY;
- tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE;
- }
- tag->bindings = 0;
- tag->parent = tagStack;
- tagStack = tag;
- tag->name.localPart = 0;
- tag->rawName = s + enc->minBytesPerChar;
- tag->rawNameLength = XmlNameLength(enc, tag->rawName);
- if (nextPtr) {
- /* Need to guarantee that:
- tag->buf + ROUND_UP(tag->rawNameLength, sizeof(XML_Char)) <= tag->bufEnd - sizeof(XML_Char) */
- if (tag->rawNameLength + (int)(sizeof(XML_Char) - 1) + (int)sizeof(XML_Char) > tag->bufEnd - tag->buf) {
- int bufSize = tag->rawNameLength * 4;
- bufSize = ROUND_UP(bufSize, sizeof(XML_Char));
- tag->buf = realloc(tag->buf, bufSize);
- if (!tag->buf)
- return XML_ERROR_NO_MEMORY;
- tag->bufEnd = tag->buf + bufSize;
- }
- memcpy(tag->buf, tag->rawName, tag->rawNameLength);
- tag->rawName = tag->buf;
- }
- ++tagLevel;
- if (startElementHandler) {
- enum XML_Error result;
- XML_Char *toPtr;
- for (;;) {
- const char *rawNameEnd = tag->rawName + tag->rawNameLength;
- const char *fromPtr = tag->rawName;
- int bufSize;
- if (nextPtr)
- toPtr = (XML_Char *)(tag->buf + ROUND_UP(tag->rawNameLength, sizeof(XML_Char)));
- else
- toPtr = (XML_Char *)tag->buf;
- tag->name.str = toPtr;
- XmlConvert(enc,
- &fromPtr, rawNameEnd,
- (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1);
- if (fromPtr == rawNameEnd)
- break;
- bufSize = (tag->bufEnd - tag->buf) << 1;
- tag->buf = realloc(tag->buf, bufSize);
- if (!tag->buf)
- return XML_ERROR_NO_MEMORY;
- tag->bufEnd = tag->buf + bufSize;
- if (nextPtr)
- tag->rawName = tag->buf;
- }
- *toPtr = XML_T('\0');
- result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings));
- if (result)
- return result;
- startElementHandler(handlerArg, tag->name.str, (const XML_Char **)atts);
- poolClear(&tempPool);
- }
- else {
- tag->name.str = 0;
- if (defaultHandler)
- reportDefault(parser, enc, s, next);
- }
- break;
- }
- case XML_TOK_EMPTY_ELEMENT_WITH_ATTS:
- if (!startElementHandler) {
- enum XML_Error result = storeAtts(parser, enc, s, 0, 0);
- if (result)
- return result;
- }
- /* fall through */
- case XML_TOK_EMPTY_ELEMENT_NO_ATTS:
- if (startElementHandler || endElementHandler) {
- const char *rawName = s + enc->minBytesPerChar;
- enum XML_Error result;
- BINDING *bindings = 0;
- TAG_NAME name;
- name.str = poolStoreString(&tempPool, enc, rawName,
- rawName + XmlNameLength(enc, rawName));
- if (!name.str)
- return XML_ERROR_NO_MEMORY;
- poolFinish(&tempPool);
- result = storeAtts(parser, enc, s, &name, &bindings);
- if (result)
- return result;
- poolFinish(&tempPool);
- if (startElementHandler)
- startElementHandler(handlerArg, name.str, (const XML_Char **)atts);
- if (endElementHandler) {
- if (startElementHandler)
- *eventPP = *eventEndPP;
- endElementHandler(handlerArg, name.str);
- }
- poolClear(&tempPool);
- while (bindings) {
- BINDING *b = bindings;
- if (endNamespaceDeclHandler)
- endNamespaceDeclHandler(handlerArg, b->prefix->name);
- bindings = bindings->nextTagBinding;
- b->nextTagBinding = freeBindingList;
- freeBindingList = b;
- b->prefix->binding = b->prevPrefixBinding;
- }
+ XML_Char buf[XML_ENCODE_MAX];
+ int i;
+ int n = XmlCharRefNumber(enc, ptr);
+ if (n < 0) {
+ if (enc == parser->m_encoding)
+ eventPtr = ptr;
+ return XML_ERROR_BAD_CHAR_REF;
+ }
+ if (!isCdata
+ && n == 0x20 /* space */
+ && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
+ break;
+ n = XmlEncode(n, (ICHAR *)buf);
+ if (!n) {
+ if (enc == parser->m_encoding)
+ eventPtr = ptr;
+ return XML_ERROR_BAD_CHAR_REF;
+ }
+ for (i = 0; i < n; i++) {
+ if (!poolAppendChar(pool, buf[i]))
+ return XML_ERROR_NO_MEMORY;
+ }
}
- else if (defaultHandler)
- reportDefault(parser, enc, s, next);
- if (tagLevel == 0)
- return epilogProcessor(parser, next, end, nextPtr);
break;
- case XML_TOK_END_TAG:
- if (tagLevel == startTagLevel)
- return XML_ERROR_ASYNC_ENTITY;
- else {
- int len;
- const char *rawName;
- TAG *tag = tagStack;
- tagStack = tag->parent;
- tag->parent = freeTagList;
- freeTagList = tag;
- rawName = s + enc->minBytesPerChar*2;
- len = XmlNameLength(enc, rawName);
- if (len != tag->rawNameLength
- || memcmp(tag->rawName, rawName, len) != 0) {
- *eventPP = rawName;
- return XML_ERROR_TAG_MISMATCH;
- }
- --tagLevel;
- if (endElementHandler && tag->name.str) {
- if (tag->name.localPart) {
- XML_Char *to = (XML_Char *)tag->name.str + tag->name.uriLen;
- const XML_Char *from = tag->name.localPart;
- while ((*to++ = *from++) != 0)
- ;
- }
- endElementHandler(handlerArg, tag->name.str);
- }
- else if (defaultHandler)
- reportDefault(parser, enc, s, next);
- while (tag->bindings) {
- BINDING *b = tag->bindings;
- if (endNamespaceDeclHandler)
- endNamespaceDeclHandler(handlerArg, b->prefix->name);
- tag->bindings = tag->bindings->nextTagBinding;
- b->nextTagBinding = freeBindingList;
- freeBindingList = b;
- b->prefix->binding = b->prevPrefixBinding;
- }
- if (tagLevel == 0)
- return epilogProcessor(parser, next, end, nextPtr);
- }
+ case XML_TOK_DATA_CHARS:
+ if (!poolAppend(pool, enc, ptr, next))
+ return XML_ERROR_NO_MEMORY;
break;
- case XML_TOK_CHAR_REF:
- {
- int n = XmlCharRefNumber(enc, s);
- if (n < 0)
- return XML_ERROR_BAD_CHAR_REF;
- if (characterDataHandler) {
- XML_Char buf[XML_ENCODE_MAX];
- characterDataHandler(handlerArg, buf, XmlEncode(n, (ICHAR *)buf));
- }
- else if (defaultHandler)
- reportDefault(parser, enc, s, next);
- }
break;
- case XML_TOK_XML_DECL:
- return XML_ERROR_MISPLACED_XML_PI;
+ case XML_TOK_TRAILING_CR:
+ next = ptr + enc->minBytesPerChar;
+ /* fall through */
+ case XML_TOK_ATTRIBUTE_VALUE_S:
case XML_TOK_DATA_NEWLINE:
- if (characterDataHandler) {
- XML_Char c = 0xA;
- characterDataHandler(handlerArg, &c, 1);
- }
- else if (defaultHandler)
- reportDefault(parser, enc, s, next);
+ if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
+ break;
+ if (!poolAppendChar(pool, 0x20))
+ return XML_ERROR_NO_MEMORY;
break;
- case XML_TOK_CDATA_SECT_OPEN:
+ case XML_TOK_ENTITY_REF:
{
- enum XML_Error result;
- if (startCdataSectionHandler)
- startCdataSectionHandler(handlerArg);
-#if 0
- /* Suppose you doing a transformation on a document that involves
- changing only the character data. You set up a defaultHandler
- and a characterDataHandler. The defaultHandler simply copies
- characters through. The characterDataHandler does the transformation
- and writes the characters out escaping them as necessary. This case
- will fail to work if we leave out the following two lines (because &
- and < inside CDATA sections will be incorrectly escaped).
-
- However, now we have a start/endCdataSectionHandler, so it seems
- easier to let the user deal with this. */
-
- else if (characterDataHandler)
- characterDataHandler(handlerArg, dataBuf, 0);
-#endif
- else if (defaultHandler)
- reportDefault(parser, enc, s, next);
- result = doCdataSection(parser, enc, &next, end, nextPtr);
- if (!next) {
- processor = cdataSectionProcessor;
- return result;
- }
+ const XML_Char *name;
+ ENTITY *entity;
+ XML_Char ch = XmlPredefinedEntityName(enc,
+ ptr + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (ch) {
+ if (!poolAppendChar(pool, ch))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ }
+ name = poolStoreString(&temp2Pool, enc,
+ ptr + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (!name)
+ return XML_ERROR_NO_MEMORY;
+ entity = (ENTITY *)lookup(&dtd.generalEntities, name, 0);
+ poolDiscard(&temp2Pool);
+ if (!entity) {
+ if (dtd.complete) {
+ if (enc == parser->m_encoding)
+ eventPtr = ptr;
+ return XML_ERROR_UNDEFINED_ENTITY;
+ }
+ }
+ else if (entity->open) {
+ if (enc == parser->m_encoding)
+ eventPtr = ptr;
+ return XML_ERROR_RECURSIVE_ENTITY_REF;
+ }
+ else if (entity->notation) {
+ if (enc == parser->m_encoding)
+ eventPtr = ptr;
+ return XML_ERROR_BINARY_ENTITY_REF;
+ }
+ else if (!entity->textPtr) {
+ if (enc == parser->m_encoding)
+ eventPtr = ptr;
+ return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
+ }
+ else {
+ enum XML_Error result;
+ const XML_Char *textEnd = entity->textPtr + entity->textLen;
+ entity->open = 1;
+ result = appendAttributeValue(xmlParserP, internalEncoding,
+ isCdata, (char *)entity->textPtr,
+ (char *)textEnd, pool);
+ entity->open = 0;
+ if (result)
+ return result;
+ }
}
break;
- case XML_TOK_TRAILING_RSQB:
- if (nextPtr) {
- *nextPtr = s;
- return XML_ERROR_NONE;
- }
- if (characterDataHandler) {
- if (MUST_CONVERT(enc, s)) {
- ICHAR *dataPtr = (ICHAR *)dataBuf;
- XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
- characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf);
- }
- else
- characterDataHandler(handlerArg,
- (XML_Char *)s,
- (XML_Char *)end - (XML_Char *)s);
- }
- else if (defaultHandler)
- reportDefault(parser, enc, s, end);
- if (startTagLevel == 0) {
- *eventPP = end;
- return XML_ERROR_NO_ELEMENTS;
- }
- if (tagLevel != startTagLevel) {
- *eventPP = end;
- return XML_ERROR_ASYNC_ENTITY;
+ default:
+ abort();
+ }
+ ptr = next;
+ }
+ /* not reached */
+}
+
+
+
+static enum XML_Error
+storeAttributeValue(XML_Parser parser, const ENCODING *enc, int isCdata,
+ const char *ptr, const char *end,
+ STRING_POOL *pool)
+{
+ enum XML_Error result =
+ appendAttributeValue(parser, enc, isCdata, ptr, end, pool);
+ if (result)
+ return result;
+ if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
+ poolChop(pool);
+ if (!poolAppendChar(pool, XML_T('\0')))
+ return XML_ERROR_NO_MEMORY;
+ return XML_ERROR_NONE;
+}
+
+
+
+static
+enum XML_Error
+storeEntityValue(XML_Parser const xmlParserP,
+ const ENCODING * const enc,
+ const char * const entityTextPtrArg,
+ const char * const entityTextEnd) {
+
+ Parser * const parser = (Parser *) xmlParserP;
+
+ STRING_POOL * const pool = &(dtd.pool);
+ const char * entityTextPtr;
+
+ entityTextPtr = entityTextPtrArg;
+
+ for (;;) {
+ const char * next;
+ int tok;
+
+ tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next);
+ switch (tok) {
+ case XML_TOK_PARAM_ENTITY_REF:
+ if (parentParser || enc != parser->m_encoding) {
+ enum XML_Error result;
+ const XML_Char *name;
+ ENTITY *entity;
+ name = poolStoreString(&tempPool, enc,
+ entityTextPtr + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (!name)
+ return XML_ERROR_NO_MEMORY;
+ entity = (ENTITY *)lookup(&dtd.paramEntities, name, 0);
+ poolDiscard(&tempPool);
+ if (!entity) {
+ if (enc == parser->m_encoding)
+ eventPtr = entityTextPtr;
+ return XML_ERROR_UNDEFINED_ENTITY;
+ }
+ if (entity->open) {
+ if (enc == parser->m_encoding)
+ eventPtr = entityTextPtr;
+ return XML_ERROR_RECURSIVE_ENTITY_REF;
+ }
+ if (entity->systemId) {
+ if (enc == parser->m_encoding)
+ eventPtr = entityTextPtr;
+ return XML_ERROR_PARAM_ENTITY_REF;
+ }
+ entity->open = 1;
+ result = storeEntityValue(parser,
+ internalEncoding,
+ (char *)entity->textPtr,
+ (char *)(entity->textPtr + entity->textLen));
+ entity->open = 0;
+ if (result)
+ return result;
+ break;
}
+ eventPtr = entityTextPtr;
+ return XML_ERROR_SYNTAX;
+ case XML_TOK_NONE:
return XML_ERROR_NONE;
+ case XML_TOK_ENTITY_REF:
case XML_TOK_DATA_CHARS:
- if (characterDataHandler) {
- if (MUST_CONVERT(enc, s)) {
- for (;;) {
- ICHAR *dataPtr = (ICHAR *)dataBuf;
- XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
- *eventEndPP = s;
- characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf);
- if (s == next)
- break;
- *eventPP = s;
- }
- }
- else
- characterDataHandler(handlerArg,
- (XML_Char *)s,
- (XML_Char *)next - (XML_Char *)s);
- }
- else if (defaultHandler)
- reportDefault(parser, enc, s, next);
+ if (!poolAppend(pool, enc, entityTextPtr, next))
+ return XML_ERROR_NO_MEMORY;
break;
- case XML_TOK_PI:
- if (!reportProcessingInstruction(parser, enc, s, next))
- return XML_ERROR_NO_MEMORY;
+ case XML_TOK_TRAILING_CR:
+ next = entityTextPtr + enc->minBytesPerChar;
+ /* fall through */
+ case XML_TOK_DATA_NEWLINE:
+ if (pool->end == pool->ptr && !poolGrow(pool))
+ return XML_ERROR_NO_MEMORY;
+ *(pool->ptr)++ = 0xA;
break;
- case XML_TOK_COMMENT:
- if (!reportComment(parser, enc, s, next))
- return XML_ERROR_NO_MEMORY;
+ case XML_TOK_CHAR_REF:
+ {
+ XML_Char buf[XML_ENCODE_MAX];
+ int i;
+ int n = XmlCharRefNumber(enc, entityTextPtr);
+ if (n < 0) {
+ if (enc == parser->m_encoding)
+ eventPtr = entityTextPtr;
+ return XML_ERROR_BAD_CHAR_REF;
+ }
+ n = XmlEncode(n, (ICHAR *)buf);
+ if (!n) {
+ if (enc == parser->m_encoding)
+ eventPtr = entityTextPtr;
+ return XML_ERROR_BAD_CHAR_REF;
+ }
+ for (i = 0; i < n; i++) {
+ if (pool->end == pool->ptr && !poolGrow(pool))
+ return XML_ERROR_NO_MEMORY;
+ *(pool->ptr)++ = buf[i];
+ }
+ }
break;
+ case XML_TOK_PARTIAL:
+ if (enc == parser->m_encoding)
+ eventPtr = entityTextPtr;
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_INVALID:
+ if (enc == parser->m_encoding)
+ eventPtr = next;
+ return XML_ERROR_INVALID_TOKEN;
default:
- if (defaultHandler)
- reportDefault(parser, enc, s, next);
- break;
+ abort();
}
- *eventPP = s = next;
+ entityTextPtr = next;
}
/* not reached */
}
+
+
+static int
+defineAttribute(ELEMENT_TYPE *type,
+ ATTRIBUTE_ID *attId,
+ int isCdata,
+ int isId,
+ const XML_Char *value)
+{
+ DEFAULT_ATTRIBUTE *att;
+ if (value || isId) {
+ /* The handling of default attributes gets messed up if we have
+ a default which duplicates a non-default. */
+ int i;
+ for (i = 0; i < type->nDefaultAtts; i++)
+ if (attId == type->defaultAtts[i].id)
+ return 1;
+ if (isId && !type->idAtt && !attId->xmlns)
+ type->idAtt = attId;
+ }
+ if (type->nDefaultAtts == type->allocDefaultAtts) {
+ if (type->allocDefaultAtts == 0) {
+ type->allocDefaultAtts = 8;
+ type->defaultAtts =
+ malloc(type->allocDefaultAtts*sizeof(DEFAULT_ATTRIBUTE));
+ }
+ else {
+ type->allocDefaultAtts *= 2;
+ type->defaultAtts =
+ realloc(type->defaultAtts,
+ type->allocDefaultAtts*sizeof(DEFAULT_ATTRIBUTE));
+ }
+ if (!type->defaultAtts)
+ return 0;
+ }
+ att = type->defaultAtts + type->nDefaultAtts;
+ att->id = attId;
+ att->value = value;
+ att->isCdata = isCdata;
+ if (!isCdata)
+ attId->maybeTokenized = 1;
+ type->nDefaultAtts += 1;
+ return 1;
+}
+
+
+
/* If tagNamePtr is non-null, build a real list of attributes,
otherwise just check the attributes for well-formedness. */
-static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *enc,
- const char *attStr, TAG_NAME *tagNamePtr,
- BINDING **bindingsPtr)
-{
+static enum XML_Error
+storeAtts(XML_Parser const xmlParserP,
+ const ENCODING * const enc,
+ const char * const attStr,
+ TAG_NAME * const tagNamePtr,
+ BINDING ** const bindingsPtr) {
+
+ Parser * const parser = (Parser *)xmlParserP;
+
ELEMENT_TYPE *elementType = 0;
int nDefaultAtts = 0;
- const XML_Char **appAtts; /* the attribute list to pass to the application */
+ const XML_Char ** appAtts;
+ /* the attribute list to pass to the application */
int attIndex = 0;
int i;
int n;
@@ -1618,15 +1806,17 @@
/* lookup the element type name */
if (tagNamePtr) {
- elementType = (ELEMENT_TYPE *)lookup(&dtd.elementTypes, tagNamePtr->str, 0);
+ elementType = (ELEMENT_TYPE *)
+ lookup(&dtd.elementTypes, tagNamePtr->str, 0);
if (!elementType) {
tagNamePtr->str = poolCopyString(&dtd.pool, tagNamePtr->str);
if (!tagNamePtr->str)
- return XML_ERROR_NO_MEMORY;
- elementType = (ELEMENT_TYPE *)lookup(&dtd.elementTypes, tagNamePtr->str, sizeof(ELEMENT_TYPE));
+ return XML_ERROR_NO_MEMORY;
+ elementType = (ELEMENT_TYPE *)
+ lookup(&dtd.elementTypes, tagNamePtr->str, sizeof(ELEMENT_TYPE));
if (!elementType)
return XML_ERROR_NO_MEMORY;
- if (ns && !setElementTypePrefix(parser, elementType))
+ if (ns && !setElementTypePrefix(xmlParserP, elementType))
return XML_ERROR_NO_MEMORY;
}
nDefaultAtts = elementType->nDefaultAtts;
@@ -1645,15 +1835,15 @@
appAtts = (const XML_Char **)atts;
for (i = 0; i < n; i++) {
/* add the name and value to the attribute list */
- ATTRIBUTE_ID *attId = getAttributeId(parser, enc, atts[i].name,
- atts[i].name
- + XmlNameLength(enc, atts[i].name));
+ ATTRIBUTE_ID *attId = getAttributeId(xmlParserP, enc, atts[i].name,
+ atts[i].name
+ + XmlNameLength(enc, atts[i].name));
if (!attId)
return XML_ERROR_NO_MEMORY;
/* detect duplicate attributes */
if ((attId->name)[-1]) {
- if (enc == encoding)
- eventPtr = atts[i].name;
+ if (enc == parser->m_encoding)
+ eventPtr = atts[i].name;
return XML_ERROR_DUPLICATE_ATTRIBUTE;
}
(attId->name)[-1] = 1;
@@ -1664,45 +1854,47 @@
/* figure out whether declared as other than CDATA */
if (attId->maybeTokenized) {
- int j;
- for (j = 0; j < nDefaultAtts; j++) {
- if (attId == elementType->defaultAtts[j].id) {
- isCdata = elementType->defaultAtts[j].isCdata;
- break;
- }
- }
+ int j;
+ for (j = 0; j < nDefaultAtts; j++) {
+ if (attId == elementType->defaultAtts[j].id) {
+ isCdata = elementType->defaultAtts[j].isCdata;
+ break;
+ }
+ }
}
/* normalize the attribute value */
- result = storeAttributeValue(parser, enc, isCdata,
- atts[i].valuePtr, atts[i].valueEnd,
- &tempPool);
+ result = storeAttributeValue(xmlParserP, enc, isCdata,
+ atts[i].valuePtr, atts[i].valueEnd,
+ &tempPool);
if (result)
- return result;
+ return result;
if (tagNamePtr) {
- appAtts[attIndex] = poolStart(&tempPool);
- poolFinish(&tempPool);
+ appAtts[attIndex] = poolStart(&tempPool);
+ poolFinish(&tempPool);
}
else
- poolDiscard(&tempPool);
+ poolDiscard(&tempPool);
}
else if (tagNamePtr) {
/* the value did not need normalizing */
- appAtts[attIndex] = poolStoreString(&tempPool, enc, atts[i].valuePtr, atts[i].valueEnd);
+ appAtts[attIndex] =
+ poolStoreString(&tempPool, enc, atts[i].valuePtr, atts[i].valueEnd);
if (appAtts[attIndex] == 0)
- return XML_ERROR_NO_MEMORY;
+ return XML_ERROR_NO_MEMORY;
poolFinish(&tempPool);
}
/* handle prefixed attribute names */
if (attId->prefix && tagNamePtr) {
if (attId->xmlns) {
- /* deal with namespace declarations here */
- if (!addBinding(parser, attId->prefix, attId, appAtts[attIndex], bindingsPtr))
+ /* deal with namespace declarations here */
+ if (!addBinding(xmlParserP, attId->prefix, attId, appAtts[attIndex],
+ bindingsPtr))
return XML_ERROR_NO_MEMORY;
--attIndex;
}
else {
- /* deal with other prefixed names later */
+ /* deal with other prefixed names later */
attIndex++;
nPrefixes++;
(attId->name)[-1] = 2;
@@ -1716,10 +1908,10 @@
nSpecifiedAtts = attIndex;
if (elementType->idAtt && (elementType->idAtt->name)[-1]) {
for (i = 0; i < attIndex; i += 2)
- if (appAtts[i] == elementType->idAtt->name) {
- idAttIndex = i;
- break;
- }
+ if (appAtts[i] == elementType->idAtt->name) {
+ idAttIndex = i;
+ break;
+ }
}
else
idAttIndex = -1;
@@ -1729,21 +1921,22 @@
if (!(da->id->name)[-1] && da->value) {
if (da->id->prefix) {
if (da->id->xmlns) {
- if (!addBinding(parser, da->id->prefix, da->id, da->value, bindingsPtr))
- return XML_ERROR_NO_MEMORY;
- }
+ if (!addBinding(xmlParserP, da->id->prefix, da->id, da->value,
+ bindingsPtr))
+ return XML_ERROR_NO_MEMORY;
+ }
else {
- (da->id->name)[-1] = 2;
- nPrefixes++;
- appAtts[attIndex++] = da->id->name;
- appAtts[attIndex++] = da->value;
- }
- }
- else {
- (da->id->name)[-1] = 1;
- appAtts[attIndex++] = da->id->name;
- appAtts[attIndex++] = da->value;
- }
+ (da->id->name)[-1] = 2;
+ nPrefixes++;
+ appAtts[attIndex++] = da->id->name;
+ appAtts[attIndex++] = da->value;
+ }
+ }
+ else {
+ (da->id->name)[-1] = 1;
+ appAtts[attIndex++] = da->id->name;
+ appAtts[attIndex++] = da->value;
+ }
}
}
appAtts[attIndex] = 0;
@@ -1755,29 +1948,29 @@
if (appAtts[i][-1] == 2) {
ATTRIBUTE_ID *id;
((XML_Char *)(appAtts[i]))[-1] = 0;
- id = (ATTRIBUTE_ID *)lookup(&dtd.attributeIds, appAtts[i], 0);
- if (id->prefix->binding) {
- int j;
- const BINDING *b = id->prefix->binding;
- const XML_Char *s = appAtts[i];
- for (j = 0; j < b->uriLen; j++) {
- if (!poolAppendChar(&tempPool, b->uri[j]))
- return XML_ERROR_NO_MEMORY;
- }
- while (*s++ != ':')
- ;
- do {
- if (!poolAppendChar(&tempPool, *s))
- return XML_ERROR_NO_MEMORY;
- } while (*s++);
- appAtts[i] = poolStart(&tempPool);
- poolFinish(&tempPool);
- }
- if (!--nPrefixes)
- break;
+ id = (ATTRIBUTE_ID *)lookup(&dtd.attributeIds, appAtts[i], 0);
+ if (id->prefix->binding) {
+ int j;
+ const BINDING *b = id->prefix->binding;
+ const XML_Char *s = appAtts[i];
+ for (j = 0; j < b->uriLen; j++) {
+ if (!poolAppendChar(&tempPool, b->uri[j]))
+ return XML_ERROR_NO_MEMORY;
+ }
+ while (*s++ != ':')
+ ;
+ do {
+ if (!poolAppendChar(&tempPool, *s))
+ return XML_ERROR_NO_MEMORY;
+ } while (*s++);
+ appAtts[i] = poolStart(&tempPool);
+ poolFinish(&tempPool);
+ }
+ if (!--nPrefixes)
+ break;
}
else
- ((XML_Char *)(appAtts[i]))[-1] = 0;
+ ((XML_Char *)(appAtts[i]))[-1] = 0;
}
}
/* clear the flags that say whether attributes were specified */
@@ -1813,98 +2006,114 @@
if (!uri)
return XML_ERROR_NO_MEMORY;
binding->uriAlloc = n + EXPAND_SPARE;
- memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char));
- for (p = tagStack; p; p = p->parent)
- if (p->name.str == binding->uri)
- p->name.str = uri;
- free(binding->uri);
- binding->uri = uri;
- }
- memcpy(binding->uri + binding->uriLen, localPart, i * sizeof(XML_Char));
- tagNamePtr->str = binding->uri;
- return XML_ERROR_NONE;
-}
-
-static
-int addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, const XML_Char *uri, BINDING **bindingsPtr)
-{
- BINDING *b;
- int len;
- for (len = 0; uri[len]; len++)
- ;
- if (namespaceSeparator)
- len++;
- if (freeBindingList) {
- b = freeBindingList;
- if (len > b->uriAlloc) {
- b->uri = realloc(b->uri, sizeof(XML_Char) * (len + EXPAND_SPARE));
- if (!b->uri)
- return 0;
- b->uriAlloc = len + EXPAND_SPARE;
- }
- freeBindingList = b->nextTagBinding;
- }
- else {
- b = malloc(sizeof(BINDING));
- if (!b)
- return 0;
- b->uri = malloc(sizeof(XML_Char) * (len + EXPAND_SPARE));
- if (!b->uri) {
- free(b);
- return 0;
- }
- b->uriAlloc = len + EXPAND_SPARE;
+ memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char));
+ for (p = tagStack; p; p = p->parent)
+ if (p->name.str == binding->uri)
+ p->name.str = uri;
+ free(binding->uri);
+ binding->uri = uri;
}
- b->uriLen = len;
- memcpy(b->uri, uri, len * sizeof(XML_Char));
- if (namespaceSeparator)
- b->uri[len - 1] = namespaceSeparator;
- b->prefix = prefix;
- b->attId = attId;
- b->prevPrefixBinding = prefix->binding;
- if (*uri == XML_T('\0') && prefix == &dtd.defaultPrefix)
- prefix->binding = 0;
- else
- prefix->binding = b;
- b->nextTagBinding = *bindingsPtr;
- *bindingsPtr = b;
- if (startNamespaceDeclHandler)
- startNamespaceDeclHandler(handlerArg, prefix->name,
- prefix->binding ? uri : 0);
- return 1;
+ memcpy(binding->uri + binding->uriLen, localPart, i * sizeof(XML_Char));
+ tagNamePtr->str = binding->uri;
+ return XML_ERROR_NONE;
}
-/* The idea here is to avoid using stack for each CDATA section when
-the whole file is parsed with one call. */
-static
-enum XML_Error cdataSectionProcessor(XML_Parser parser,
- const char *start,
- const char *end,
- const char **endPtr)
-{
- enum XML_Error result = doCdataSection(parser, encoding, &start, end, endPtr);
- if (start) {
- processor = contentProcessor;
- return contentProcessor(parser, start, end, endPtr);
- }
- return result;
+
+static Processor epilogProcessor;
+
+static void
+epilogProcessor(XML_Parser const xmlParserP,
+ const char * const startArg,
+ const char * const end,
+ const char ** const nextPtr,
+ enum XML_Error * const errorCodeP,
+ const char ** const errorP) {
+
+ Parser * const parser = (Parser *) xmlParserP;
+
+ const char * s;
+
+ *errorP = NULL;
+
+ s = startArg;
+
+ processor = epilogProcessor;
+ eventPtr = s;
+ for (;;) {
+ const char *next;
+ int tok = XmlPrologTok(parser->m_encoding, s, end, &next);
+ eventEndPtr = next;
+ switch (tok) {
+ case -XML_TOK_PROLOG_S:
+ if (defaultHandler) {
+ eventEndPtr = end;
+ reportDefault(xmlParserP, parser->m_encoding, s, end);
+ }
+ /* fall through */
+ case XML_TOK_NONE:
+ if (nextPtr)
+ *nextPtr = end;
+ *errorCodeP = XML_ERROR_NONE;
+ return;
+ case XML_TOK_PROLOG_S:
+ if (defaultHandler)
+ reportDefault(xmlParserP, parser->m_encoding, s, next);
+ break;
+ case XML_TOK_PI:
+ if (!reportProcessingInstruction(xmlParserP, parser->m_encoding,
+ s, next)) {
+ *errorCodeP = XML_ERROR_NO_MEMORY;
+ return;
+ }
+ break;
+ case XML_TOK_COMMENT:
+ if (!reportComment(xmlParserP, parser->m_encoding, s, next)) {
+ *errorCodeP = XML_ERROR_NO_MEMORY;
+ return;
+ }
+ break;
+ case XML_TOK_INVALID:
+ eventPtr = next;
+ *errorCodeP = XML_ERROR_INVALID_TOKEN;
+ return;
+ case XML_TOK_PARTIAL:
+ if (nextPtr) {
+ *nextPtr = s;
+ *errorCodeP = XML_ERROR_NONE;
+ } else
+ *errorCodeP = XML_ERROR_UNCLOSED_TOKEN;
+ return;
+ case XML_TOK_PARTIAL_CHAR:
+ if (nextPtr) {
+ *nextPtr = s;
+ *errorCodeP = XML_ERROR_NONE;
+ } else
+ *errorCodeP = XML_ERROR_PARTIAL_CHAR;
+ return;
+ default:
+ *errorCodeP = XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
+ return;
+ }
+ eventPtr = s = next;
+ }
}
-/* startPtr gets set to non-null is the section is closed, and to null if
-the section is not yet closed. */
-static
-enum XML_Error doCdataSection(XML_Parser parser,
- const ENCODING *enc,
- const char **startPtr,
- const char *end,
- const char **nextPtr)
-{
+
+static enum XML_Error
+doCdataSection(XML_Parser const xmlParserP,
+ const ENCODING * const enc,
+ const char ** const startPtr,
+ const char * const end,
+ const char ** const nextPtr) {
+
+ Parser * const parser = (Parser *) xmlParserP;
+
const char *s = *startPtr;
const char **eventPP;
const char **eventEndPP;
- if (enc == encoding) {
+ if (enc == parser->m_encoding) {
eventPP = &eventPtr;
*eventPP = s;
eventEndPP = &eventEndPtr;
@@ -1922,59 +2131,54 @@
switch (tok) {
case XML_TOK_CDATA_SECT_CLOSE:
if (endCdataSectionHandler)
- endCdataSectionHandler(handlerArg);
-#if 0
- /* see comment under XML_TOK_CDATA_SECT_OPEN */
- else if (characterDataHandler)
- characterDataHandler(handlerArg, dataBuf, 0);
-#endif
+ endCdataSectionHandler(handlerArg);
else if (defaultHandler)
- reportDefault(parser, enc, s, next);
+ reportDefault(xmlParserP, enc, s, next);
*startPtr = next;
return XML_ERROR_NONE;
case XML_TOK_DATA_NEWLINE:
if (characterDataHandler) {
- XML_Char c = 0xA;
- characterDataHandler(handlerArg, &c, 1);
+ XML_Char c = 0xA;
+ characterDataHandler(handlerArg, &c, 1);
}
else if (defaultHandler)
- reportDefault(parser, enc, s, next);
+ reportDefault(xmlParserP, enc, s, next);
break;
case XML_TOK_DATA_CHARS:
if (characterDataHandler) {
- if (MUST_CONVERT(enc, s)) {
- for (;;) {
- ICHAR *dataPtr = (ICHAR *)dataBuf;
- XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
- *eventEndPP = next;
- characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf);
- if (s == next)
- break;
- *eventPP = s;
- }
- }
- else
- characterDataHandler(handlerArg,
- (XML_Char *)s,
- (XML_Char *)next - (XML_Char *)s);
+ if (MUST_CONVERT(enc, s)) {
+ for (;;) {
+ ICHAR *dataPtr = (ICHAR *)dataBuf;
+ XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
+ *eventEndPP = next;
+ characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf);
+ if (s == next)
+ break;
+ *eventPP = s;
+ }
+ }
+ else
+ characterDataHandler(handlerArg,
+ (XML_Char *)s,
+ (XML_Char *)next - (XML_Char *)s);
}
else if (defaultHandler)
- reportDefault(parser, enc, s, next);
+ reportDefault(xmlParserP, enc, s, next);
break;
case XML_TOK_INVALID:
*eventPP = next;
return XML_ERROR_INVALID_TOKEN;
case XML_TOK_PARTIAL_CHAR:
if (nextPtr) {
- *nextPtr = s;
- return XML_ERROR_NONE;
+ *nextPtr = s;
+ return XML_ERROR_NONE;
}
return XML_ERROR_PARTIAL_CHAR;
case XML_TOK_PARTIAL:
case XML_TOK_NONE:
if (nextPtr) {
- *nextPtr = s;
- return XML_ERROR_NONE;
+ *nextPtr = s;
+ return XML_ERROR_NONE;
}
return XML_ERROR_UNCLOSED_CDATA_SECTION;
default:
@@ -1985,246 +2189,1024 @@
/* not reached */
}
-#ifdef XML_DTD
-/* The idea here is to avoid using stack for each IGNORE section when
+
+/* Forward declaration for recursive reference: */
+static void
+doContent(XML_Parser const xmlParserP,
+ int const startTagLevel,
+ const ENCODING * const enc,
+ const char * const startArg,
+ const char * const end,
+ const char ** const nextPtr,
+ enum XML_Error * const errorCodeP,
+ const char ** const errorP);
+
+
+static Processor contentProcessor;
+
+static void
+contentProcessor(XML_Parser const xmlParserP,
+ const char * const start,
+ const char * const end,
+ const char ** const endPtr,
+ enum XML_Error * const errorCodeP,
+ const char ** const errorP) {
+
+ Parser * const parser = (Parser *) xmlParserP;
+
+ const char * error;
+
+ parser->m_errorString = NULL;
+
+ doContent(xmlParserP, 0, parser->m_encoding, start, end, endPtr,
+ errorCodeP, &error);
+
+ if (*errorCodeP != XML_ERROR_NONE) {
+ if (error) {
+ xmlrpc_asprintf(errorP, "Invalid XML \"content\". %s", error);
+
+ xmlrpc_strfree(error);
+ } else {
+ const char * const sampleXml = extractXmlSample(start, end, 40);
+
+ xmlrpc_asprintf(errorP, "Invalid XML \"content\" starting "
+ "with '%s'. %s",
+ sampleXml,
+ xmlrpc_XML_ErrorString(*errorCodeP));
+
+ xmlrpc_strfree(sampleXml);
+ }
+ } else
+ *errorP = NULL;
+}
+
+
+
+/* The idea here is to avoid using stack for each CDATA section when
the whole file is parsed with one call. */
-static
-enum XML_Error ignoreSectionProcessor(XML_Parser parser,
- const char *start,
- const char *end,
- const char **endPtr)
-{
- enum XML_Error result = doIgnoreSection(parser, encoding, &start, end, endPtr);
- if (start) {
- processor = prologProcessor;
- return prologProcessor(parser, start, end, endPtr);
- }
- return result;
+
+
+static Processor cdataSectionProcessor;
+
+static void
+cdataSectionProcessor(XML_Parser const xmlParserP,
+ const char * const startArg,
+ const char * const end,
+ const char ** const endPtr,
+ enum XML_Error * const errorCodeP,
+ const char ** const errorP) {
+
+ Parser * const parser = (Parser *) xmlParserP;
+
+ enum XML_Error result;
+ const char * start;
+
+ start = startArg;
+
+ result =
+ doCdataSection(xmlParserP, parser->m_encoding, &start, end, endPtr);
+
+ if (start) {
+ processor = contentProcessor;
+ contentProcessor(xmlParserP, start, end, endPtr, errorCodeP, errorP);
+ } else {
+ *errorCodeP = result;
+ *errorP = NULL;
+ }
}
-/* startPtr gets set to non-null is the section is closed, and to null if
-the section is not yet closed. */
-static
-enum XML_Error doIgnoreSection(XML_Parser parser,
- const ENCODING *enc,
- const char **startPtr,
- const char *end,
- const char **nextPtr)
-{
- const char *next;
- int tok;
- const char *s = *startPtr;
- const char **eventPP;
- const char **eventEndPP;
- if (enc == encoding) {
- eventPP = &eventPtr;
- *eventPP = s;
- eventEndPP = &eventEndPtr;
- }
- else {
- eventPP = &(openInternalEntities->internalEventPtr);
- eventEndPP = &(openInternalEntities->internalEventEndPtr);
- }
- *eventPP = s;
- *startPtr = 0;
- tok = XmlIgnoreSectionTok(enc, s, end, &next);
- *eventEndPP = next;
- switch (tok) {
- case XML_TOK_IGNORE_SECT:
- if (defaultHandler)
- reportDefault(parser, enc, s, next);
- *startPtr = next;
- return XML_ERROR_NONE;
- case XML_TOK_INVALID:
- *eventPP = next;
- return XML_ERROR_INVALID_TOKEN;
- case XML_TOK_PARTIAL_CHAR:
- if (nextPtr) {
- *nextPtr = s;
- return XML_ERROR_NONE;
+
+static void
+doEntityRef(XML_Parser const xmlParserP,
+ const ENCODING * const enc,
+ const char * const s,
+ const char * const next,
+ enum XML_Error * const errorCodeP,
+ const char ** const errorP) {
+
+ Parser * const parser = (Parser *) xmlParserP;
+
+ XML_Char const ch = XmlPredefinedEntityName(enc,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ const XML_Char *name;
+ ENTITY *entity;
+ *errorP = NULL;
+
+ if (ch) {
+ if (characterDataHandler)
+ characterDataHandler(handlerArg, &ch, 1);
+ else if (defaultHandler)
+ reportDefault(xmlParserP, enc, s, next);
+ *errorCodeP = XML_ERROR_NONE;
+ return;
+ }
+ name = poolStoreString(&dtd.pool, enc,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (!name) {
+ *errorCodeP = XML_ERROR_NO_MEMORY;
+ return;
+ }
+ entity = (ENTITY *)lookup(&dtd.generalEntities, name, 0);
+ poolDiscard(&dtd.pool);
+ if (!entity) {
+ if (dtd.complete || dtd.standalone)
+ *errorCodeP = XML_ERROR_UNDEFINED_ENTITY;
+ else {
+ if (defaultHandler)
+ reportDefault(xmlParserP, enc, s, next);
+ *errorCodeP = XML_ERROR_NONE;
+ }
+ return;
+ }
+ if (entity->open) {
+ *errorCodeP = XML_ERROR_RECURSIVE_ENTITY_REF;
+ return;
+ }
+ if (entity->notation) {
+ *errorCodeP = XML_ERROR_BINARY_ENTITY_REF;
+ return;
+ }
+ if (entity) {
+ if (entity->textPtr) {
+ OPEN_INTERNAL_ENTITY openEntity;
+ if (defaultHandler && !defaultExpandInternalEntities) {
+ reportDefault(xmlParserP, enc, s, next);
+ *errorCodeP = XML_ERROR_NONE;
+ return;
+ }
+ entity->open = 1;
+ openEntity.next = openInternalEntities;
+ openInternalEntities = &openEntity;
+ openEntity.entity = entity;
+ openEntity.internalEventPtr = 0;
+ openEntity.internalEventEndPtr = 0;
+ doContent(xmlParserP,
+ tagLevel,
+ internalEncoding,
+ (char *)entity->textPtr,
+ (char *)(entity->textPtr + entity->textLen),
+ 0, errorCodeP, errorP);
+ entity->open = 0;
+ openInternalEntities = openEntity.next;
+ if (*errorCodeP != XML_ERROR_NONE)
+ return;
+ } else if (externalEntityRefHandler) {
+ const XML_Char *context;
+ entity->open = 1;
+ context = getContext(xmlParserP);
+ entity->open = 0;
+ if (!context) {
+ *errorCodeP = XML_ERROR_NO_MEMORY;
+ return;
+ }
+ if (!externalEntityRefHandler(externalEntityRefHandlerArg,
+ context,
+ entity->base,
+ entity->systemId,
+ entity->publicId)) {
+ *errorCodeP = XML_ERROR_EXTERNAL_ENTITY_HANDLING;
+ return;
+ }
+ poolDiscard(&tempPool);
+ } else if (defaultHandler)
+ reportDefault(xmlParserP, enc, s, next);
}
- return XML_ERROR_PARTIAL_CHAR;
- case XML_TOK_PARTIAL:
- case XML_TOK_NONE:
+ *errorCodeP = XML_ERROR_NONE;
+}
+
+
+
+static void
+doStartTagNoAtts(XML_Parser const xmlParserP,
+ const ENCODING * const enc,
+ const char * const s,
+ const char * const next,
+ const char ** const nextPtr,
+ enum XML_Error * const errorCodeP,
+ const char ** const errorP) {
+
+ Parser * const parser = (Parser *) xmlParserP;
+
+ TAG *tag;
+
+ *errorP = NULL;
+
+ if (freeTagList) {
+ tag = freeTagList;
+ freeTagList = freeTagList->parent;
+ } else {
+ tag = malloc(sizeof(TAG));
+ if (!tag) {
+ *errorCodeP = XML_ERROR_NO_MEMORY;
+ return;
+ }
+ tag->buf = malloc(INIT_TAG_BUF_SIZE);
+ if (!tag->buf) {
+ *errorCodeP = XML_ERROR_NO_MEMORY;
+ return;
+ }
+ tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE;
+ }
+ tag->bindings = NULL;
+ tag->parent = tagStack;
+ tagStack = tag;
+ tag->name.localPart = 0;
+ tag->rawName = s + enc->minBytesPerChar;
+ tag->rawNameLength = XmlNameLength(enc, tag->rawName);
if (nextPtr) {
- *nextPtr = s;
- return XML_ERROR_NONE;
+ /* Need to guarantee that: tag->buf +
+ ROUND_UP(tag->rawNameLength, sizeof(XML_Char)) <=
+ tag->bufEnd - sizeof(XML_Char)
+ */
+
+ if (tag->rawNameLength +
+ (int)(sizeof(XML_Char) - 1) +
+ (int)sizeof(XML_Char) > tag->bufEnd - tag->buf) {
+ int bufSize = tag->rawNameLength * 4;
+ bufSize = ROUND_UP(bufSize, sizeof(XML_Char));
+ tag->buf = realloc(tag->buf, bufSize);
+ if (!tag->buf) {
+ *errorCodeP = XML_ERROR_NO_MEMORY;
+ return;
+ }
+ tag->bufEnd = tag->buf + bufSize;
+ }
+ memcpy(tag->buf, tag->rawName, tag->rawNameLength);
+ tag->rawName = tag->buf;
+ }
+ ++tagLevel;
+ if (startElementHandler) {
+ enum XML_Error result;
+ XML_Char *toPtr;
+ for (;;) {
+ const char *rawNameEnd = tag->rawName + tag->rawNameLength;
+ const char *fromPtr = tag->rawName;
+ if (nextPtr)
+ toPtr = (XML_Char *)
+ (tag->buf + ROUND_UP(tag->rawNameLength,
+ sizeof(XML_Char)));
+ else
+ toPtr = (XML_Char *)tag->buf;
+ tag->name.str = toPtr;
+ XmlConvert(enc,
+ &fromPtr, rawNameEnd,
+ (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1);
+ if (fromPtr == rawNameEnd)
+ break;
+ else {
+ int const bufSize = (tag->bufEnd - tag->buf) << 1;
+ tag->buf = realloc(tag->buf, bufSize);
+ if (!tag->buf) {
+ *errorCodeP = XML_ERROR_NO_MEMORY;
+ return;
+ }
+ tag->bufEnd = tag->buf + bufSize;
+ if (nextPtr)
+ tag->rawName = tag->buf;
+ }
+ }
+ *toPtr = XML_T('\0');
+ result = storeAtts(xmlParserP, enc, s,
+ &(tag->name), &(tag->bindings));
+ if (result) {
+ *errorCodeP = result;
+ return;
+ }
+ startElementHandler(handlerArg, tag->name.str,
+ (const XML_Char **)atts);
+ poolClear(&tempPool);
+ } else {
+ tag->name.str = 0;
+ if (defaultHandler)
+ reportDefault(xmlParserP, enc, s, next);
}
- return XML_ERROR_SYNTAX; /* XML_ERROR_UNCLOSED_IGNORE_SECTION */
- default:
- abort();
- }
- /* not reached */
}
-#endif /* XML_DTD */
-static enum XML_Error
-initializeEncoding(XML_Parser parser)
-{
- const char *s;
-#ifdef XML_UNICODE
- char encodingBuf[128];
- if (!protocolEncodingName)
- s = 0;
- else {
- int i;
- for (i = 0; protocolEncodingName[i]; i++) {
- if (i == sizeof(encodingBuf) - 1
- || (protocolEncodingName[i] & ~0x7f) != 0) {
- encodingBuf[0] = '\0';
- break;
- }
- encodingBuf[i] = (char)protocolEncodingName[i];
+
+static void
+doEmptyElementNoAtts(XML_Parser const xmlParserP,
+ const ENCODING * const enc,
+ const char * const s,
+ const char * const end,
+ const char * const next,
+ const char ** const nextPtr,
+ const char ** const eventPP,
+ const char ** const eventEndPP,
+ bool * const doneP,
+ enum XML_Error * const errorCodeP,
+ const char ** const errorP) {
+
+ Parser * const parser = (Parser *) xmlParserP;
+
+ if (startElementHandler || endElementHandler) {
+ const char * const rawName = s + enc->minBytesPerChar;
+
+ enum XML_Error result;
+ BINDING * bindings;
+ TAG_NAME name;
+
+ bindings = NULL; /* initial value */
+ name.str = poolStoreString(&tempPool, enc, rawName,
+ rawName + XmlNameLength(enc, rawName));
+ if (!name.str) {
+ *errorCodeP = XML_ERROR_NO_MEMORY;
+ return;
+ }
+ poolFinish(&tempPool);
+ result = storeAtts(xmlParserP, enc, s, &name, &bindings);
+ if (result) {
+ *errorCodeP = result;
+ return;
+ }
+ poolFinish(&tempPool);
+ if (startElementHandler)
+ startElementHandler(handlerArg, name.str, (const XML_Char **)atts);
+ if (endElementHandler) {
+ if (startElementHandler)
+ *eventPP = *eventEndPP;
+ endElementHandler(handlerArg, name.str);
+ }
+ poolClear(&tempPool);
+ while (bindings) {
+ BINDING * const b = bindings;
+ if (endNamespaceDeclHandler)
+ endNamespaceDeclHandler(handlerArg, b->prefix->name);
+ bindings = bindings->nextTagBinding;
+ b->nextTagBinding = freeBindingList;
+ freeBindingList = b;
+ b->prefix->binding = b->prevPrefixBinding;
+ }
+ } else if (defaultHandler)
+ reportDefault(xmlParserP, enc, s, next);
+
+ if (tagLevel == 0) {
+ epilogProcessor(xmlParserP, next, end, nextPtr, errorCodeP, errorP);
+ *doneP = true;
+ } else
+ *doneP = false;
+}
+
+
+
+static void
+doEndTag(XML_Parser const xmlParserP,
+ const ENCODING * const enc,
+ const char * const s,
+ const char * const end,
+ const char * const next,
+ const char ** const nextPtr,
+ int const startTagLevel,
+ const char ** const eventPP,
+ bool * const doneP,
+ enum XML_Error * const errorCodeP,
+ const char ** const errorP) {
+
+ Parser * const parser = (Parser *) xmlParserP;
+
+ if (tagLevel == startTagLevel)
+ *errorCodeP = XML_ERROR_ASYNC_ENTITY;
+ else {
+ TAG * const tag = tagStack;
+
+ int len;
+ const char * rawName;
+
+ tagStack = tag->parent;
+ tag->parent = freeTagList;
+ freeTagList = tag;
+ rawName = s + enc->minBytesPerChar*2;
+ len = XmlNameLength(enc, rawName);
+ if (len != tag->rawNameLength
+ || memcmp(tag->rawName, rawName, len) != 0) {
+ *eventPP = rawName;
+ *errorCodeP = XML_ERROR_TAG_MISMATCH;
+ } else {
+ --tagLevel;
+ if (endElementHandler && tag->name.str) {
+ if (tag->name.localPart) {
+ XML_Char * to;
+ const XML_Char * from;
+ to = (XML_Char *)tag->name.str + tag->name.uriLen;
+ from = tag->name.localPart;
+ while ((*to++ = *from++) != 0)
+ ;
+ }
+ endElementHandler(handlerArg, tag->name.str);
+ } else if (defaultHandler)
+ reportDefault(xmlParserP, enc, s, next);
+
+ while (tag->bindings) {
+ BINDING * const b = tag->bindings;
+ if (endNamespaceDeclHandler)
+ endNamespaceDeclHandler(handlerArg, b->prefix->name);
+ tag->bindings = tag->bindings->nextTagBinding;
+ b->nextTagBinding = freeBindingList;
+ freeBindingList = b;
+ b->prefix->binding = b->prevPrefixBinding;
+ }
+ if (tagLevel == 0) {
+ epilogProcessor(xmlParserP, next, end, nextPtr,
+ errorCodeP, errorP);
+ *doneP = true;
+ } else {
+ *errorCodeP = XML_ERROR_NONE;
+ *doneP = false;
+ }
+ }
}
- encodingBuf[i] = '\0';
- s = encodingBuf;
- }
-#else
- s = protocolEncodingName;
-#endif
- if ((ns ? XmlInitEncodingNS : XmlInitEncoding)(&initEncoding, &encoding, s))
- return XML_ERROR_NONE;
- return handleUnknownEncoding(parser, protocolEncodingName);
}
-static enum XML_Error
-processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
- const char *s, const char *next)
-{
- const char *encodingName = 0;
- const ENCODING *newEncoding = 0;
- const char *version;
- int standalone = -1;
- if (!(ns
- ? XmlParseXmlDeclNS
- : XmlParseXmlDecl)(isGeneralTextEntity,
- encoding,
- s,
- next,
- &eventPtr,
- &version,
- &encodingName,
- &newEncoding,
- &standalone))
- return XML_ERROR_SYNTAX;
- if (!isGeneralTextEntity && standalone == 1) {
- dtd.standalone = 1;
-#ifdef XML_DTD
- if (paramEntityParsing == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE)
- paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
-#endif /* XML_DTD */
- }
- if (defaultHandler)
- reportDefault(parser, encoding, s, next);
- if (!protocolEncodingName) {
- if (newEncoding) {
- if (newEncoding->minBytesPerChar != encoding->minBytesPerChar) {
- eventPtr = encodingName;
- return XML_ERROR_INCORRECT_ENCODING;
+
+
+static void
+processContentToken(XML_Parser const xmlParserP,
+ int const tok,
+ const ENCODING * const enc,
+ const char * const s,
+ const char * const end,
+ const char ** const nextP,
+ const char ** const nextPtr,
+ int const startTagLevel,
+ const char ** const eventPP,
+ const char ** const eventEndPP,
+ bool * const doneP,
+ enum XML_Error * const errorCodeP,
+ const char ** const errorP) {
+
+ Parser * const parser = (Parser *) xmlParserP;
+
+ *errorP = NULL;
+ *errorCodeP = XML_ERROR_NONE;
+
+ switch (tok) {
+ case XML_TOK_TRAILING_CR:
+ if (nextPtr) {
+ *nextPtr = s;
+ *doneP = true;
+ } else {
+ *eventEndPP = end;
+
+ if (characterDataHandler) {
+ XML_Char c = 0xA;
+ characterDataHandler(handlerArg, &c, 1);
+ } else if (defaultHandler)
+ reportDefault(xmlParserP, enc, s, end);
+
+ if (startTagLevel == 0)
+ *errorCodeP = XML_ERROR_NO_ELEMENTS;
+ else if (tagLevel != startTagLevel) {
+ *errorCodeP = XML_ERROR_ASYNC_ENTITY;
+ } else
+ *doneP = true;
}
- encoding = newEncoding;
+ break;
+ case XML_TOK_NONE:
+ if (nextPtr) {
+ *nextPtr = s;
+ *doneP = true;
+ } else if (startTagLevel > 0) {
+ if (tagLevel != startTagLevel)
+ *errorCodeP = XML_ERROR_ASYNC_ENTITY;
+ else
+ *doneP = true;
+ } else
+ *errorCodeP = XML_ERROR_NO_ELEMENTS;
+ break;
+ case XML_TOK_INVALID:
+ *eventPP = *nextP;
+ *errorCodeP = XML_ERROR_INVALID_TOKEN;
+ xmlrpc_asprintf(errorP, "Invalid token, starting %ld bytes in",
+ (long)(*nextP - s));
+ break;
+ case XML_TOK_PARTIAL:
+ if (nextPtr) {
+ *nextPtr = s;
+ *doneP = true;
+ } else
+ *errorCodeP = XML_ERROR_UNCLOSED_TOKEN;
+ break;
+ case XML_TOK_PARTIAL_CHAR:
+ if (nextPtr) {
+ *nextPtr = s;
+ *doneP = true;
+ } else
+ *errorCodeP = XML_ERROR_PARTIAL_CHAR;
+ break;
+ case XML_TOK_ENTITY_REF:
+ doEntityRef(xmlParserP, enc, s, *nextP, errorCodeP, errorP);
+ break;
+ case XML_TOK_START_TAG_WITH_ATTS:
+ if (!startElementHandler)
+ *errorCodeP = storeAtts(xmlParserP, enc, s, 0, 0);
+ if (*errorCodeP == XML_ERROR_NONE)
+ doStartTagNoAtts(xmlParserP, enc, s, *nextP, nextPtr,
+ errorCodeP, errorP);
+ break;
+ case XML_TOK_START_TAG_NO_ATTS:
+ doStartTagNoAtts(xmlParserP, enc, s, *nextP, nextPtr,
+ errorCodeP, errorP);
+ break;
+ case XML_TOK_EMPTY_ELEMENT_WITH_ATTS:
+ if (!startElementHandler)
+ *errorCodeP = storeAtts(xmlParserP, enc, s, 0, 0);
+
+ if (*errorCodeP == XML_ERROR_NONE)
+ doEmptyElementNoAtts(xmlParserP, enc, s, end, *nextP, nextPtr,
+ eventPP, eventEndPP,
+ doneP, errorCodeP, errorP);
+ break;
+ case XML_TOK_EMPTY_ELEMENT_NO_ATTS:
+ doEmptyElementNoAtts(xmlParserP, enc, s, end, *nextP, nextPtr,
+ eventPP, eventEndPP,
+ doneP, errorCodeP, errorP);
+ break;
+ case XML_TOK_END_TAG:
+ doEndTag(xmlParserP, enc, s, end, *nextP, nextPtr, startTagLevel,
+ eventPP, doneP, errorCodeP, errorP);
+ break;
+ case XML_TOK_CHAR_REF: {
+ int const n = XmlCharRefNumber(enc, s);
+ if (n < 0)
+ *errorCodeP = XML_ERROR_BAD_CHAR_REF;
+ else {
+ if (characterDataHandler) {
+ XML_Char buf[XML_ENCODE_MAX];
+ characterDataHandler(handlerArg, buf,
+ XmlEncode(n, (ICHAR *)buf));
+ } else if (defaultHandler)
+ reportDefault(xmlParserP, enc, s, *nextP);
+ }
+ } break;
+ case XML_TOK_XML_DECL:
+ *errorCodeP = XML_ERROR_MISPLACED_XML_PI;
+ break;
+ case XML_TOK_DATA_NEWLINE:
+ if (characterDataHandler) {
+ XML_Char c = 0xA;
+ characterDataHandler(handlerArg, &c, 1);
+ } else if (defaultHandler)
+ reportDefault(xmlParserP, enc, s, *nextP);
+ break;
+ case XML_TOK_CDATA_SECT_OPEN: {
+ enum XML_Error result;
+ if (startCdataSectionHandler)
+ startCdataSectionHandler(handlerArg);
+ else if (defaultHandler)
+ reportDefault(xmlParserP, enc, s, *nextP);
+ result = doCdataSection(xmlParserP, enc, nextP, end, nextPtr);
+ if (!*nextP) {
+ processor = cdataSectionProcessor;
+ *errorCodeP = result;
+ }
+ } break;
+ case XML_TOK_TRAILING_RSQB:
+ if (nextPtr) {
+ *nextPtr = s;
+ *errorCodeP = XML_ERROR_NONE;
+ } else {
+ if (characterDataHandler) {
+ if (MUST_CONVERT(enc, s)) {
+ const char * from;
+ ICHAR * dataPtr;
+ from = s;
+ dataPtr = (ICHAR *)dataBuf;
+ XmlConvert(enc, &from, end, &dataPtr, (ICHAR *)dataBufEnd);
+ characterDataHandler(handlerArg, dataBuf,
+ dataPtr - (ICHAR *)dataBuf);
+ } else
+ characterDataHandler(handlerArg,
+ (XML_Char *)s,
+ (XML_Char *)end - (XML_Char *)s);
+ } else if (defaultHandler)
+ reportDefault(xmlParserP, enc, s, end);
+
+ if (startTagLevel == 0) {
+ *eventPP = end;
+ *errorCodeP = XML_ERROR_NO_ELEMENTS;
+ } else if (tagLevel != startTagLevel) {
+ *eventPP = end;
+ *errorCodeP = XML_ERROR_ASYNC_ENTITY;
+ } else
+ *doneP = true;
+ }
+ break;
+ case XML_TOK_DATA_CHARS:
+ if (characterDataHandler) {
+ if (MUST_CONVERT(enc, s)) {
+ for (;;) {
+ const char * from;
+ ICHAR * dataPtr;
+ dataPtr = (ICHAR *)dataBuf;
+ from = s;
+ XmlConvert(enc, &from, *nextP, &dataPtr,
+ (ICHAR *)dataBufEnd);
+ *eventEndPP = from;
+ characterDataHandler(handlerArg, dataBuf,
+ dataPtr - (ICHAR *)dataBuf);
+ if (from == *nextP)
+ break;
+ *eventPP = from;
+ }
+ } else
+ characterDataHandler(handlerArg,
+ (XML_Char *)s,
+ (XML_Char *)*nextP - (XML_Char *)s);
+ } else if (defaultHandler)
+ reportDefault(xmlParserP, enc, s, *nextP);
+ break;
+ case XML_TOK_PI:
+ if (!reportProcessingInstruction(xmlParserP, enc, s, *nextP))
+ *errorCodeP = XML_ERROR_NO_MEMORY;
+ break;
+ case XML_TOK_COMMENT:
+ if (!reportComment(xmlParserP, enc, s, *nextP))
+ *errorCodeP = XML_ERROR_NO_MEMORY;
+ break;
+ default:
+ if (defaultHandler)
+ reportDefault(xmlParserP, enc, s, *nextP);
+ break;
}
- else if (encodingName) {
- enum XML_Error result;
- const XML_Char *s = poolStoreString(&tempPool,
- encoding,
- encodingName,
- encodingName
- + XmlNameLength(encoding, encodingName));
- if (!s)
- return XML_ERROR_NO_MEMORY;
- result = handleUnknownEncoding(parser, s);
- poolDiscard(&tempPool);
- if (result == XML_ERROR_UNKNOWN_ENCODING)
- eventPtr = encodingName;
- return result;
+}
+
+
+
+static void
+doContent(XML_Parser const xmlParserP,
+ int const startTagLevel,
+ const ENCODING * const enc,
+ const char * const startArg,
+ const char * const end,
+ const char ** const nextPtr,
+ enum XML_Error * const errorCodeP,
+ const char ** const errorP) {
+
+ Parser * const parser = (Parser *) xmlParserP;
+
+ const char **eventPP;
+ const char **eventEndPP;
+ const char * s;
+ bool done;
+
+ if (enc == parser->m_encoding) {
+ eventPP = &eventPtr;
+ eventEndPP = &eventEndPtr;
+ } else {
+ eventPP = &(openInternalEntities->internalEventPtr);
+ eventEndPP = &(openInternalEntities->internalEventEndPtr);
+ }
+
+ s = startArg;
+ *eventPP = s;
+ done = false;
+ *errorCodeP = XML_ERROR_NONE;
+ *errorP = NULL;
+
+ while (*errorCodeP == XML_ERROR_NONE && !done) {
+ int tok;
+ const char * next;
+ const char * error;
+
+ next = s; /* XmlContentTok doesn't always set the last arg */
+ /* XmlContentTok() is normally normal_contentTok(), aka
+ PREFIX(contentTok)() in xmltok/xmltok_impl.c
+ */
+ tok = XmlContentTok(enc, s, end, &next);
+ *eventEndPP = next;
+
+ processContentToken(xmlParserP, tok, enc, s, end, &next, nextPtr,
+ startTagLevel, eventPP, eventEndPP, &done,
+ errorCodeP, &error);
+
+ if (*errorCodeP != XML_ERROR_NONE) {
+ const char * const xmlSample = extractXmlSample(s, end, 40);
+
+ if (error) {
+ xmlrpc_asprintf(errorP, "Problem with token at '%s...': %s",
+ xmlSample, error);
+ xmlrpc_strfree(error);
+ } else
+ xmlrpc_asprintf(errorP, "Problem with token at '%s...': %s",
+ xmlSample,
+ xmlrpc_XML_ErrorString(*errorCodeP));
+
+ xmlrpc_strfree(xmlSample);
+ }
+ *eventPP = s = next;
}
- }
- return XML_ERROR_NONE;
}
-static enum XML_Error
-handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName)
-{
- if (unknownEncodingHandler) {
- XML_Encoding info;
- int i;
- for (i = 0; i < 256; i++)
- info.map[i] = -1;
- info.convert = 0;
- info.data = 0;
- info.release = 0;
- if (unknownEncodingHandler(unknownEncodingHandlerData, encodingName, &info)) {
- ENCODING *enc;
- unknownEncodingMem = malloc(XmlSizeOfUnknownEncoding());
- if (!unknownEncodingMem) {
- if (info.release)
- info.release(info.data);
- return XML_ERROR_NO_MEMORY;
- }
- enc = (ns
- ? XmlInitUnknownEncodingNS
- : XmlInitUnknownEncoding)(unknownEncodingMem,
- info.map,
- info.convert,
- info.data);
- if (enc) {
- unknownEncodingData = info.data;
- unknownEncodingRelease = info.release;
- encoding = enc;
- return XML_ERROR_NONE;
- }
+
+
+static Processor externalEntityContentProcessor;
+
+static void
+externalEntityContentProcessor(XML_Parser const xmlParserP,
+ const char * const start,
+ const char * const end,
+ const char ** const endPtr,
+ enum XML_Error * const errorCodeP,
+ const char ** const errorP) {
+
+ Parser * const parser = (Parser *) xmlParserP;
+
+ *errorP = NULL;
+
+ doContent(xmlParserP, 1, parser->m_encoding, start, end, endPtr,
+ errorCodeP, errorP);
+}
+
+
+
+static Processor externalEntityInitProcessor3;
+
+static void
+externalEntityInitProcessor3(XML_Parser const xmlParserP,
+ const char * const startArg,
+ const char * const end,
+ const char ** const endPtr,
+ enum XML_Error * const errorCodeP,
+ const char ** const errorP) {
+
+ Parser * const parser = (Parser *) xmlParserP;
+
+ const char * start;
+ const char *next;
+ int tok;
+
+ tok = XmlContentTok(parser->m_encoding, startArg, end, &next);
+
+ *errorP = NULL;
+
+ start = startArg;
+
+ switch (tok) {
+ case XML_TOK_XML_DECL:
+ {
+ enum XML_Error result = processXmlDecl(xmlParserP, 1, start, next);
+ if (result != XML_ERROR_NONE) {
+ *errorCodeP = result;
+ return;
+ }
+ start = next;
+ }
+ break;
+ case XML_TOK_PARTIAL:
+ if (endPtr) {
+ *endPtr = start;
+ *errorCodeP = XML_ERROR_NONE;
+ return;
+ }
+ eventPtr = start;
+ *errorCodeP = XML_ERROR_UNCLOSED_TOKEN;
+ return;
+ case XML_TOK_PARTIAL_CHAR:
+ if (endPtr) {
+ *endPtr = start;
+ *errorCodeP = XML_ERROR_NONE;
+ return;
+ }
+ eventPtr = start;
+ *errorCodeP = XML_ERROR_PARTIAL_CHAR;
+ return;
+ }
+ processor = externalEntityContentProcessor;
+ tagLevel = 1;
+ doContent(xmlParserP, 1, parser->m_encoding, start, end, endPtr,
+ errorCodeP, errorP);
+}
+
+
+
+static Processor externalEntityInitProcessor2;
+
+static void
+externalEntityInitProcessor2(XML_Parser const xmlParserP,
+ const char * const startArg,
+ const char * const end,
+ const char ** const endPtr,
+ enum XML_Error * const errorCodeP,
+ const char ** const errorP) {
+
+ Parser * const parser = (Parser *)xmlParserP;
+
+ const char * start;
+ const char * next;
+ int tok;
+
+ tok = XmlContentTok(parser->m_encoding, startArg, end, &next);
+
+ start = startArg;
+
+ switch (tok) {
+ case XML_TOK_BOM:
+ start = next;
+ break;
+ case XML_TOK_PARTIAL:
+ if (endPtr) {
+ *endPtr = start;
+ *errorCodeP = XML_ERROR_NONE;
+ *errorP = NULL;
+ } else {
+ eventPtr = start;
+ *errorCodeP = XML_ERROR_UNCLOSED_TOKEN;
+ *errorP = NULL;
+ }
+ return;
+ case XML_TOK_PARTIAL_CHAR:
+ if (endPtr) {
+ *endPtr = start;
+ *errorCodeP = XML_ERROR_NONE;
+ *errorP = NULL;
+ } else {
+ eventPtr = start;
+ *errorCodeP = XML_ERROR_PARTIAL_CHAR;
+ *errorP = NULL;
+ }
+ return;
+ }
+ processor = externalEntityInitProcessor3;
+ externalEntityInitProcessor3(xmlParserP, start, end, endPtr,
+ errorCodeP, errorP);
+}
+
+
+
+static Processor externalEntityInitProcessor;
+
+static void
+externalEntityInitProcessor(XML_Parser const parser,
+ const char * const start,
+ const char * const end,
+ const char ** const endPtr,
+ enum XML_Error * const errorCodeP,
+ const char ** const errorP) {
+
+ enum XML_Error result;
+
+ result = initializeEncoding(parser);
+
+ if (result != XML_ERROR_NONE) {
+ *errorCodeP = result;
+ *errorP = NULL;
+ } else {
+ processor = externalEntityInitProcessor2;
+
+ externalEntityInitProcessor2(parser, start, end, endPtr,
+ errorCodeP, errorP);
}
- if (info.release)
- info.release(info.data);
- }
- return XML_ERROR_UNKNOWN_ENCODING;
}
+
+
static enum XML_Error
-prologInitProcessor(XML_Parser parser,
- const char *s,
- const char *end,
- const char **nextPtr)
-{
- enum XML_Error result = initializeEncoding(parser);
- if (result != XML_ERROR_NONE)
- return result;
- processor = prologProcessor;
- return prologProcessor(parser, s, end, nextPtr);
+doIgnoreSection(XML_Parser const xmlParserP,
+ const ENCODING * const enc,
+ const char ** const startPtr,
+ const char * const end,
+ const char ** const nextPtr) {
+/*----------------------------------------------------------------------------
+
+ We set *startPtr to non-null is the section is closed, and to null if
+ the section is not yet closed.
+-----------------------------------------------------------------------------*/
+ Parser * const parser = (Parser *) xmlParserP;
+ const char * const s = *startPtr;
+
+ enum XML_Error retval;
+ const char * next;
+ int tok;
+ const char ** eventPP;
+ const char ** eventEndPP;
+
+ if (enc == parser->m_encoding) {
+ eventPP = &eventPtr;
+ eventEndPP = &eventEndPtr;
+ } else {
+ eventPP = &(openInternalEntities->internalEventPtr);
+ eventEndPP = &(openInternalEntities->internalEventEndPtr);
+ }
+ *eventPP = s;
+ *startPtr = '\0';
+ tok = XmlIgnoreSectionTok(enc, s, end, &next);
+ *eventEndPP = next;
+
+ switch (tok) {
+ case XML_TOK_IGNORE_SECT:
+ if (defaultHandler)
+ reportDefault(xmlParserP, enc, s, next);
+ *startPtr = next;
+ retval = XML_ERROR_NONE;
+ break;
+ case XML_TOK_INVALID:
+ *eventPP = next;
+ retval = XML_ERROR_INVALID_TOKEN;
+ break;
+ case XML_TOK_PARTIAL_CHAR:
+ if (nextPtr) {
+ *nextPtr = s;
+ retval = XML_ERROR_NONE;
+ } else
+ retval = XML_ERROR_PARTIAL_CHAR;
+ break;
+ case XML_TOK_PARTIAL:
+ case XML_TOK_NONE:
+ if (nextPtr) {
+ *nextPtr = s;
+ retval = XML_ERROR_NONE;
+ } else
+ retval = XML_ERROR_SYNTAX; /* XML_ERROR_UNCLOSED_IGNORE_SECTION */
+ break;
+ default:
+ assert(false); /* All possibilities are handled above */
+ retval = 99; /* quiet compiler warning */
+ }
+
+ return retval;
+}
+
+
+
+static Processor prologProcessor;
+
+
+/* The idea here is to avoid using stack for each IGNORE section when
+the whole file is parsed with one call. */
+
+static Processor ignoreSectionProcessor;
+
+static void
+ignoreSectionProcessor(XML_Parser const xmlParserP,
+ const char * const startArg,
+ const char * const end,
+ const char ** const endPtr,
+ enum XML_Error * const errorCodeP,
+ const char ** const errorP) {
+
+ Parser * const parser = (Parser *) xmlParserP;
+
+ enum XML_Error result;
+ const char * start;
+
+ start = startArg; /* initial value */
+
+ result = doIgnoreSection(parser, parser->m_encoding, &start, end, endPtr);
+
+ if (start) {
+ processor = prologProcessor;
+ prologProcessor(xmlParserP, start, end, endPtr, errorCodeP, errorP);
+ } else {
+ *errorCodeP = result;
+ *errorP = NULL;
+ }
}
-static enum XML_Error
-prologProcessor(XML_Parser parser,
- const char *s,
- const char *end,
- const char **nextPtr)
-{
- const char *next;
- int tok = XmlPrologTok(encoding, s, end, &next);
- return doProlog(parser, encoding, s, end, tok, next, nextPtr);
-}
-static enum XML_Error
-doProlog(XML_Parser parser,
- const ENCODING *enc,
- const char *s,
- const char *end,
- int tok,
- const char *next,
- const char **nextPtr)
-{
-#ifdef XML_DTD
+
+/* Forward declaration for recursive reference: */
+static void
+processInternalParamEntity(XML_Parser const parser,
+ ENTITY * const entity,
+ enum XML_Error * const errorCodeP,
+ const char ** const errorP);
+
+static void
+doProlog(XML_Parser const xmlParserP,
+ const ENCODING * const encArg,
+ const char * const startArg,
+ const char * const end,
+ int const tokArg,
+ const char * const nextArg,
+ const char ** const nextPtr,
+ enum XML_Error * const errorCodeP,
+ const char ** const errorP) {
+
+ Parser * const parser = (Parser *) xmlParserP;
+
+ int tok;
+ const char * next;
+ const ENCODING * enc;
+ const char * s;
+
static const XML_Char externalSubsetName[] = { '#' , '\0' };
-#endif /* XML_DTD */
const char **eventPP;
const char **eventEndPP;
- if (enc == encoding) {
+
+ *errorP = NULL;
+
+ tok = tokArg;
+ next = nextArg;
+ enc = encArg;
+ s = startArg;
+
+ if (enc == parser->m_encoding) {
eventPP = &eventPtr;
eventEndPP = &eventEndPtr;
}
@@ -2238,138 +3220,164 @@
*eventEndPP = next;
if (tok <= 0) {
if (nextPtr != 0 && tok != XML_TOK_INVALID) {
- *nextPtr = s;
- return XML_ERROR_NONE;
+ *nextPtr = s;
+ *errorCodeP = XML_ERROR_NONE;
+ return;
}
switch (tok) {
case XML_TOK_INVALID:
- *eventPP = next;
- return XML_ERROR_INVALID_TOKEN;
+ *eventPP = next;
+ *errorCodeP = XML_ERROR_INVALID_TOKEN;
+ return;
case XML_TOK_PARTIAL:
- return XML_ERROR_UNCLOSED_TOKEN;
+ *errorCodeP = XML_ERROR_UNCLOSED_TOKEN;
+ return;
case XML_TOK_PARTIAL_CHAR:
- return XML_ERROR_PARTIAL_CHAR;
+ *errorCodeP = XML_ERROR_PARTIAL_CHAR;
+ return;
case XML_TOK_NONE:
-#ifdef XML_DTD
- if (enc != encoding)
- return XML_ERROR_NONE;
- if (parentParser) {
- if (XmlTokenRole(&prologState, XML_TOK_NONE, end, end, enc)
- == XML_ROLE_ERROR)
- return XML_ERROR_SYNTAX;
- hadExternalDoctype = 0;
- return XML_ERROR_NONE;
- }
-#endif /* XML_DTD */
- return XML_ERROR_NO_ELEMENTS;
+ if (enc != parser->m_encoding)
+ *errorCodeP = XML_ERROR_NONE;
+ else {
+ if (parentParser) {
+ if (XmlTokenRole(&prologState, XML_TOK_NONE, end, end, enc)
+ == XML_ROLE_ERROR) {
+ *errorCodeP = XML_ERROR_SYNTAX;
+ } else {
+ *errorCodeP = XML_ERROR_NONE;
+ hadExternalDoctype = 0;
+ }
+ } else
+ *errorCodeP = XML_ERROR_NO_ELEMENTS;
+ }
+ return;
default:
- tok = -tok;
- next = end;
- break;
+ tok = -tok;
+ next = end;
+ break;
}
}
role = XmlTokenRole(&prologState, tok, s, next, enc);
switch (role) {
- case XML_ROLE_XML_DECL:
- {
- enum XML_Error result = processXmlDecl(parser, 0, s, next);
- if (result != XML_ERROR_NONE)
- return result;
- enc = encoding;
+ case XML_ROLE_XML_DECL: {
+ enum XML_Error result = processXmlDecl(xmlParserP, 0, s, next);
+ if (result != XML_ERROR_NONE) {
+ *errorCodeP = result;
+ return;
+ }
+ enc = parser->m_encoding;
}
break;
case XML_ROLE_DOCTYPE_NAME:
if (startDoctypeDeclHandler) {
- const XML_Char *name = poolStoreString(&tempPool, enc, s, next);
- if (!name)
- return XML_ERROR_NO_MEMORY;
- startDoctypeDeclHandler(handlerArg, name);
- poolClear(&tempPool);
- }
- break;
-#ifdef XML_DTD
- case XML_ROLE_TEXT_DECL:
- {
- enum XML_Error result = processXmlDecl(parser, 1, s, next);
- if (result != XML_ERROR_NONE)
- return result;
- enc = encoding;
+ const XML_Char *name = poolStoreString(&tempPool, enc, s, next);
+ if (!name) {
+ *errorCodeP = XML_ERROR_NO_MEMORY;
+ return;
+ }
+ startDoctypeDeclHandler(handlerArg, name);
+ poolClear(&tempPool);
+ }
+ break;
+ case XML_ROLE_TEXT_DECL: {
+ enum XML_Error result = processXmlDecl(xmlParserP, 1, s, next);
+ if (result != XML_ERROR_NONE) {
+ *errorCodeP = result;
+ return;
+ }
+ enc = parser->m_encoding;
}
break;
-#endif /* XML_DTD */
case XML_ROLE_DOCTYPE_PUBLIC_ID:
-#ifdef XML_DTD
declEntity = (ENTITY *)lookup(&dtd.paramEntities,
- externalSubsetName,
- sizeof(ENTITY));
- if (!declEntity)
- return XML_ERROR_NO_MEMORY;
-#endif /* XML_DTD */
+ externalSubsetName,
+ sizeof(ENTITY));
+ if (!declEntity) {
+ *errorCodeP = XML_ERROR_NO_MEMORY;
+ return;
+ }
/* fall through */
case XML_ROLE_ENTITY_PUBLIC_ID:
- if (!XmlIsPublicId(enc, s, next, eventPP))
- return XML_ERROR_SYNTAX;
+ if (!XmlIsPublicId(enc, s, next, eventPP)) {
+ *errorCodeP = XML_ERROR_SYNTAX;
+ return;
+ }
if (declEntity) {
- XML_Char *tem = poolStoreString(&dtd.pool,
- enc,
- s + enc->minBytesPerChar,
- next - enc->minBytesPerChar);
- if (!tem)
- return XML_ERROR_NO_MEMORY;
- normalizePublicId(tem);
- declEntity->publicId = tem;
- poolFinish(&dtd.pool);
+ XML_Char *tem = poolStoreString(&dtd.pool,
+ enc,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (!tem) {
+ *errorCodeP = XML_ERROR_NO_MEMORY;
+ return;
+ }
+ normalizePublicId(tem);
+ declEntity->publicId = tem;
+ poolFinish(&dtd.pool);
}
break;
case XML_ROLE_DOCTYPE_CLOSE:
if (dtd.complete && hadExternalDoctype) {
- dtd.complete = 0;
-#ifdef XML_DTD
- if (paramEntityParsing && externalEntityRefHandler) {
- ENTITY *entity = (ENTITY *)lookup(&dtd.paramEntities,
- externalSubsetName,
- 0);
- if (!externalEntityRefHandler(externalEntityRefHandlerArg,
- 0,
- entity->base,
- entity->systemId,
- entity->publicId))
- return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
- }
-#endif /* XML_DTD */
- if (!dtd.complete
- && !dtd.standalone
- && notStandaloneHandler
- && !notStandaloneHandler(handlerArg))
- return XML_ERROR_NOT_STANDALONE;
+ dtd.complete = 0;
+ if (paramEntityParsing && externalEntityRefHandler) {
+ ENTITY *entity = (ENTITY *)lookup(&dtd.paramEntities,
+ externalSubsetName,
+ 0);
+ if (!externalEntityRefHandler(externalEntityRefHandlerArg,
+ 0,
+ entity->base,
+ entity->systemId,
+ entity->publicId)) {
+ *errorCodeP = XML_ERROR_EXTERNAL_ENTITY_HANDLING;
+ return;
+ }
+ }
+ if (!dtd.complete
+ && !dtd.standalone
+ && notStandaloneHandler
+ && !notStandaloneHandler(handlerArg)) {
+ *errorCodeP = XML_ERROR_NOT_STANDALONE;
+ return;
+ }
}
if (endDoctypeDeclHandler)
- endDoctypeDeclHandler(handlerArg);
+ endDoctypeDeclHandler(handlerArg);
break;
- case XML_ROLE_INSTANCE_START:
+ case XML_ROLE_INSTANCE_START: {
processor = contentProcessor;
- return contentProcessor(parser, s, end, nextPtr);
+ contentProcessor(xmlParserP, s, end, nextPtr, errorCodeP, errorP);
+ return;
+ }
case XML_ROLE_ATTLIST_ELEMENT_NAME:
{
- const XML_Char *name = poolStoreString(&dtd.pool, enc, s, next);
- if (!name)
- return XML_ERROR_NO_MEMORY;
- declElementType = (ELEMENT_TYPE *)lookup(&dtd.elementTypes, name, sizeof(ELEMENT_TYPE));
- if (!declElementType)
- return XML_ERROR_NO_MEMORY;
- if (declElementType->name != name)
- poolDiscard(&dtd.pool);
- else {
- poolFinish(&dtd.pool);
- if (!setElementTypePrefix(parser, declElementType))
- return XML_ERROR_NO_MEMORY;
- }
- break;
+ const XML_Char *name = poolStoreString(&dtd.pool, enc, s, next);
+ if (!name) {
+ *errorCodeP = XML_ERROR_NO_MEMORY;
+ return;
+ }
+ declElementType = (ELEMENT_TYPE *)
+ lookup(&dtd.elementTypes, name, sizeof(ELEMENT_TYPE));
+ if (!declElementType) {
+ *errorCodeP = XML_ERROR_NO_MEMORY;
+ return;
+ }
+ if (declElementType->name != name)
+ poolDiscard(&dtd.pool);
+ else {
+ poolFinish(&dtd.pool);
+ if (!setElementTypePrefix(xmlParserP, declElementType)) {
+ *errorCodeP = XML_ERROR_NO_MEMORY;
+ return;
+ }
+ }
+ break;
}
case XML_ROLE_ATTRIBUTE_NAME:
- declAttributeId = getAttributeId(parser, enc, s, next);
- if (!declAttributeId)
- return XML_ERROR_NO_MEMORY;
+ declAttributeId = getAttributeId(xmlParserP, enc, s, next);
+ if (!declAttributeId) {
+ *errorCodeP = XML_ERROR_NO_MEMORY;
+ return;
+ }
declAttributeIsCdata = 0;
declAttributeIsId = 0;
break;
@@ -2382,323 +3390,366 @@
case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE:
case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE:
if (dtd.complete
- && !defineAttribute(declElementType, declAttributeId, declAttributeIsCdata,
- declAttributeIsId, 0))
- return XML_ERROR_NO_MEMORY;
+ && !defineAttribute(declElementType, declAttributeId,
+ declAttributeIsCdata,
+ declAttributeIsId, 0)) {
+ *errorCodeP = XML_ERROR_NO_MEMORY;
+ return;
+ }
break;
case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE:
case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
{
- const XML_Char *attVal;
- enum XML_Error result
- = storeAttributeValue(parser, enc, declAttributeIsCdata,
- s + enc->minBytesPerChar,
- next - enc->minBytesPerChar,
- &dtd.pool);
- if (result)
- return result;
- attVal = poolStart(&dtd.pool);
- poolFinish(&dtd.pool);
- if (dtd.complete
- /* ID attributes aren't allowed to have a default */
- && !defineAttribute(declElementType, declAttributeId, declAttributeIsCdata, 0, attVal))
- return XML_ERROR_NO_MEMORY;
- break;
+ const XML_Char *attVal;
+ enum XML_Error result
+ = storeAttributeValue(xmlParserP, enc, declAttributeIsCdata,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar,
+ &dtd.pool);
+ if (result) {
+ *errorCodeP = result;
+ return;
+ }
+ attVal = poolStart(&dtd.pool);
+ poolFinish(&dtd.pool);
+ if (dtd.complete
+ /* ID attributes aren't allowed to have a default */
+ && !defineAttribute(declElementType, declAttributeId,
+ declAttributeIsCdata, 0, attVal)) {
+ *errorCodeP = XML_ERROR_NO_MEMORY;
+ return;
+ }
+ break;
}
case XML_ROLE_ENTITY_VALUE:
{
- enum XML_Error result = storeEntityValue(parser, enc,
- s + enc->minBytesPerChar,
- next - enc->minBytesPerChar);
- if (declEntity) {
- declEntity->textPtr = poolStart(&dtd.pool);
- declEntity->textLen = poolLength(&dtd.pool);
- poolFinish(&dtd.pool);
- if (internalParsedEntityDeclHandler
- /* Check it's not a parameter entity */
- && ((ENTITY *)lookup(&dtd.generalEntities, declEntity->name, 0)
- == declEntity)) {
- *eventEndPP = s;
- internalParsedEntityDeclHandler(handlerArg,
- declEntity->name,
- declEntity->textPtr,
- declEntity->textLen);
- }
- }
- else
- poolDiscard(&dtd.pool);
- if (result != XML_ERROR_NONE)
- return result;
+ enum XML_Error result = storeEntityValue(xmlParserP, enc,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (declEntity) {
+ declEntity->textPtr = poolStart(&dtd.pool);
+ declEntity->textLen = poolLength(&dtd.pool);
+ poolFinish(&dtd.pool);
+ if (internalParsedEntityDeclHandler
+ /* Check it's not a parameter entity */
+ && ((ENTITY *)lookup(&dtd.generalEntities, declEntity->name, 0)
+ == declEntity)) {
+ *eventEndPP = s;
+ internalParsedEntityDeclHandler(handlerArg,
+ declEntity->name,
+ declEntity->textPtr,
+ declEntity->textLen);
+ }
+ }
+ else
+ poolDiscard(&dtd.pool);
+ if (result != XML_ERROR_NONE) {
+ *errorCodeP = result;
+ return;
+ }
}
break;
case XML_ROLE_DOCTYPE_SYSTEM_ID:
if (!dtd.standalone
-#ifdef XML_DTD
- && !paramEntityParsing
-#endif /* XML_DTD */
- && notStandaloneHandler
- && !notStandaloneHandler(handlerArg))
- return XML_ERROR_NOT_STANDALONE;
+ && !paramEntityParsing
+ && notStandaloneHandler
+ && !notStandaloneHandler(handlerArg)) {
+ *errorCodeP = XML_ERROR_NOT_STANDALONE;
+ return;
+ }
hadExternalDoctype = 1;
-#ifndef XML_DTD
- break;
-#else /* XML_DTD */
if (!declEntity) {
- declEntity = (ENTITY *)lookup(&dtd.paramEntities,
- externalSubsetName,
- sizeof(ENTITY));
- if (!declEntity)
- return XML_ERROR_NO_MEMORY;
+ declEntity = (ENTITY *)lookup(&dtd.paramEntities,
+ externalSubsetName,
+ sizeof(ENTITY));
+ if (!declEntity) {
+ *errorCodeP = XML_ERROR_NO_MEMORY;
+ return;
+ }
}
/* fall through */
-#endif /* XML_DTD */
case XML_ROLE_ENTITY_SYSTEM_ID:
if (declEntity) {
- declEntity->systemId = poolStoreString(&dtd.pool, enc,
- s + enc->minBytesPerChar,
- next - enc->minBytesPerChar);
- if (!declEntity->systemId)
- return XML_ERROR_NO_MEMORY;
- declEntity->base = curBase;
- poolFinish(&dtd.pool);
+ declEntity->systemId = poolStoreString(&dtd.pool, enc,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (!declEntity->systemId) {
+ *errorCodeP = XML_ERROR_NO_MEMORY;
+ return;
+ }
+ declEntity->base = curBase;
+ poolFinish(&dtd.pool);
}
break;
case XML_ROLE_ENTITY_NOTATION_NAME:
if (declEntity) {
- declEntity->notation = poolStoreString(&dtd.pool, enc, s, next);
- if (!declEntity->notation)
- return XML_ERROR_NO_MEMORY;
- poolFinish(&dtd.pool);
- if (unparsedEntityDeclHandler) {
- *eventEndPP = s;
- unparsedEntityDeclHandler(handlerArg,
- declEntity->name,
- declEntity->base,
- declEntity->systemId,
- declEntity->publicId,
- declEntity->notation);
- }
+ declEntity->notation = poolStoreString(&dtd.pool, enc, s, next);
+ if (!declEntity->notation) {
+ *errorCodeP = XML_ERROR_NO_MEMORY;
+ return;
+ }
+ poolFinish(&dtd.pool);
+ if (unparsedEntityDeclHandler) {
+ *eventEndPP = s;
+ unparsedEntityDeclHandler(handlerArg,
+ declEntity->name,
+ declEntity->base,
+ declEntity->systemId,
+ declEntity->publicId,
+ declEntity->notation);
+ }
}
break;
case XML_ROLE_EXTERNAL_GENERAL_ENTITY_NO_NOTATION:
if (declEntity && externalParsedEntityDeclHandler) {
- *eventEndPP = s;
- externalParsedEntityDeclHandler(handlerArg,
- declEntity->name,
- declEntity->base,
- declEntity->systemId,
- declEntity->publicId);
+ *eventEndPP = s;
+ externalParsedEntityDeclHandler(handlerArg,
+ declEntity->name,
+ declEntity->base,
+ declEntity->systemId,
+ declEntity->publicId);
}
break;
case XML_ROLE_GENERAL_ENTITY_NAME:
{
- const XML_Char *name;
- if (XmlPredefinedEntityName(enc, s, next)) {
- declEntity = 0;
- break;
- }
- name = poolStoreString(&dtd.pool, enc, s, next);
- if (!name)
- return XML_ERROR_NO_MEMORY;
- if (dtd.complete) {
- declEntity = (ENTITY *)lookup(&dtd.generalEntities, name, sizeof(ENTITY));
- if (!declEntity)
- return XML_ERROR_NO_MEMORY;
- if (declEntity->name != name) {
- poolDiscard(&dtd.pool);
- declEntity = 0;
- }
- else
- poolFinish(&dtd.pool);
- }
- else {
- poolDiscard(&dtd.pool);
- declEntity = 0;
- }
+ const XML_Char *name;
+ if (XmlPredefinedEntityName(enc, s, next)) {
+ declEntity = 0;
+ break;
+ }
+ name = poolStoreString(&dtd.pool, enc, s, next);
+ if (!name) {
+ *errorCodeP = XML_ERROR_NO_MEMORY;
+ return;
+ }
+ if (dtd.complete) {
+ declEntity = (ENTITY *)
+ lookup(&dtd.generalEntities, name, sizeof(ENTITY));
+ if (!declEntity) {
+ *errorCodeP = XML_ERROR_NO_MEMORY;
+ return;
+ }
+ if (declEntity->name != name) {
+ poolDiscard(&dtd.pool);
+ declEntity = 0;
+ }
+ else
+ poolFinish(&dtd.pool);
+ }
+ else {
+ poolDiscard(&dtd.pool);
+ declEntity = 0;
+ }
}
break;
case XML_ROLE_PARAM_ENTITY_NAME:
-#ifdef XML_DTD
if (dtd.complete) {
- const XML_Char *name = poolStoreString(&dtd.pool, enc, s, next);
- if (!name)
- return XML_ERROR_NO_MEMORY;
- declEntity = (ENTITY *)lookup(&dtd.paramEntities, name, sizeof(ENTITY));
- if (!declEntity)
- return XML_ERROR_NO_MEMORY;
- if (declEntity->name != name) {
- poolDiscard(&dtd.pool);
- declEntity = 0;
- }
- else
- poolFinish(&dtd.pool);
- }
-#else /* not XML_DTD */
- declEntity = 0;
-#endif /* not XML_DTD */
+ const XML_Char *name = poolStoreString(&dtd.pool, enc, s, next);
+ if (!name) {
+ *errorCodeP = XML_ERROR_NO_MEMORY;
+ return;
+ }
+ declEntity = (ENTITY *)
+ lookup(&dtd.paramEntities, name, sizeof(ENTITY));
+ if (!declEntity) {
+ *errorCodeP = XML_ERROR_NO_MEMORY;
+ return;
+ }
+ if (declEntity->name != name) {
+ poolDiscard(&dtd.pool);
+ declEntity = 0;
+ }
+ else
+ poolFinish(&dtd.pool);
+ }
break;
case XML_ROLE_NOTATION_NAME:
declNotationPublicId = 0;
declNotationName = 0;
if (notationDeclHandler) {
- declNotationName = poolStoreString(&tempPool, enc, s, next);
- if (!declNotationName)
- return XML_ERROR_NO_MEMORY;
- poolFinish(&tempPool);
+ declNotationName = poolStoreString(&tempPool, enc, s, next);
+ if (!declNotationName) {
+ *errorCodeP = XML_ERROR_NO_MEMORY;
+ return;
+ }
+ poolFinish(&tempPool);
}
break;
case XML_ROLE_NOTATION_PUBLIC_ID:
- if (!XmlIsPublicId(enc, s, next, eventPP))
- return XML_ERROR_SYNTAX;
+ if (!XmlIsPublicId(enc, s, next, eventPP)) {
+ *errorCodeP = XML_ERROR_SYNTAX;
+ return;
+ }
if (declNotationName) {
- XML_Char *tem = poolStoreString(&tempPool,
- enc,
- s + enc->minBytesPerChar,
- next - enc->minBytesPerChar);
- if (!tem)
- return XML_ERROR_NO_MEMORY;
- normalizePublicId(tem);
- declNotationPublicId = tem;
- poolFinish(&tempPool);
+ XML_Char *tem = poolStoreString(&tempPool,
+ enc,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (!tem) {
+ *errorCodeP = XML_ERROR_NO_MEMORY;
+ return;
+ }
+ normalizePublicId(tem);
+ declNotationPublicId = tem;
+ poolFinish(&tempPool);
}
break;
case XML_ROLE_NOTATION_SYSTEM_ID:
if (declNotationName && notationDeclHandler) {
- const XML_Char *systemId
- = poolStoreString(&tempPool, enc,
- s + enc->minBytesPerChar,
- next - enc->minBytesPerChar);
- if (!systemId)
- return XML_ERROR_NO_MEMORY;
- *eventEndPP = s;
- notationDeclHandler(handlerArg,
- declNotationName,
- curBase,
- systemId,
- declNotationPublicId);
+ const XML_Char *systemId
+ = poolStoreString(&tempPool, enc,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (!systemId) {
+ *errorCodeP = XML_ERROR_NO_MEMORY;
+ return;
+ }
+ *eventEndPP = s;
+ notationDeclHandler(handlerArg,
+ declNotationName,
+ curBase,
+ systemId,
+ declNotationPublicId);
}
poolClear(&tempPool);
break;
case XML_ROLE_NOTATION_NO_SYSTEM_ID:
if (declNotationPublicId && notationDeclHandler) {
- *eventEndPP = s;
- notationDeclHandler(handlerArg,
- declNotationName,
- curBase,
- 0,
- declNotationPublicId);
+ *eventEndPP = s;
+ notationDeclHandler(handlerArg,
+ declNotationName,
+ curBase,
+ 0,
+ declNotationPublicId);
}
poolClear(&tempPool);
break;
case XML_ROLE_ERROR:
switch (tok) {
case XML_TOK_PARAM_ENTITY_REF:
- return XML_ERROR_PARAM_ENTITY_REF;
+ *errorCodeP = XML_ERROR_PARAM_ENTITY_REF;
case XML_TOK_XML_DECL:
- return XML_ERROR_MISPLACED_XML_PI;
+ *errorCodeP = XML_ERROR_MISPLACED_XML_PI;
default:
- return XML_ERROR_SYNTAX;
+ *errorCodeP = XML_ERROR_SYNTAX;
}
-#ifdef XML_DTD
+ return;
case XML_ROLE_IGNORE_SECT:
{
- enum XML_Error result;
- if (defaultHandler)
- reportDefault(parser, enc, s, next);
- result = doIgnoreSection(parser, enc, &next, end, nextPtr);
- if (!next) {
- processor = ignoreSectionProcessor;
- return result;
- }
+ enum XML_Error result;
+ if (defaultHandler)
+ reportDefault(xmlParserP, enc, s, next);
+ result = doIgnoreSection(xmlParserP, enc, &next, end, nextPtr);
+ if (!next) {
+ processor = ignoreSectionProcessor;
+ *errorCodeP = result;
+ return;
+ }
}
break;
-#endif /* XML_DTD */
case XML_ROLE_GROUP_OPEN:
if (prologState.level >= groupSize) {
- if (groupSize)
- groupConnector = realloc(groupConnector, groupSize *= 2);
- else
- groupConnector = malloc(groupSize = 32);
- if (!groupConnector)
- return XML_ERROR_NO_MEMORY;
+ if (groupSize)
+ groupConnector = realloc(groupConnector, groupSize *= 2);
+ else
+ groupConnector = malloc(groupSize = 32);
+ if (!groupConnector) {
+ *errorCodeP = XML_ERROR_NO_MEMORY;
+ return;
+ }
}
groupConnector[prologState.level] = 0;
break;
case XML_ROLE_GROUP_SEQUENCE:
- if (groupConnector[prologState.level] == '|')
- return XML_ERROR_SYNTAX;
+ if (groupConnector[prologState.level] == '|') {
+ *errorCodeP = XML_ERROR_SYNTAX;
+ return;
+ }
groupConnector[prologState.level] = ',';
break;
case XML_ROLE_GROUP_CHOICE:
- if (groupConnector[prologState.level] == ',')
- return XML_ERROR_SYNTAX;
+ if (groupConnector[prologState.level] == ',') {
+ *errorCodeP = XML_ERROR_SYNTAX;
+ return;
+ }
groupConnector[prologState.level] = '|';
break;
case XML_ROLE_PARAM_ENTITY_REF:
-#ifdef XML_DTD
case XML_ROLE_INNER_PARAM_ENTITY_REF:
if (paramEntityParsing
- && (dtd.complete || role == XML_ROLE_INNER_PARAM_ENTITY_REF)) {
- const XML_Char *name;
- ENTITY *entity;
- name = poolStoreString(&dtd.pool, enc,
- s + enc->minBytesPerChar,
- next - enc->minBytesPerChar);
- if (!name)
- return XML_ERROR_NO_MEMORY;
- entity = (ENTITY *)lookup(&dtd.paramEntities, name, 0);
- poolDiscard(&dtd.pool);
- if (!entity) {
- /* FIXME what to do if !dtd.complete? */
- return XML_ERROR_UNDEFINED_ENTITY;
- }
- if (entity->open)
- return XML_ERROR_RECURSIVE_ENTITY_REF;
- if (entity->textPtr) {
- enum XML_Error result;
- result = processInternalParamEntity(parser, entity);
- if (result != XML_ERROR_NONE)
- return result;
- break;
- }
- if (role == XML_ROLE_INNER_PARAM_ENTITY_REF)
- return XML_ERROR_PARAM_ENTITY_REF;
- if (externalEntityRefHandler) {
- dtd.complete = 0;
- entity->open = 1;
- if (!externalEntityRefHandler(externalEntityRefHandlerArg,
- 0,
- entity->base,
- entity->systemId,
- entity->publicId)) {
- entity->open = 0;
- return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
- }
- entity->open = 0;
- if (dtd.complete)
- break;
- }
+ && (dtd.complete || role == XML_ROLE_INNER_PARAM_ENTITY_REF)) {
+ const XML_Char *name;
+ ENTITY *entity;
+ name = poolStoreString(&dtd.pool, enc,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (!name) {
+ *errorCodeP = XML_ERROR_NO_MEMORY;
+ return;
+ }
+ entity = (ENTITY *)lookup(&dtd.paramEntities, name, 0);
+ poolDiscard(&dtd.pool);
+ if (!entity) {
+ /* FIXME what to do if !dtd.complete? */
+ *errorCodeP = XML_ERROR_UNDEFINED_ENTITY;
+ return;
+ }
+ if (entity->open) {
+ *errorCodeP = XML_ERROR_RECURSIVE_ENTITY_REF;
+ return;
+ }
+ if (entity->textPtr) {
+ processInternalParamEntity(xmlParserP, entity, errorCodeP, errorP);
+ if (*errorCodeP != XML_ERROR_NONE)
+ return;
+ break;
+ }
+ if (role == XML_ROLE_INNER_PARAM_ENTITY_REF) {
+ *errorCodeP = XML_ERROR_PARAM_ENTITY_REF;
+ return;
+ }
+ if (externalEntityRefHandler) {
+ dtd.complete = 0;
+ entity->open = 1;
+ if (!externalEntityRefHandler(externalEntityRefHandlerArg,
+ 0,
+ entity->base,
+ entity->systemId,
+ entity->publicId)) {
+ entity->open = 0;
+ *errorCodeP = XML_ERROR_EXTERNAL_ENTITY_HANDLING;
+ return;
+ }
+ entity->open = 0;
+ if (dtd.complete)
+ break;
+ }
}
-#endif /* XML_DTD */
if (!dtd.standalone
- && notStandaloneHandler
- && !notStandaloneHandler(handlerArg))
- return XML_ERROR_NOT_STANDALONE;
+ && notStandaloneHandler
+ && !notStandaloneHandler(handlerArg)) {
+ *errorCodeP = XML_ERROR_NOT_STANDALONE;
+ return;
+ }
dtd.complete = 0;
if (defaultHandler)
- reportDefault(parser, enc, s, next);
+ reportDefault(xmlParserP, enc, s, next);
break;
case XML_ROLE_NONE:
switch (tok) {
case XML_TOK_PI:
- if (!reportProcessingInstruction(parser, enc, s, next))
- return XML_ERROR_NO_MEMORY;
- break;
+ if (!reportProcessingInstruction(xmlParserP, enc, s, next)) {
+ *errorCodeP = XML_ERROR_NO_MEMORY;
+ return;
+ }
+ break;
case XML_TOK_COMMENT:
- if (!reportComment(parser, enc, s, next))
- return XML_ERROR_NO_MEMORY;
- break;
+ if (!reportComment(xmlParserP, enc, s, next)) {
+ *errorCodeP = XML_ERROR_NO_MEMORY;
+ return;
+ }
+ break;
}
break;
}
@@ -2708,16 +3759,12 @@
case XML_TOK_COMMENT:
case XML_TOK_BOM:
case XML_TOK_XML_DECL:
-#ifdef XML_DTD
case XML_TOK_IGNORE_SECT:
-#endif /* XML_DTD */
case XML_TOK_PARAM_ENTITY_REF:
- break;
+ break;
default:
-#ifdef XML_DTD
- if (role != XML_ROLE_IGNORE_SECT)
-#endif /* XML_DTD */
- reportDefault(parser, enc, s, next);
+ if (role != XML_ROLE_IGNORE_SECT)
+ reportDefault(xmlParserP, enc, s, next);
}
}
s = next;
@@ -2726,1200 +3773,886 @@
/* not reached */
}
-static
-enum XML_Error epilogProcessor(XML_Parser parser,
- const char *s,
- const char *end,
- const char **nextPtr)
-{
- processor = epilogProcessor;
- eventPtr = s;
- for (;;) {
- const char *next;
- int tok = XmlPrologTok(encoding, s, end, &next);
- eventEndPtr = next;
- switch (tok) {
- case -XML_TOK_PROLOG_S:
- if (defaultHandler) {
- eventEndPtr = end;
- reportDefault(parser, encoding, s, end);
- }
- /* fall through */
- case XML_TOK_NONE:
- if (nextPtr)
- *nextPtr = end;
- return XML_ERROR_NONE;
- case XML_TOK_PROLOG_S:
- if (defaultHandler)
- reportDefault(parser, encoding, s, next);
- break;
- case XML_TOK_PI:
- if (!reportProcessingInstruction(parser, encoding, s, next))
- return XML_ERROR_NO_MEMORY;
- break;
- case XML_TOK_COMMENT:
- if (!reportComment(parser, encoding, s, next))
- return XML_ERROR_NO_MEMORY;
- break;
- case XML_TOK_INVALID:
- eventPtr = next;
- return XML_ERROR_INVALID_TOKEN;
- case XML_TOK_PARTIAL:
- if (nextPtr) {
- *nextPtr = s;
- return XML_ERROR_NONE;
- }
- return XML_ERROR_UNCLOSED_TOKEN;
- case XML_TOK_PARTIAL_CHAR:
- if (nextPtr) {
- *nextPtr = s;
- return XML_ERROR_NONE;
- }
- return XML_ERROR_PARTIAL_CHAR;
- default:
- return XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
+
+
+static Processor prologProcessor;
+
+static void
+prologProcessor(XML_Parser const xmlParserP,
+ const char * const s,
+ const char * const end,
+ const char ** const nextPtr,
+ enum XML_Error * const errorCodeP,
+ const char ** const errorP) {
+
+ Parser * const parser = (Parser *) xmlParserP;
+
+ const char * next;
+ int tok;
+
+ *errorP = NULL;
+
+ tok = XmlPrologTok(parser->m_encoding, s, end, &next);
+
+ doProlog(xmlParserP, parser->m_encoding, s, end, tok, next, nextPtr,
+ errorCodeP, errorP);
+}
+
+
+
+static Processor prologInitProcessor;
+
+static void
+prologInitProcessor(XML_Parser const parser,
+ const char * const s,
+ const char * const end,
+ const char ** const nextPtr,
+ enum XML_Error * const errorCodeP,
+ const char ** const errorP) {
+
+ enum XML_Error result;
+
+ *errorP = NULL;
+
+ result = initializeEncoding(parser);
+
+ if (result != XML_ERROR_NONE)
+ *errorCodeP = result;
+ else {
+ processor = prologProcessor;
+ prologProcessor(parser, s, end, nextPtr, errorCodeP, errorP);
}
- eventPtr = s = next;
- }
}
-#ifdef XML_DTD
-static enum XML_Error
-processInternalParamEntity(XML_Parser parser, ENTITY *entity)
-{
- const char *s, *end, *next;
- int tok;
- enum XML_Error result;
- OPEN_INTERNAL_ENTITY openEntity;
- entity->open = 1;
- openEntity.next = openInternalEntities;
- openInternalEntities = &openEntity;
- openEntity.entity = entity;
- openEntity.internalEventPtr = 0;
- openEntity.internalEventEndPtr = 0;
- s = (char *)entity->textPtr;
- end = (char *)(entity->textPtr + entity->textLen);
- tok = XmlPrologTok(internalEncoding, s, end, &next);
- result = doProlog(parser, internalEncoding, s, end, tok, next, 0);
- entity->open = 0;
- openInternalEntities = openEntity.next;
- return result;
+
+static void
+processInternalParamEntity(XML_Parser const parser,
+ ENTITY * const entity,
+ enum XML_Error * const errorCodeP,
+ const char ** const errorP) {
+
+ const char *s, *end, *next;
+ int tok;
+ OPEN_INTERNAL_ENTITY openEntity;
+
+ entity->open = 1;
+ openEntity.next = openInternalEntities;
+ openInternalEntities = &openEntity;
+ openEntity.entity = entity;
+ openEntity.internalEventPtr = 0;
+ openEntity.internalEventEndPtr = 0;
+ s = (char *)entity->textPtr;
+ end = (char *)(entity->textPtr + entity->textLen);
+ tok = XmlPrologTok(internalEncoding, s, end, &next);
+
+ doProlog(parser, internalEncoding, s, end, tok, next, 0,
+ errorCodeP, errorP);
+
+ entity->open = 0;
+ openInternalEntities = openEntity.next;
+}
+
+
+
+XML_Parser
+xmlrpc_XML_ParserCreate(const XML_Char * const encodingName) {
+
+ XML_Parser const xmlParserP = malloc(sizeof(Parser));
+ Parser * const parser = (Parser *)xmlParserP;
+ if (xmlParserP) {
+ processor = prologInitProcessor;
+ xmlrpc_XmlPrologStateInit(&prologState);
+ userData = 0;
+ handlerArg = 0;
+ startElementHandler = 0;
+ endElementHandler = 0;
+ characterDataHandler = 0;
+ processingInstructionHandler = 0;
+ commentHandler = 0;
+ startCdataSectionHandler = 0;
+ endCdataSectionHandler = 0;
+ defaultHandler = 0;
+ startDoctypeDeclHandler = 0;
+ endDoctypeDeclHandler = 0;
+ unparsedEntityDeclHandler = 0;
+ notationDeclHandler = 0;
+ externalParsedEntityDeclHandler = 0;
+ internalParsedEntityDeclHandler = 0;
+ startNamespaceDeclHandler = 0;
+ endNamespaceDeclHandler = 0;
+ notStandaloneHandler = 0;
+ externalEntityRefHandler = 0;
+ externalEntityRefHandlerArg = parser;
+ unknownEncodingHandler = 0;
+ buffer = 0;
+ bufferPtr = 0;
+ bufferEnd = 0;
+ parseEndByteIndex = 0;
+ parseEndPtr = 0;
+ bufferLim = 0;
+ declElementType = 0;
+ declAttributeId = 0;
+ declEntity = 0;
+ declNotationName = 0;
+ declNotationPublicId = 0;
+ memset(&position, 0, sizeof(POSITION));
+ errorCode = XML_ERROR_NONE;
+ errorString = NULL;
+ eventPtr = 0;
+ eventEndPtr = 0;
+ positionPtr = 0;
+ openInternalEntities = 0;
+ tagLevel = 0;
+ tagStack = 0;
+ freeTagList = 0;
+ freeBindingList = 0;
+ inheritedBindings = 0;
+ attsSize = INIT_ATTS_SIZE;
+ atts = malloc(attsSize * sizeof(ATTRIBUTE));
+ nSpecifiedAtts = 0;
+ dataBuf = malloc(INIT_DATA_BUF_SIZE * sizeof(XML_Char));
+ groupSize = 0;
+ groupConnector = 0;
+ hadExternalDoctype = 0;
+ unknownEncodingMem = 0;
+ unknownEncodingRelease = 0;
+ unknownEncodingData = 0;
+ unknownEncodingHandlerData = 0;
+ namespaceSeparator = '!';
+ parentParser = 0;
+ paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
+ ns = 0;
+ poolInit(&tempPool);
+ poolInit(&temp2Pool);
+ protocolEncodingName =
+ encodingName ? poolCopyString(&tempPool, encodingName) : 0;
+ curBase = 0;
+ if (!dtdInit(&dtd) || !atts || !dataBuf
+ || (encodingName && !protocolEncodingName)) {
+ xmlrpc_XML_ParserFree(xmlParserP);
+ return 0;
+ }
+ dataBufEnd = dataBuf + INIT_DATA_BUF_SIZE;
+ xmlrpc_XmlInitEncoding(&parser->m_initEncoding,
+ &parser->m_encoding,
+ 0);
+ internalEncoding = XmlGetInternalEncoding();
+ }
+ return xmlParserP;
+}
+
+XML_Parser
+xmlrpc_XML_ParserCreateNS(const XML_Char * const encodingName,
+ XML_Char const nsSep) {
+
+ static
+ const XML_Char implicitContext[] = {
+ XML_T('x'), XML_T('m'), XML_T('l'), XML_T('='),
+ XML_T('h'), XML_T('t'), XML_T('t'), XML_T('p'), XML_T(':'),
+ XML_T('/'), XML_T('/'), XML_T('w'), XML_T('w'), XML_T('w'),
+ XML_T('.'), XML_T('w'), XML_T('3'),
+ XML_T('.'), XML_T('o'), XML_T('r'), XML_T('g'),
+ XML_T('/'), XML_T('X'), XML_T('M'), XML_T('L'),
+ XML_T('/'), XML_T('1'), XML_T('9'), XML_T('9'), XML_T('8'),
+ XML_T('/'), XML_T('n'), XML_T('a'), XML_T('m'), XML_T('e'),
+ XML_T('s'), XML_T('p'), XML_T('a'), XML_T('c'), XML_T('e'),
+ XML_T('\0')
+ };
+
+ XML_Parser const xmlParserP = xmlrpc_XML_ParserCreate(encodingName);
+ Parser * const parser = (Parser *)xmlParserP;
+ XML_Parser retval;
+
+ if (xmlParserP) {
+ int succeeded;
+ xmlrpc_XmlInitEncodingNS(&initEncoding, &parser->m_encoding, 0);
+ ns = 1;
+ internalEncoding = XmlGetInternalEncodingNS();
+ namespaceSeparator = nsSep;
+
+ succeeded = setContext(xmlParserP, implicitContext);
+ if (succeeded)
+ retval = xmlParserP;
+ else {
+ xmlrpc_XML_ParserFree(xmlParserP);
+ retval = NULL;
+ }
+ } else
+ retval = NULL;
+
+ return retval;
}
-#endif /* XML_DTD */
-static
-enum XML_Error errorProcessor(XML_Parser parser,
- const char *s,
- const char *end,
- const char **nextPtr)
+
+int
+xmlrpc_XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName)
{
- return errorCode;
+ if (!encodingName)
+ protocolEncodingName = 0;
+ else {
+ protocolEncodingName = poolCopyString(&tempPool, encodingName);
+ if (!protocolEncodingName)
+ return 0;
+ }
+ return 1;
}
-static enum XML_Error
-storeAttributeValue(XML_Parser parser, const ENCODING *enc, int isCdata,
- const char *ptr, const char *end,
- STRING_POOL *pool)
+
+
+XML_Parser
+xmlrpc_XML_ExternalEntityParserCreate(XML_Parser oldParser,
+ const XML_Char *context,
+ const XML_Char *encodingName)
{
- enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr, end, pool);
- if (result)
- return result;
- if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
- poolChop(pool);
- if (!poolAppendChar(pool, XML_T('\0')))
- return XML_ERROR_NO_MEMORY;
- return XML_ERROR_NONE;
+ XML_Parser parser = oldParser;
+ DTD *oldDtd = &dtd;
+ XML_StartElementHandler oldStartElementHandler = startElementHandler;
+ XML_EndElementHandler oldEndElementHandler = endElementHandler;
+ XML_CharacterDataHandler oldCharacterDataHandler = characterDataHandler;
+ XML_ProcessingInstructionHandler oldProcessingInstructionHandler = processingInstructionHandler;
+ XML_CommentHandler oldCommentHandler = commentHandler;
+ XML_StartCdataSectionHandler oldStartCdataSectionHandler = startCdataSectionHandler;
+ XML_EndCdataSectionHandler oldEndCdataSectionHandler = endCdataSectionHandler;
+ XML_DefaultHandler oldDefaultHandler = defaultHandler;
+ XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler = unparsedEntityDeclHandler;
+ XML_NotationDeclHandler oldNotationDeclHandler = notationDeclHandler;
+ XML_ExternalParsedEntityDeclHandler oldExternalParsedEntityDeclHandler = externalParsedEntityDeclHandler;
+ XML_InternalParsedEntityDeclHandler oldInternalParsedEntityDeclHandler = internalParsedEntityDeclHandler;
+ XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler = startNamespaceDeclHandler;
+ XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler = endNamespaceDeclHandler;
+ XML_NotStandaloneHandler oldNotStandaloneHandler = notStandaloneHandler;
+ XML_ExternalEntityRefHandler oldExternalEntityRefHandler = externalEntityRefHandler;
+ XML_UnknownEncodingHandler oldUnknownEncodingHandler = unknownEncodingHandler;
+ void *oldUserData = userData;
+ void *oldHandlerArg = handlerArg;
+ int oldDefaultExpandInternalEntities = defaultExpandInternalEntities;
+ void *oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg;
+ int oldParamEntityParsing = paramEntityParsing;
+ parser = (ns
+ ? xmlrpc_XML_ParserCreateNS(encodingName, namespaceSeparator)
+ : xmlrpc_XML_ParserCreate(encodingName));
+ if (!parser)
+ return 0;
+ startElementHandler = oldStartElementHandler;
+ endElementHandler = oldEndElementHandler;
+ characterDataHandler = oldCharacterDataHandler;
+ processingInstructionHandler = oldProcessingInstructionHandler;
+ commentHandler = oldCommentHandler;
+ startCdataSectionHandler = oldStartCdataSectionHandler;
+ endCdataSectionHandler = oldEndCdataSectionHandler;
+ defaultHandler = oldDefaultHandler;
+ unparsedEntityDeclHandler = oldUnparsedEntityDeclHandler;
+ notationDeclHandler = oldNotationDeclHandler;
+ externalParsedEntityDeclHandler = oldExternalParsedEntityDeclHandler;
+ internalParsedEntityDeclHandler = oldInternalParsedEntityDeclHandler;
+ startNamespaceDeclHandler = oldStartNamespaceDeclHandler;
+ endNamespaceDeclHandler = oldEndNamespaceDeclHandler;
+ notStandaloneHandler = oldNotStandaloneHandler;
+ externalEntityRefHandler = oldExternalEntityRefHandler;
+ unknownEncodingHandler = oldUnknownEncodingHandler;
+ userData = oldUserData;
+ if (oldUserData == oldHandlerArg)
+ handlerArg = userData;
+ else
+ handlerArg = parser;
+ if (oldExternalEntityRefHandlerArg != oldParser)
+ externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg;
+ defaultExpandInternalEntities = oldDefaultExpandInternalEntities;
+ paramEntityParsing = oldParamEntityParsing;
+ if (context) {
+ if (!dtdCopy(&dtd, oldDtd) || !setContext(parser, context)) {
+ xmlrpc_XML_ParserFree(parser);
+ return 0;
+ }
+ processor = externalEntityInitProcessor;
+ }
+ else {
+ dtdSwap(&dtd, oldDtd);
+ parentParser = oldParser;
+ xmlrpc_XmlPrologStateInitExternalEntity(&prologState);
+ dtd.complete = 1;
+ hadExternalDoctype = 1;
+ }
+ return parser;
}
-static enum XML_Error
-appendAttributeValue(XML_Parser parser, const ENCODING *enc, int isCdata,
- const char *ptr, const char *end,
- STRING_POOL *pool)
+static
+void destroyBindings(BINDING *bindings)
{
for (;;) {
- const char *next;
- int tok = XmlAttributeValueTok(enc, ptr, end, &next);
- switch (tok) {
- case XML_TOK_NONE:
- return XML_ERROR_NONE;
- case XML_TOK_INVALID:
- if (enc == encoding)
- eventPtr = next;
- return XML_ERROR_INVALID_TOKEN;
- case XML_TOK_PARTIAL:
- if (enc == encoding)
- eventPtr = ptr;
- return XML_ERROR_INVALID_TOKEN;
- case XML_TOK_CHAR_REF:
- {
- XML_Char buf[XML_ENCODE_MAX];
- int i;
- int n = XmlCharRefNumber(enc, ptr);
- if (n < 0) {
- if (enc == encoding)
- eventPtr = ptr;
- return XML_ERROR_BAD_CHAR_REF;
- }
- if (!isCdata
- && n == 0x20 /* space */
- && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
- break;
- n = XmlEncode(n, (ICHAR *)buf);
- if (!n) {
- if (enc == encoding)
- eventPtr = ptr;
- return XML_ERROR_BAD_CHAR_REF;
- }
- for (i = 0; i < n; i++) {
- if (!poolAppendChar(pool, buf[i]))
- return XML_ERROR_NO_MEMORY;
- }
- }
- break;
- case XML_TOK_DATA_CHARS:
- if (!poolAppend(pool, enc, ptr, next))
- return XML_ERROR_NO_MEMORY;
- break;
- break;
- case XML_TOK_TRAILING_CR:
- next = ptr + enc->minBytesPerChar;
- /* fall through */
- case XML_TOK_ATTRIBUTE_VALUE_S:
- case XML_TOK_DATA_NEWLINE:
- if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
- break;
- if (!poolAppendChar(pool, 0x20))
- return XML_ERROR_NO_MEMORY;
- break;
- case XML_TOK_ENTITY_REF:
- {
- const XML_Char *name;
- ENTITY *entity;
- XML_Char ch = XmlPredefinedEntityName(enc,
- ptr + enc->minBytesPerChar,
- next - enc->minBytesPerChar);
- if (ch) {
- if (!poolAppendChar(pool, ch))
- return XML_ERROR_NO_MEMORY;
- break;
- }
- name = poolStoreString(&temp2Pool, enc,
- ptr + enc->minBytesPerChar,
- next - enc->minBytesPerChar);
- if (!name)
- return XML_ERROR_NO_MEMORY;
- entity = (ENTITY *)lookup(&dtd.generalEntities, name, 0);
- poolDiscard(&temp2Pool);
- if (!entity) {
- if (dtd.complete) {
- if (enc == encoding)
- eventPtr = ptr;
- return XML_ERROR_UNDEFINED_ENTITY;
- }
- }
- else if (entity->open) {
- if (enc == encoding)
- eventPtr = ptr;
- return XML_ERROR_RECURSIVE_ENTITY_REF;
- }
- else if (entity->notation) {
- if (enc == encoding)
- eventPtr = ptr;
- return XML_ERROR_BINARY_ENTITY_REF;
- }
- else if (!entity->textPtr) {
- if (enc == encoding)
- eventPtr = ptr;
- return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
- }
- else {
- enum XML_Error result;
- const XML_Char *textEnd = entity->textPtr + entity->textLen;
- entity->open = 1;
- result = appendAttributeValue(parser, internalEncoding, isCdata, (char *)entity->textPtr, (char *)textEnd, pool);
- entity->open = 0;
- if (result)
- return result;
- }
- }
+ BINDING *b = bindings;
+ if (!b)
break;
- default:
- abort();
- }
- ptr = next;
+ bindings = b->nextTagBinding;
+ free(b->uri);
+ free(b);
}
- /* not reached */
}
-static
-enum XML_Error storeEntityValue(XML_Parser parser,
- const ENCODING *enc,
- const char *entityTextPtr,
- const char *entityTextEnd)
+void
+xmlrpc_XML_ParserFree(XML_Parser parser)
{
- STRING_POOL *pool = &(dtd.pool);
for (;;) {
- const char *next;
- int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next);
- switch (tok) {
- case XML_TOK_PARAM_ENTITY_REF:
-#ifdef XML_DTD
- if (parentParser || enc != encoding) {
- enum XML_Error result;
- const XML_Char *name;
- ENTITY *entity;
- name = poolStoreString(&tempPool, enc,
- entityTextPtr + enc->minBytesPerChar,
- next - enc->minBytesPerChar);
- if (!name)
- return XML_ERROR_NO_MEMORY;
- entity = (ENTITY *)lookup(&dtd.paramEntities, name, 0);
- poolDiscard(&tempPool);
- if (!entity) {
- if (enc == encoding)
- eventPtr = entityTextPtr;
- return XML_ERROR_UNDEFINED_ENTITY;
- }
- if (entity->open) {
- if (enc == encoding)
- eventPtr = entityTextPtr;
- return XML_ERROR_RECURSIVE_ENTITY_REF;
- }
- if (entity->systemId) {
- if (enc == encoding)
- eventPtr = entityTextPtr;
- return XML_ERROR_PARAM_ENTITY_REF;
- }
- entity->open = 1;
- result = storeEntityValue(parser,
- internalEncoding,
- (char *)entity->textPtr,
- (char *)(entity->textPtr + entity->textLen));
- entity->open = 0;
- if (result)
- return result;
- break;
- }
-#endif /* XML_DTD */
- eventPtr = entityTextPtr;
- return XML_ERROR_SYNTAX;
- case XML_TOK_NONE:
- return XML_ERROR_NONE;
- case XML_TOK_ENTITY_REF:
- case XML_TOK_DATA_CHARS:
- if (!poolAppend(pool, enc, entityTextPtr, next))
- return XML_ERROR_NO_MEMORY;
- break;
- case XML_TOK_TRAILING_CR:
- next = entityTextPtr + enc->minBytesPerChar;
- /* fall through */
- case XML_TOK_DATA_NEWLINE:
- if (pool->end == pool->ptr && !poolGrow(pool))
- return XML_ERROR_NO_MEMORY;
- *(pool->ptr)++ = 0xA;
- break;
- case XML_TOK_CHAR_REF:
- {
- XML_Char buf[XML_ENCODE_MAX];
- int i;
- int n = XmlCharRefNumber(enc, entityTextPtr);
- if (n < 0) {
- if (enc == encoding)
- eventPtr = entityTextPtr;
- return XML_ERROR_BAD_CHAR_REF;
- }
- n = XmlEncode(n, (ICHAR *)buf);
- if (!n) {
- if (enc == encoding)
- eventPtr = entityTextPtr;
- return XML_ERROR_BAD_CHAR_REF;
- }
- for (i = 0; i < n; i++) {
- if (pool->end == pool->ptr && !poolGrow(pool))
- return XML_ERROR_NO_MEMORY;
- *(pool->ptr)++ = buf[i];
- }
- }
- break;
- case XML_TOK_PARTIAL:
- if (enc == encoding)
- eventPtr = entityTextPtr;
- return XML_ERROR_INVALID_TOKEN;
- case XML_TOK_INVALID:
- if (enc == encoding)
- eventPtr = next;
- return XML_ERROR_INVALID_TOKEN;
- default:
- abort();
+ TAG *p;
+ if (tagStack == 0) {
+ if (freeTagList == 0)
+ break;
+ tagStack = freeTagList;
+ freeTagList = 0;
}
- entityTextPtr = next;
+ p = tagStack;
+ tagStack = tagStack->parent;
+ free(p->buf);
+ destroyBindings(p->bindings);
+ free(p);
+ }
+ destroyBindings(freeBindingList);
+ destroyBindings(inheritedBindings);
+ poolDestroy(&tempPool);
+ poolDestroy(&temp2Pool);
+ if (parentParser) {
+ if (hadExternalDoctype)
+ dtd.complete = 0;
+ dtdSwap(&dtd, &((Parser *)parentParser)->m_dtd);
}
- /* not reached */
+ dtdDestroy(&dtd);
+ free((void *)atts);
+ free(groupConnector);
+ free(buffer);
+ free(dataBuf);
+ free(unknownEncodingMem);
+ if (unknownEncodingRelease)
+ unknownEncodingRelease(unknownEncodingData);
+ if (errorString)
+ xmlrpc_strfree(errorString);
+ free(parser);
}
-static void
-normalizeLines(XML_Char *s)
+void
+xmlrpc_XML_UseParserAsHandlerArg(XML_Parser parser)
{
- XML_Char *p;
- for (;; s++) {
- if (*s == XML_T('\0'))
- return;
- if (*s == 0xD)
- break;
- }
- p = s;
- do {
- if (*s == 0xD) {
- *p++ = 0xA;
- if (*++s == 0xA)
- s++;
- }
- else
- *p++ = *s++;
- } while (*s);
- *p = XML_T('\0');
+ handlerArg = parser;
}
-static int
-reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, const char *start, const char *end)
+void
+xmlrpc_XML_SetUserData(XML_Parser parser, void *p)
{
- const XML_Char *target;
- XML_Char *data;
- const char *tem;
- if (!processingInstructionHandler) {
- if (defaultHandler)
- reportDefault(parser, enc, start, end);
- return 1;
- }
- start += enc->minBytesPerChar * 2;
- tem = start + XmlNameLength(enc, start);
- target = poolStoreString(&tempPool, enc, start, tem);
- if (!target)
- return 0;
- poolFinish(&tempPool);
- data = poolStoreString(&tempPool, enc,
- XmlSkipS(enc, tem),
- end - enc->minBytesPerChar*2);
- if (!data)
- return 0;
- normalizeLines(data);
- processingInstructionHandler(handlerArg, target, data);
- poolClear(&tempPool);
- return 1;
+ if (handlerArg == userData)
+ handlerArg = userData = p;
+ else
+ userData = p;
}
-static int
-reportComment(XML_Parser parser, const ENCODING *enc, const char *start, const char *end)
+int
+xmlrpc_XML_SetBase(XML_Parser parser, const XML_Char *p)
{
- XML_Char *data;
- if (!commentHandler) {
- if (defaultHandler)
- reportDefault(parser, enc, start, end);
- return 1;
+ if (p) {
+ p = poolCopyString(&dtd.pool, p);
+ if (!p)
+ return 0;
+ curBase = p;
}
- data = poolStoreString(&tempPool,
- enc,
- start + enc->minBytesPerChar * 4,
- end - enc->minBytesPerChar * 3);
- if (!data)
- return 0;
- normalizeLines(data);
- commentHandler(handlerArg, data);
- poolClear(&tempPool);
+ else
+ curBase = 0;
return 1;
}
-static void
-reportDefault(XML_Parser parser, const ENCODING *enc, const char *s, const char *end)
+const XML_Char *
+xmlrpc_XML_GetBase(XML_Parser parser)
{
- if (MUST_CONVERT(enc, s)) {
- const char **eventPP;
- const char **eventEndPP;
- if (enc == encoding) {
- eventPP = &eventPtr;
- eventEndPP = &eventEndPtr;
- }
- else {
- eventPP = &(openInternalEntities->internalEventPtr);
- eventEndPP = &(openInternalEntities->internalEventEndPtr);
- }
- do {
- ICHAR *dataPtr = (ICHAR *)dataBuf;
- XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
- *eventEndPP = s;
- defaultHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf);
- *eventPP = s;
- } while (s != end);
- }
- else
- defaultHandler(handlerArg, (XML_Char *)s, (XML_Char *)end - (XML_Char *)s);
+ return curBase;
}
+int
+xmlrpc_XML_GetSpecifiedAttributeCount(XML_Parser parser)
+{
+ return nSpecifiedAtts;
+}
-static int
-defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, int isCdata, int isId, const XML_Char *value)
+int
+xmlrpc_XML_GetIdAttributeIndex(XML_Parser parser)
{
- DEFAULT_ATTRIBUTE *att;
- if (value || isId) {
- /* The handling of default attributes gets messed up if we have
- a default which duplicates a non-default. */
- int i;
- for (i = 0; i < type->nDefaultAtts; i++)
- if (attId == type->defaultAtts[i].id)
- return 1;
- if (isId && !type->idAtt && !attId->xmlns)
- type->idAtt = attId;
- }
- if (type->nDefaultAtts == type->allocDefaultAtts) {
- if (type->allocDefaultAtts == 0) {
- type->allocDefaultAtts = 8;
- type->defaultAtts = malloc(type->allocDefaultAtts*sizeof(DEFAULT_ATTRIBUTE));
- }
- else {
- type->allocDefaultAtts *= 2;
- type->defaultAtts = realloc(type->defaultAtts,
- type->allocDefaultAtts*sizeof(DEFAULT_ATTRIBUTE));
- }
- if (!type->defaultAtts)
- return 0;
- }
- att = type->defaultAtts + type->nDefaultAtts;
- att->id = attId;
- att->value = value;
- att->isCdata = isCdata;
- if (!isCdata)
- attId->maybeTokenized = 1;
- type->nDefaultAtts += 1;
- return 1;
+ return idAttIndex;
}
-static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType)
+void
+xmlrpc_XML_SetElementHandler(XML_Parser parser,
+ XML_StartElementHandler start,
+ XML_EndElementHandler end)
{
- const XML_Char *name;
- for (name = elementType->name; *name; name++) {
- if (*name == XML_T(':')) {
- PREFIX *prefix;
- const XML_Char *s;
- for (s = elementType->name; s != name; s++) {
- if (!poolAppendChar(&dtd.pool, *s))
- return 0;
- }
- if (!poolAppendChar(&dtd.pool, XML_T('\0')))
- return 0;
- prefix = (PREFIX *)lookup(&dtd.prefixes, poolStart(&dtd.pool), sizeof(PREFIX));
- if (!prefix)
- return 0;
- if (prefix->name == poolStart(&dtd.pool))
- poolFinish(&dtd.pool);
- else
- poolDiscard(&dtd.pool);
- elementType->prefix = prefix;
+ startElementHandler = start;
+ endElementHandler = end;
+}
- }
- }
- return 1;
+void
+xmlrpc_XML_SetCharacterDataHandler(XML_Parser parser,
+ XML_CharacterDataHandler handler)
+{
+ characterDataHandler = handler;
}
-static ATTRIBUTE_ID *
-getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, const char *end)
+void
+xmlrpc_XML_SetProcessingInstructionHandler(
+ XML_Parser parser,
+ XML_ProcessingInstructionHandler handler)
{
- ATTRIBUTE_ID *id;
- const XML_Char *name;
- if (!poolAppendChar(&dtd.pool, XML_T('\0')))
- return 0;
- name = poolStoreString(&dtd.pool, enc, start, end);
- if (!name)
- return 0;
- ++name;
- id = (ATTRIBUTE_ID *)lookup(&dtd.attributeIds, name, sizeof(ATTRIBUTE_ID));
- if (!id)
- return 0;
- if (id->name != name)
- poolDiscard(&dtd.pool);
- else {
- poolFinish(&dtd.pool);
- if (!ns)
- ;
- else if (name[0] == 'x'
- && name[1] == 'm'
- && name[2] == 'l'
- && name[3] == 'n'
- && name[4] == 's'
- && (name[5] == XML_T('\0') || name[5] == XML_T(':'))) {
- if (name[5] == '\0')
- id->prefix = &dtd.defaultPrefix;
- else
- id->prefix = (PREFIX *)lookup(&dtd.prefixes, name + 6, sizeof(PREFIX));
- id->xmlns = 1;
- }
- else {
- int i;
- for (i = 0; name[i]; i++) {
- if (name[i] == XML_T(':')) {
- int j;
- for (j = 0; j < i; j++) {
- if (!poolAppendChar(&dtd.pool, name[j]))
- return 0;
- }
- if (!poolAppendChar(&dtd.pool, XML_T('\0')))
- return 0;
- id->prefix = (PREFIX *)lookup(&dtd.prefixes, poolStart(&dtd.pool), sizeof(PREFIX));
- if (id->prefix->name == poolStart(&dtd.pool))
- poolFinish(&dtd.pool);
- else
- poolDiscard(&dtd.pool);
- break;
- }
- }
- }
- }
- return id;
+ processingInstructionHandler = handler;
}
-#define CONTEXT_SEP XML_T('\f')
+void
+xmlrpc_XML_SetCommentHandler(XML_Parser parser,
+ XML_CommentHandler handler)
+{
+ commentHandler = handler;
+}
-static
-const XML_Char *getContext(XML_Parser parser)
+void
+xmlrpc_XML_SetCdataSectionHandler(XML_Parser parser,
+ XML_StartCdataSectionHandler start,
+ XML_EndCdataSectionHandler end)
{
- HASH_TABLE_ITER iter;
- int needSep = 0;
+ startCdataSectionHandler = start;
+ endCdataSectionHandler = end;
+}
- if (dtd.defaultPrefix.binding) {
- int i;
- int len;
- if (!poolAppendChar(&tempPool, XML_T('=')))
- return 0;
- len = dtd.defaultPrefix.binding->uriLen;
- if (namespaceSeparator != XML_T('\0'))
- len--;
- for (i = 0; i < len; i++)
- if (!poolAppendChar(&tempPool, dtd.defaultPrefix.binding->uri[i]))
- return 0;
- needSep = 1;
- }
+void
+xmlrpc_XML_SetDefaultHandler(XML_Parser parser,
+ XML_DefaultHandler handler)
+{
+ defaultHandler = handler;
+ defaultExpandInternalEntities = 0;
+}
- hashTableIterInit(&iter, &(dtd.prefixes));
- for (;;) {
- int i;
- int len;
- const XML_Char *s;
- PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter);
- if (!prefix)
- break;
- if (!prefix->binding)
- continue;
- if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
- return 0;
- for (s = prefix->name; *s; s++)
- if (!poolAppendChar(&tempPool, *s))
- return 0;
- if (!poolAppendChar(&tempPool, XML_T('=')))
- return 0;
- len = prefix->binding->uriLen;
- if (namespaceSeparator != XML_T('\0'))
- len--;
- for (i = 0; i < len; i++)
- if (!poolAppendChar(&tempPool, prefix->binding->uri[i]))
- return 0;
- needSep = 1;
- }
+void
+xmlrpc_XML_SetDefaultHandlerExpand(XML_Parser parser,
+ XML_DefaultHandler handler)
+{
+ defaultHandler = handler;
+ defaultExpandInternalEntities = 1;
+}
+void
+xmlrpc_XML_SetDoctypeDeclHandler(XML_Parser parser,
+ XML_StartDoctypeDeclHandler start,
+ XML_EndDoctypeDeclHandler end)
+{
+ startDoctypeDeclHandler = start;
+ endDoctypeDeclHandler = end;
+}
- hashTableIterInit(&iter, &(dtd.generalEntities));
- for (;;) {
- const XML_Char *s;
- ENTITY *e = (ENTITY *)hashTableIterNext(&iter);
- if (!e)
- break;
- if (!e->open)
- continue;
- if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
- return 0;
- for (s = e->name; *s; s++)
- if (!poolAppendChar(&tempPool, *s))
- return 0;
- needSep = 1;
- }
+void
+xmlrpc_XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
+ XML_UnparsedEntityDeclHandler handler)
+{
+ unparsedEntityDeclHandler = handler;
+}
- if (!poolAppendChar(&tempPool, XML_T('\0')))
- return 0;
- return tempPool.start;
+void
+xmlrpc_XML_SetExternalParsedEntityDeclHandler(
+ XML_Parser parser,
+ XML_ExternalParsedEntityDeclHandler handler)
+{
+ externalParsedEntityDeclHandler = handler;
}
-static
-int setContext(XML_Parser parser, const XML_Char *context)
+void
+xmlrpc_XML_SetInternalParsedEntityDeclHandler(
+ XML_Parser parser,
+ XML_InternalParsedEntityDeclHandler handler)
{
- const XML_Char *s = context;
+ internalParsedEntityDeclHandler = handler;
+}
- while (*context != XML_T('\0')) {
- if (*s == CONTEXT_SEP || *s == XML_T('\0')) {
- ENTITY *e;
- if (!poolAppendChar(&tempPool, XML_T('\0')))
- return 0;
- e = (ENTITY *)lookup(&dtd.generalEntities, poolStart(&tempPool), 0);
- if (e)
- e->open = 1;
- if (*s != XML_T('\0'))
- s++;
- context = s;
- poolDiscard(&tempPool);
- }
- else if (*s == '=') {
- PREFIX *prefix;
- if (poolLength(&tempPool) == 0)
- prefix = &dtd.defaultPrefix;
- else {
- if (!poolAppendChar(&tempPool, XML_T('\0')))
- return 0;
- prefix = (PREFIX *)lookup(&dtd.prefixes, poolStart(&tempPool), sizeof(PREFIX));
- if (!prefix)
- return 0;
- if (prefix->name == poolStart(&tempPool)) {
- prefix->name = poolCopyString(&dtd.pool, prefix->name);
- if (!prefix->name)
- return 0;
- }
- poolDiscard(&tempPool);
- }
- for (context = s + 1; *context != CONTEXT_SEP && *context != XML_T('\0'); context++)
- if (!poolAppendChar(&tempPool, *context))
- return 0;
- if (!poolAppendChar(&tempPool, XML_T('\0')))
- return 0;
- if (!addBinding(parser, prefix, 0, poolStart(&tempPool), &inheritedBindings))
- return 0;
- poolDiscard(&tempPool);
- if (*context != XML_T('\0'))
- ++context;
- s = context;
- }
- else {
- if (!poolAppendChar(&tempPool, *s))
- return 0;
- s++;
- }
- }
- return 1;
+void
+xmlrpc_XML_SetNotationDeclHandler(XML_Parser parser,
+ XML_NotationDeclHandler handler)
+{
+ notationDeclHandler = handler;
}
+void
+xmlrpc_XML_SetNamespaceDeclHandler(XML_Parser parser,
+ XML_StartNamespaceDeclHandler start,
+ XML_EndNamespaceDeclHandler end)
+{
+ startNamespaceDeclHandler = start;
+ endNamespaceDeclHandler = end;
+}
-static
-void normalizePublicId(XML_Char *publicId)
+void
+xmlrpc_XML_SetNotStandaloneHandler(XML_Parser parser,
+ XML_NotStandaloneHandler handler)
{
- XML_Char *p = publicId;
- XML_Char *s;
- for (s = publicId; *s; s++) {
- switch (*s) {
- case 0x20:
- case 0xD:
- case 0xA:
- if (p != publicId && p[-1] != 0x20)
- *p++ = 0x20;
- break;
- default:
- *p++ = *s;
- }
- }
- if (p != publicId && p[-1] == 0x20)
- --p;
- *p = XML_T('\0');
+ notStandaloneHandler = handler;
}
-static int dtdInit(DTD *p)
+void
+xmlrpc_XML_SetExternalEntityRefHandler(XML_Parser parser,
+ XML_ExternalEntityRefHandler handler)
{
- poolInit(&(p->pool));
- hashTableInit(&(p->generalEntities));
- hashTableInit(&(p->elementTypes));
- hashTableInit(&(p->attributeIds));
- hashTableInit(&(p->prefixes));
- p->complete = 1;
- p->standalone = 0;
-#ifdef XML_DTD
- hashTableInit(&(p->paramEntities));
-#endif /* XML_DTD */
- p->defaultPrefix.name = 0;
- p->defaultPrefix.binding = 0;
- return 1;
+ externalEntityRefHandler = handler;
}
-#ifdef XML_DTD
+void
+xmlrpc_XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg)
+{
+ if (arg)
+ externalEntityRefHandlerArg = arg;
+ else
+ externalEntityRefHandlerArg = parser;
+}
-static void dtdSwap(DTD *p1, DTD *p2)
+void
+xmlrpc_XML_SetUnknownEncodingHandler(XML_Parser parser,
+ XML_UnknownEncodingHandler handler,
+ void *data)
{
- DTD tem;
- memcpy(&tem, p1, sizeof(DTD));
- memcpy(p1, p2, sizeof(DTD));
- memcpy(p2, &tem, sizeof(DTD));
+ unknownEncodingHandler = handler;
+ unknownEncodingHandlerData = data;
}
-#endif /* XML_DTD */
-static void dtdDestroy(DTD *p)
-{
- HASH_TABLE_ITER iter;
- hashTableIterInit(&iter, &(p->elementTypes));
- for (;;) {
- ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
- if (!e)
- break;
- if (e->allocDefaultAtts != 0)
- free(e->defaultAtts);
- }
- hashTableDestroy(&(p->generalEntities));
-#ifdef XML_DTD
- hashTableDestroy(&(p->paramEntities));
-#endif /* XML_DTD */
- hashTableDestroy(&(p->elementTypes));
- hashTableDestroy(&(p->attributeIds));
- hashTableDestroy(&(p->prefixes));
- poolDestroy(&(p->pool));
+
+int
+xmlrpc_XML_SetParamEntityParsing(
+ XML_Parser const parser ATTR_UNUSED,
+ enum XML_ParamEntityParsing const parsing) {
+
+ int retval;
+
+ paramEntityParsing = parsing;
+ retval = 1;
+
+ return retval;
}
-/* Do a deep copy of the DTD. Return 0 for out of memory; non-zero otherwise.
-The new DTD has already been initialized. */
-static int dtdCopy(DTD *newDtd, const DTD *oldDtd)
-{
- HASH_TABLE_ITER iter;
- /* Copy the prefix table. */
+static Processor errorProcessor;
- hashTableIterInit(&iter, &(oldDtd->prefixes));
- for (;;) {
- const XML_Char *name;
- const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter);
- if (!oldP)
- break;
- name = poolCopyString(&(newDtd->pool), oldP->name);
- if (!name)
- return 0;
- if (!lookup(&(newDtd->prefixes), name, sizeof(PREFIX)))
- return 0;
- }
+static void
+errorProcessor(XML_Parser const parser ATTR_UNUSED,
+ const char * const s ATTR_UNUSED,
+ const char * const end ATTR_UNUSED,
+ const char ** const nextPtr ATTR_UNUSED,
+ enum XML_Error * const errorCodeP,
+ const char ** const errorP) {
- hashTableIterInit(&iter, &(oldDtd->attributeIds));
+ *errorP = errorString;
+ *errorCodeP = errorCode;
+}
- /* Copy the attribute id table. */
- for (;;) {
- ATTRIBUTE_ID *newA;
- const XML_Char *name;
- const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter);
- if (!oldA)
- break;
- /* Remember to allocate the scratch byte before the name. */
- if (!poolAppendChar(&(newDtd->pool), XML_T('\0')))
- return 0;
- name = poolCopyString(&(newDtd->pool), oldA->name);
- if (!name)
- return 0;
- ++name;
- newA = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), name, sizeof(ATTRIBUTE_ID));
- if (!newA)
- return 0;
- newA->maybeTokenized = oldA->maybeTokenized;
- if (oldA->prefix) {
- newA->xmlns = oldA->xmlns;
- if (oldA->prefix == &oldDtd->defaultPrefix)
- newA->prefix = &newDtd->defaultPrefix;
- else
- newA->prefix = (PREFIX *)lookup(&(newDtd->prefixes), oldA->prefix->name, 0);
- }
- }
+static void
+parseFinalLen0(Parser * const parser,
+ int * const retvalP) {
- /* Copy the element type table. */
+ positionPtr = bufferPtr;
+ parseEndPtr = bufferEnd;
- hashTableIterInit(&iter, &(oldDtd->elementTypes));
+ processor(parser, bufferPtr, bufferEnd, 0, &errorCode, &errorString);
- for (;;) {
- int i;
- ELEMENT_TYPE *newE;
- const XML_Char *name;
- const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter);
- if (!oldE)
- break;
- name = poolCopyString(&(newDtd->pool), oldE->name);
- if (!name)
- return 0;
- newE = (ELEMENT_TYPE *)lookup(&(newDtd->elementTypes), name, sizeof(ELEMENT_TYPE));
- if (!newE)
- return 0;
- if (oldE->nDefaultAtts) {
- newE->defaultAtts = (DEFAULT_ATTRIBUTE *)malloc(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
- if (!newE->defaultAtts)
- return 0;
- }
- if (oldE->idAtt)
- newE->idAtt = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), oldE->idAtt->name, 0);
- newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts;
- if (oldE->prefix)
- newE->prefix = (PREFIX *)lookup(&(newDtd->prefixes), oldE->prefix->name, 0);
- for (i = 0; i < newE->nDefaultAtts; i++) {
- newE->defaultAtts[i].id = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
- newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;
- if (oldE->defaultAtts[i].value) {
- newE->defaultAtts[i].value = poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value);
- if (!newE->defaultAtts[i].value)
- return 0;
- }
- else
- newE->defaultAtts[i].value = 0;
+ if (errorCode == XML_ERROR_NONE)
+ *retvalP = 1;
+ else {
+ eventEndPtr = eventPtr;
+ processor = errorProcessor;
+ *retvalP = 0;
}
- }
+}
- /* Copy the entity tables. */
- if (!copyEntityTable(&(newDtd->generalEntities),
- &(newDtd->pool),
- &(oldDtd->generalEntities)))
- return 0;
-#ifdef XML_DTD
- if (!copyEntityTable(&(newDtd->paramEntities),
- &(newDtd->pool),
- &(oldDtd->paramEntities)))
- return 0;
-#endif /* XML_DTD */
- newDtd->complete = oldDtd->complete;
- newDtd->standalone = oldDtd->standalone;
- return 1;
+static void
+parseNoBuffer(Parser * const parser,
+ const char * const s,
+ int const len,
+ bool const isFinal,
+ int * const succeededP) {
+
+ parseEndByteIndex += len;
+ positionPtr = s;
+
+ if (isFinal) {
+ processor(parser, s, parseEndPtr = s + len, 0,
+ &errorCode, &errorString);
+ if (errorCode == XML_ERROR_NONE)
+ *succeededP = true;
+ else {
+ eventEndPtr = eventPtr;
+ processor = errorProcessor;
+ *succeededP = false;
+ }
+ } else {
+ const char * end;
+
+ parseEndPtr = s + len;
+ processor(parser, s, s + len, &end, &errorCode, &errorString);
+ if (errorCode != XML_ERROR_NONE) {
+ eventEndPtr = eventPtr;
+ processor = errorProcessor;
+ *succeededP = false;
+ } else {
+ int const nLeftOver = s + len - end;
+ XmlUpdatePosition(parser->m_encoding, positionPtr, end, &position);
+ if (nLeftOver > 0) {
+ if (buffer == 0 || nLeftOver > bufferLim - buffer) {
+ REALLOCARRAY(buffer, len * 2);
+ if (buffer)
+ bufferLim = buffer + len * 2;
+ }
+
+ if (buffer) {
+ memcpy(buffer, end, nLeftOver);
+ bufferPtr = buffer;
+ bufferEnd = buffer + nLeftOver;
+ *succeededP = true;
+ } else {
+ errorCode = XML_ERROR_NO_MEMORY;
+ eventPtr = eventEndPtr = 0;
+ processor = errorProcessor;
+ *succeededP = false;
+ }
+ } else
+ *succeededP = true;
+ }
+ }
}
-static int copyEntityTable(HASH_TABLE *newTable,
- STRING_POOL *newPool,
- const HASH_TABLE *oldTable)
-{
- HASH_TABLE_ITER iter;
- const XML_Char *cachedOldBase = 0;
- const XML_Char *cachedNewBase = 0;
- hashTableIterInit(&iter, oldTable);
- for (;;) {
- ENTITY *newE;
- const XML_Char *name;
- const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter);
- if (!oldE)
- break;
- name = poolCopyString(newPool, oldE->name);
- if (!name)
- return 0;
- newE = (ENTITY *)lookup(newTable, name, sizeof(ENTITY));
- if (!newE)
- return 0;
- if (oldE->systemId) {
- const XML_Char *tem = poolCopyString(newPool, oldE->systemId);
- if (!tem)
- return 0;
- newE->systemId = tem;
- if (oldE->base) {
- if (oldE->base == cachedOldBase)
- newE->base = cachedNewBase;
- else {
- cachedOldBase = oldE->base;
- tem = poolCopyString(newPool, cachedOldBase);
- if (!tem)
- return 0;
- cachedNewBase = newE->base = tem;
- }
- }
- }
+int
+xmlrpc_XML_Parse(XML_Parser const xmlParserP,
+ const char * const s,
+ int const len,
+ int const isFinal) {
+
+ Parser * const parser = (Parser *) xmlParserP;
+
+ int retval;
+
+ if (errorString) {
+ xmlrpc_strfree(errorString);
+ errorString = NULL;
+ }
+
+ if (len == 0) {
+ if (!isFinal)
+ retval = 1;
+ else
+ parseFinalLen0(parser, &retval);
+ } else if (bufferPtr == bufferEnd)
+ parseNoBuffer(parser, s, len, isFinal, &retval);
else {
- const XML_Char *tem = poolCopyStringN(newPool, oldE->textPtr, oldE->textLen);
- if (!tem)
- return 0;
- newE->textPtr = tem;
- newE->textLen = oldE->textLen;
- }
- if (oldE->notation) {
- const XML_Char *tem = poolCopyString(newPool, oldE->notation);
- if (!tem)
- return 0;
- newE->notation = tem;
+ memcpy(xmlrpc_XML_GetBuffer(parser, len), s, len);
+ retval = xmlrpc_XML_ParseBuffer(parser, len, isFinal);
}
- }
- return 1;
+ return retval;
}
-#define INIT_SIZE 64
-static
-int keyeq(KEY s1, KEY s2)
-{
- for (; *s1 == *s2; s1++, s2++)
- if (*s1 == 0)
- return 1;
- return 0;
-}
-static
-unsigned long hash(KEY s)
-{
- unsigned long h = 0;
- while (*s)
- h = (h << 5) + h + (unsigned char)*s++;
- return h;
+int
+xmlrpc_XML_ParseBuffer(XML_Parser const xmlParserP,
+ int const len,
+ int const isFinal) {
+
+ Parser * const parser = (Parser *)xmlParserP;
+
+ const char * const start = bufferPtr;
+
+ if (errorString) {
+ xmlrpc_strfree(errorString);
+ errorString = NULL;
+ }
+
+ positionPtr = start;
+ bufferEnd += len;
+ parseEndByteIndex += len;
+ processor(xmlParserP, start, parseEndPtr = bufferEnd,
+ isFinal ? (const char **)0 : &bufferPtr,
+ &errorCode, &errorString);
+ if (errorCode == XML_ERROR_NONE) {
+ if (!isFinal)
+ XmlUpdatePosition(parser->m_encoding, positionPtr, bufferPtr,
+ &position);
+ return 1;
+ } else {
+ eventEndPtr = eventPtr;
+ processor = errorProcessor;
+ return 0;
+ }
}
-static
-NAMED *lookup(HASH_TABLE *table, KEY name, size_t createSize)
+void *
+xmlrpc_XML_GetBuffer(XML_Parser parser, int len)
{
- size_t i;
- if (table->size == 0) {
- if (!createSize)
- return 0;
- table->v = calloc(INIT_SIZE, sizeof(NAMED *));
- if (!table->v)
- return 0;
- table->size = INIT_SIZE;
- table->usedLim = INIT_SIZE / 2;
- i = hash(name) & (table->size - 1);
- }
- else {
- unsigned long h = hash(name);
- for (i = h & (table->size - 1);
- table->v[i];
- i == 0 ? i = table->size - 1 : --i) {
- if (keyeq(name, table->v[i]->name))
- return table->v[i];
+ if (len > bufferLim - bufferEnd) {
+ /* FIXME avoid integer overflow */
+ int neededSize = len + (bufferEnd - bufferPtr);
+ if (neededSize <= bufferLim - buffer) {
+ memmove(buffer, bufferPtr, bufferEnd - bufferPtr);
+ bufferEnd = buffer + (bufferEnd - bufferPtr);
+ bufferPtr = buffer;
}
- if (!createSize)
- return 0;
- if (table->used == table->usedLim) {
- /* check for overflow */
- size_t newSize = table->size * 2;
- NAMED **newV = calloc(newSize, sizeof(NAMED *));
- if (!newV)
- return 0;
- for (i = 0; i < table->size; i++)
- if (table->v[i]) {
- size_t j;
- for (j = hash(table->v[i]->name) & (newSize - 1);
- newV[j];
- j == 0 ? j = newSize - 1 : --j)
- ;
- newV[j] = table->v[i];
- }
- free(table->v);
- table->v = newV;
- table->size = newSize;
- table->usedLim = newSize/2;
- for (i = h & (table->size - 1);
- table->v[i];
- i == 0 ? i = table->size - 1 : --i)
- ;
+ else {
+ char *newBuf;
+ int bufferSize = bufferLim - bufferPtr;
+ if (bufferSize == 0)
+ bufferSize = INIT_BUFFER_SIZE;
+ do {
+ bufferSize *= 2;
+ } while (bufferSize < neededSize);
+ newBuf = malloc(bufferSize);
+ if (newBuf == 0) {
+ errorCode = XML_ERROR_NO_MEMORY;
+ return 0;
+ }
+ bufferLim = newBuf + bufferSize;
+ if (bufferPtr) {
+ memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr);
+ free(buffer);
+ }
+ bufferEnd = newBuf + (bufferEnd - bufferPtr);
+ bufferPtr = buffer = newBuf;
}
}
- table->v[i] = calloc(1, createSize);
- if (!table->v[i])
- return 0;
- table->v[i]->name = name;
- (table->used)++;
- return table->v[i];
+ return bufferEnd;
}
-static
-void hashTableDestroy(HASH_TABLE *table)
-{
- size_t i;
- for (i = 0; i < table->size; i++) {
- NAMED *p = table->v[i];
- if (p)
- free(p);
- }
- if (table->v)
- free(table->v);
+
+
+enum XML_Error
+xmlrpc_XML_GetErrorCode(XML_Parser const parser) {
+
+ return errorCode;
}
-static
-void hashTableInit(HASH_TABLE *p)
-{
- p->size = 0;
- p->usedLim = 0;
- p->used = 0;
- p->v = 0;
+
+
+const char *
+xmlrpc_XML_GetErrorString(XML_Parser const parser) {
+
+ if (errorString)
+ return errorString;
+ else if (errorCode == XML_ERROR_NONE)
+ return NULL;
+ else
+ return xmlrpc_XML_ErrorString(errorCode);
}
-static
-void hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table)
+
+
+long
+xmlrpc_XML_GetCurrentByteIndex(XML_Parser parser)
{
- iter->p = table->v;
- iter->end = iter->p + table->size;
+ if (eventPtr)
+ return parseEndByteIndex - (parseEndPtr - eventPtr);
+ return -1;
}
-static
-NAMED *hashTableIterNext(HASH_TABLE_ITER *iter)
+int
+xmlrpc_XML_GetCurrentByteCount(XML_Parser parser)
{
- while (iter->p != iter->end) {
- NAMED *tem = *(iter->p)++;
- if (tem)
- return tem;
- }
+ if (eventEndPtr && eventPtr)
+ return eventEndPtr - eventPtr;
return 0;
}
-static
-void poolInit(STRING_POOL *pool)
-{
- pool->blocks = 0;
- pool->freeBlocks = 0;
- pool->start = 0;
- pool->ptr = 0;
- pool->end = 0;
-}
-static
-void poolClear(STRING_POOL *pool)
-{
- if (!pool->freeBlocks)
- pool->freeBlocks = pool->blocks;
- else {
- BLOCK *p = pool->blocks;
- while (p) {
- BLOCK *tem = p->next;
- p->next = pool->freeBlocks;
- pool->freeBlocks = p;
- p = tem;
+int
+xmlrpc_XML_GetCurrentLineNumber(XML_Parser const xmlParserP) {
+
+ Parser * const parser = (Parser *) xmlParserP;
+
+ if (eventPtr) {
+ XmlUpdatePosition(parser->m_encoding, positionPtr, eventPtr,
+ &position);
+ positionPtr = eventPtr;
}
- }
- pool->blocks = 0;
- pool->start = 0;
- pool->ptr = 0;
- pool->end = 0;
+ return position.lineNumber + 1;
}
-static
-void poolDestroy(STRING_POOL *pool)
-{
- BLOCK *p = pool->blocks;
- while (p) {
- BLOCK *tem = p->next;
- free(p);
- p = tem;
- }
- pool->blocks = 0;
- p = pool->freeBlocks;
- while (p) {
- BLOCK *tem = p->next;
- free(p);
- p = tem;
- }
- pool->freeBlocks = 0;
- pool->ptr = 0;
- pool->start = 0;
- pool->end = 0;
-}
-static
-XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc,
- const char *ptr, const char *end)
-{
- if (!pool->ptr && !poolGrow(pool))
- return 0;
- for (;;) {
- XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
- if (ptr == end)
- break;
- if (!poolGrow(pool))
- return 0;
- }
- return pool->start;
-}
-static const XML_Char *poolCopyString(STRING_POOL *pool, const XML_Char *s)
-{
- do {
- if (!poolAppendChar(pool, *s))
- return 0;
- } while (*s++);
- s = pool->start;
- poolFinish(pool);
- return s;
-}
+int
+xmlrpc_XML_GetCurrentColumnNumber(XML_Parser const xmlParserP) {
-static const XML_Char *poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n)
-{
- if (!pool->ptr && !poolGrow(pool))
- return 0;
- for (; n > 0; --n, s++) {
- if (!poolAppendChar(pool, *s))
- return 0;
+ Parser * const parser = (Parser *) xmlParserP;
- }
- s = pool->start;
- poolFinish(pool);
- return s;
+ if (eventPtr) {
+ XmlUpdatePosition(parser->m_encoding, positionPtr, eventPtr,
+ &position);
+ positionPtr = eventPtr;
+ }
+ return position.columnNumber;
}
-static
-XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc,
- const char *ptr, const char *end)
-{
- if (!poolAppend(pool, enc, ptr, end))
- return 0;
- if (pool->ptr == pool->end && !poolGrow(pool))
- return 0;
- *(pool->ptr)++ = 0;
- return pool->start;
-}
-static
-int poolGrow(STRING_POOL *pool)
-{
- if (pool->freeBlocks) {
- if (pool->start == 0) {
- pool->blocks = pool->freeBlocks;
- pool->freeBlocks = pool->freeBlocks->next;
- pool->blocks->next = 0;
- pool->start = pool->blocks->s;
- pool->end = pool->start + pool->blocks->size;
- pool->ptr = pool->start;
- return 1;
- }
- if (pool->end - pool->start < pool->freeBlocks->size) {
- BLOCK *tem = pool->freeBlocks->next;
- pool->freeBlocks->next = pool->blocks;
- pool->blocks = pool->freeBlocks;
- pool->freeBlocks = tem;
- memcpy(pool->blocks->s, pool->start, (pool->end - pool->start) * sizeof(XML_Char));
- pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
- pool->start = pool->blocks->s;
- pool->end = pool->start + pool->blocks->size;
- return 1;
+
+void
+xmlrpc_XML_DefaultCurrent(XML_Parser const xmlParserP) {
+
+ Parser * const parser = (Parser *) xmlParserP;
+
+ if (defaultHandler) {
+ if (openInternalEntities)
+ reportDefault(xmlParserP,
+ internalEncoding,
+ openInternalEntities->internalEventPtr,
+ openInternalEntities->internalEventEndPtr);
+ else
+ reportDefault(xmlParserP, parser->m_encoding,
+ eventPtr, eventEndPtr);
}
- }
- if (pool->blocks && pool->start == pool->blocks->s) {
- int blockSize = (pool->end - pool->start)*2;
- pool->blocks = realloc(pool->blocks, offsetof(BLOCK, s) + blockSize * sizeof(XML_Char));
- if (!pool->blocks)
- return 0;
- pool->blocks->size = blockSize;
- pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
- pool->start = pool->blocks->s;
- pool->end = pool->start + blockSize;
- }
- else {
- BLOCK *tem;
- int blockSize = pool->end - pool->start;
- if (blockSize < INIT_BLOCK_SIZE)
- blockSize = INIT_BLOCK_SIZE;
+}
+
+const XML_LChar *
+xmlrpc_XML_ErrorString(int const code) {
+
+ static const XML_LChar * const message[] = {
+ /* NONE */ NULL,
+ /* NO_MEMORY */ XML_T("out of memory"),
+ /* SYNTAX */ XML_T("syntax error"),
+ /* NO_ELEMENTS */ XML_T("no element found"),
+ /* INVALID_TOKEN */ XML_T("not well-formed"),
+ /* UNCLOSED_TOKEN */ XML_T("unclosed token"),
+ /* PARTIAL_CHAR */ XML_T("unclosed token"),
+ /* TAG_MISMATCH */ XML_T("mismatched tag"),
+ /* DUPLICATE_ATTRIBUTE */ XML_T("duplicate attribute"),
+ /* JUNK_AFTER_DOC_ELEMENT */ XML_T("junk after document element"),
+ /* PARAM_ENTITY_REF */
+ XML_T("illegal parameter entity reference"),
+ /* UNDEFINED_ENTITY */ XML_T("undefined entity"),
+ /* RECURSIVE_ENTITY_REF */ XML_T("recursive entity reference"),
+ /* ASYNC_ENTITY */ XML_T("asynchronous entity"),
+ /* BAD_CHAR_REF */
+ XML_T("reference to invalid character number"),
+ /* BINARY_ENTITY_REF */ XML_T("reference to binary entity"),
+ /* ATTRIBUTE_EXTERNAL_ENTITY_REF */
+ XML_T("reference to external entity in attribute"),
+ /* MISPLACED_XML_PI */
+ XML_T("xml processing instruction not at start "
+ "of external entity"),
+ /* UNKNOWN_ENCODING */ XML_T("unknown encoding"),
+ /* INCORRECT_ENCODING */
+ XML_T("encoding specified in XML declaration is incorrect"),
+ /* UNCLOSED_CDATA_SECTION */ XML_T("unclosed CDATA section"),
+ /* EXTERNAL_ENTITY_HANDLING */
+ XML_T("error in processing external entity reference"),
+ /* NOT_STANDALONE */ XML_T("document is not standalone")
+ };
+
+ const XML_LChar * retval;
+
+ if (code > 0 && (unsigned)code < ARRAY_SIZE(message))
+ retval = message[code];
else
- blockSize *= 2;
- tem = malloc(offsetof(BLOCK, s) + blockSize * sizeof(XML_Char));
- if (!tem)
- return 0;
- tem->size = blockSize;
- tem->next = pool->blocks;
- pool->blocks = tem;
- if (pool->ptr != pool->start)
- memcpy(tem->s, pool->start, (pool->ptr - pool->start) * sizeof(XML_Char));
- pool->ptr = tem->s + (pool->ptr - pool->start);
- pool->start = tem->s;
- pool->end = tem->s + blockSize;
- }
- return 1;
+ retval = NULL;
+
+ return retval;
}
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmlparse/xmlparse.h
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmlparse/xmlparse.h (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmlparse/xmlparse.h Fri May 23 16:56:24 2008
@@ -1,10 +1,10 @@
/*
-Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
-See the file copying.txt for copying permission.
+ Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
+ See the file copying.txt for copying permission.
*/
-#ifndef XmlParse_INCLUDED
-#define XmlParse_INCLUDED 1
+#ifndef XMLPARSE_H_INCLUDED
+#define XMLPARSE_H_INCLUDED
#ifdef __cplusplus
extern "C" {
@@ -19,7 +19,8 @@
#ifdef XML_UNICODE_WCHAR_T
/* XML_UNICODE_WCHAR_T will work only if sizeof(wchar_t) == 2 and wchar_t
-uses Unicode. */
+ uses Unicode.
+*/
/* Information is UTF-16 encoded as wchar_ts */
#ifndef XML_UNICODE
@@ -53,7 +54,7 @@
protocol or null if there is none specified. */
XML_Parser XMLPARSEAPI
-XML_ParserCreate(const XML_Char *encoding);
+xmlrpc_XML_ParserCreate(const XML_Char * const encoding);
/* Constructs a new parser and namespace processor. Element type names
and attribute names that belong to a namespace will be expanded;
@@ -66,28 +67,29 @@
passed through without expansion. */
XML_Parser XMLPARSEAPI
-XML_ParserCreateNS(const XML_Char *encoding, XML_Char namespaceSeparator);
+xmlrpc_XML_ParserCreateNS(const XML_Char * const encoding,
+ XML_Char const namespaceSeparator);
/* atts is array of name/value pairs, terminated by 0;
names and values are 0 terminated. */
typedef void (*XML_StartElementHandler)(void *userData,
- const XML_Char *name,
- const XML_Char **atts);
+ const XML_Char *name,
+ const XML_Char **atts);
typedef void (*XML_EndElementHandler)(void *userData,
- const XML_Char *name);
+ const XML_Char *name);
/* s is not 0 terminated. */
typedef void (*XML_CharacterDataHandler)(void *userData,
- const XML_Char *s,
- int len);
+ const XML_Char *s,
+ int len);
/* target and data are 0 terminated */
typedef void (*XML_ProcessingInstructionHandler)(void *userData,
- const XML_Char *target,
- const XML_Char *data);
+ const XML_Char *target,
+ const XML_Char *data);
/* data is 0 terminated */
typedef void (*XML_CommentHandler)(void *userData, const XML_Char *data);
@@ -109,13 +111,13 @@
multiple calls. */
typedef void (*XML_DefaultHandler)(void *userData,
- const XML_Char *s,
- int len);
+ const XML_Char *s,
+ int len);
/* This is called for the start of the DOCTYPE declaration when the
name of the DOCTYPE is encountered. */
typedef void (*XML_StartDoctypeDeclHandler)(void *userData,
- const XML_Char *doctypeName);
+ const XML_Char *doctypeName);
/* This is called for the start of the DOCTYPE declaration when the
closing > is encountered, but after processing any external subset. */
@@ -127,32 +129,32 @@
The other arguments may be. */
typedef void (*XML_UnparsedEntityDeclHandler)(void *userData,
- const XML_Char *entityName,
- const XML_Char *base,
- const XML_Char *systemId,
- const XML_Char *publicId,
- const XML_Char *notationName);
+ const XML_Char *entityName,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId,
+ const XML_Char *notationName);
/* This is called for a declaration of notation.
The base argument is whatever was set by XML_SetBase.
The notationName will never be null. The other arguments can be. */
typedef void (*XML_NotationDeclHandler)(void *userData,
- const XML_Char *notationName,
- const XML_Char *base,
- const XML_Char *systemId,
- const XML_Char *publicId);
+ const XML_Char *notationName,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId);
typedef void (*XML_ExternalParsedEntityDeclHandler)(void *userData,
- const XML_Char *entityName,
- const XML_Char *base,
- const XML_Char *systemId,
- const XML_Char *publicId);
+ const XML_Char *entityName,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId);
typedef void (*XML_InternalParsedEntityDeclHandler)(void *userData,
- const XML_Char *entityName,
- const XML_Char *replacementText,
- int replacementTextLength);
+ const XML_Char *entityName,
+ const XML_Char *replacementText,
+ int replacementTextLength);
/* When namespace processing is enabled, these are called once for
each namespace declaration. The call to the start and end element
@@ -161,11 +163,11 @@
For an xmlns="" attribute, uri will be null. */
typedef void (*XML_StartNamespaceDeclHandler)(void *userData,
- const XML_Char *prefix,
- const XML_Char *uri);
+ const XML_Char *prefix,
+ const XML_Char *uri);
typedef void (*XML_EndNamespaceDeclHandler)(void *userData,
- const XML_Char *prefix);
+ const XML_Char *prefix);
/* This is called if the document is not standalone (it has an
external subset or a reference to a parameter entity, but does not
@@ -200,10 +202,10 @@
Note that unlike other handlers the first argument is the parser, not userData. */
typedef int (*XML_ExternalEntityRefHandler)(XML_Parser parser,
- const XML_Char *context,
- const XML_Char *base,
- const XML_Char *systemId,
- const XML_Char *publicId);
+ const XML_Char *context,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId);
/* This structure is filled in by the XML_UnknownEncodingHandler
to provide information to the parser about encodings that are unknown
@@ -265,97 +267,105 @@
then the parser will return an XML_UNKNOWN_ENCODING error. */
typedef int (*XML_UnknownEncodingHandler)(void *encodingHandlerData,
- const XML_Char *name,
- XML_Encoding *info);
+ const XML_Char *name,
+ XML_Encoding *info);
void XMLPARSEAPI
-XML_SetElementHandler(XML_Parser parser,
- XML_StartElementHandler start,
- XML_EndElementHandler end);
+xmlrpc_XML_SetElementHandler(XML_Parser parser,
+ XML_StartElementHandler start,
+ XML_EndElementHandler end);
void XMLPARSEAPI
-XML_SetCharacterDataHandler(XML_Parser parser,
- XML_CharacterDataHandler handler);
+xmlrpc_XML_SetCharacterDataHandler(XML_Parser parser,
+ XML_CharacterDataHandler handler);
void XMLPARSEAPI
-XML_SetProcessingInstructionHandler(XML_Parser parser,
- XML_ProcessingInstructionHandler handler);
+xmlrpc_XML_SetProcessingInstructionHandler(
+ XML_Parser parser,
+ XML_ProcessingInstructionHandler handler);
void XMLPARSEAPI
-XML_SetCommentHandler(XML_Parser parser,
- XML_CommentHandler handler);
+xmlrpc_XML_SetCommentHandler(XML_Parser parser,
+ XML_CommentHandler handler);
void XMLPARSEAPI
-XML_SetCdataSectionHandler(XML_Parser parser,
- XML_StartCdataSectionHandler start,
- XML_EndCdataSectionHandler end);
+xmlrpc_XML_SetCdataSectionHandler(XML_Parser parser,
+ XML_StartCdataSectionHandler start,
+ XML_EndCdataSectionHandler end);
-/* This sets the default handler and also inhibits expansion of internal entities.
-The entity reference will be passed to the default handler. */
+/* This sets the default handler and also inhibits expansion of
+ internal entities. The entity reference will be passed to the default
+ handler.
+*/
void XMLPARSEAPI
-XML_SetDefaultHandler(XML_Parser parser,
- XML_DefaultHandler handler);
+xmlrpc_XML_SetDefaultHandler(XML_Parser parser,
+ XML_DefaultHandler handler);
/* This sets the default handler but does not inhibit expansion of internal entities.
The entity reference will not be passed to the default handler. */
void XMLPARSEAPI
-XML_SetDefaultHandlerExpand(XML_Parser parser,
- XML_DefaultHandler handler);
+xmlrpc_XML_SetDefaultHandlerExpand(XML_Parser parser,
+ XML_DefaultHandler handler);
void XMLPARSEAPI
-XML_SetDoctypeDeclHandler(XML_Parser parser,
- XML_StartDoctypeDeclHandler start,
- XML_EndDoctypeDeclHandler end);
+xmlrpc_XML_SetDoctypeDeclHandler(XML_Parser parser,
+ XML_StartDoctypeDeclHandler start,
+ XML_EndDoctypeDeclHandler end);
void XMLPARSEAPI
-XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
- XML_UnparsedEntityDeclHandler handler);
+xmlrpc_XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
+ XML_UnparsedEntityDeclHandler handler);
void XMLPARSEAPI
-XML_SetNotationDeclHandler(XML_Parser parser,
- XML_NotationDeclHandler handler);
+xmlrpc_XML_SetNotationDeclHandler(XML_Parser parser,
+ XML_NotationDeclHandler handler);
void XMLPARSEAPI
-XML_SetExternalParsedEntityDeclHandler(XML_Parser parser,
- XML_ExternalParsedEntityDeclHandler handler);
+xmlrpc_XML_SetExternalParsedEntityDeclHandler(
+ XML_Parser parser,
+ XML_ExternalParsedEntityDeclHandler handler);
void XMLPARSEAPI
-XML_SetInternalParsedEntityDeclHandler(XML_Parser parser,
- XML_InternalParsedEntityDeclHandler handler);
+xmlrpc_XML_SetInternalParsedEntityDeclHandler(
+ XML_Parser parser,
+ XML_InternalParsedEntityDeclHandler handler);
void XMLPARSEAPI
-XML_SetNamespaceDeclHandler(XML_Parser parser,
- XML_StartNamespaceDeclHandler start,
- XML_EndNamespaceDeclHandler end);
+xmlrpc_XML_SetNamespaceDeclHandler(XML_Parser parser,
+ XML_StartNamespaceDeclHandler start,
+ XML_EndNamespaceDeclHandler end);
void XMLPARSEAPI
-XML_SetNotStandaloneHandler(XML_Parser parser,
- XML_NotStandaloneHandler handler);
+xmlrpc_XML_SetNotStandaloneHandler(XML_Parser parser,
+ XML_NotStandaloneHandler handler);
void XMLPARSEAPI
-XML_SetExternalEntityRefHandler(XML_Parser parser,
- XML_ExternalEntityRefHandler handler);
+xmlrpc_XML_SetExternalEntityRefHandler(XML_Parser parser,
+ XML_ExternalEntityRefHandler handler);
-/* If a non-null value for arg is specified here, then it will be passed
-as the first argument to the external entity ref handler instead
-of the parser object. */
+/* If a non-null value for arg is specified here, then it will be
+ passed as the first argument to the external entity ref handler
+ instead of the parser object.
+*/
void XMLPARSEAPI
-XML_SetExternalEntityRefHandlerArg(XML_Parser, void *arg);
+xmlrpc_XML_SetExternalEntityRefHandlerArg(XML_Parser, void *arg);
void XMLPARSEAPI
-XML_SetUnknownEncodingHandler(XML_Parser parser,
- XML_UnknownEncodingHandler handler,
- void *encodingHandlerData);
+xmlrpc_XML_SetUnknownEncodingHandler(XML_Parser parser,
+ XML_UnknownEncodingHandler handler,
+ void *encodingHandlerData);
/* This can be called within a handler for a start element, end element,
-processing instruction or character data. It causes the corresponding
-markup to be passed to the default handler. */
-void XMLPARSEAPI XML_DefaultCurrent(XML_Parser parser);
+ processing instruction or character data. It causes the corresponding
+ markup to be passed to the default handler.
+*/
+void XMLPARSEAPI
+xmlrpc_XML_DefaultCurrent(XML_Parser parser);
/* This value is passed as the userData argument to callbacks. */
void XMLPARSEAPI
-XML_SetUserData(XML_Parser parser, void *userData);
+xmlrpc_XML_SetUserData(XML_Parser parser, void *userData);
/* Returns the last value set by XML_SetUserData or null. */
#define XML_GetUserData(parser) (*(void **)(parser))
@@ -365,71 +375,78 @@
or XML_ParseBuffer. */
int XMLPARSEAPI
-XML_SetEncoding(XML_Parser parser, const XML_Char *encoding);
+xmlrpc_XML_SetEncoding(XML_Parser parser, const XML_Char *encoding);
/* If this function is called, then the parser will be passed
-as the first argument to callbacks instead of userData.
-The userData will still be accessible using XML_GetUserData. */
-
+ as the first argument to callbacks instead of userData.
+ The userData will still be accessible using XML_GetUserData.
+*/
void XMLPARSEAPI
-XML_UseParserAsHandlerArg(XML_Parser parser);
-
-/* Sets the base to be used for resolving relative URIs in system identifiers in
-declarations. Resolving relative identifiers is left to the application:
-this value will be passed through as the base argument to the
-XML_ExternalEntityRefHandler, XML_NotationDeclHandler
-and XML_UnparsedEntityDeclHandler. The base argument will be copied.
-Returns zero if out of memory, non-zero otherwise. */
+xmlrpc_XML_UseParserAsHandlerArg(XML_Parser parser);
+/* Sets the base to be used for resolving relative URIs in system
+ identifiers in declarations. Resolving relative identifiers is left
+ to the application: this value will be passed through as the base
+ argument to the XML_ExternalEntityRefHandler, XML_NotationDeclHandler
+ and XML_UnparsedEntityDeclHandler. The base argument will be copied.
+ Returns zero if out of memory, non-zero otherwise.
+*/
int XMLPARSEAPI
-XML_SetBase(XML_Parser parser, const XML_Char *base);
+xmlrpc_XML_SetBase(XML_Parser parser, const XML_Char *base);
const XML_Char XMLPARSEAPI *
-XML_GetBase(XML_Parser parser);
+xmlrpc_XML_GetBase(XML_Parser parser);
/* Returns the number of the attribute/value pairs passed in last call
-to the XML_StartElementHandler that were specified in the start-tag
-rather than defaulted. Each attribute/value pair counts as 2; thus
-this correspondds to an index into the atts array passed to the
-XML_StartElementHandler. */
-
-int XMLPARSEAPI XML_GetSpecifiedAttributeCount(XML_Parser parser);
+ to the XML_StartElementHandler that were specified in the start-tag
+ rather than defaulted. Each attribute/value pair counts as 2; thus
+ this correspondds to an index into the atts array passed to the
+ XML_StartElementHandler.
+*/
+int XMLPARSEAPI
+xmlrpc_XML_GetSpecifiedAttributeCount(XML_Parser parser);
/* Returns the index of the ID attribute passed in the last call to
-XML_StartElementHandler, or -1 if there is no ID attribute. Each
-attribute/value pair counts as 2; thus this correspondds to an index
-into the atts array passed to the XML_StartElementHandler. */
-int XMLPARSEAPI XML_GetIdAttributeIndex(XML_Parser parser);
+ XML_StartElementHandler, or -1 if there is no ID attribute. Each
+ attribute/value pair counts as 2; thus this correspondds to an index
+ into the atts array passed to the XML_StartElementHandler.
+*/
+int XMLPARSEAPI
+xmlrpc_XML_GetIdAttributeIndex(XML_Parser parser);
/* Parses some input. Returns 0 if a fatal error is detected.
-The last call to XML_Parse must have isFinal true;
-len may be zero for this call (or any other). */
+ The last call to XML_Parse must have isFinal true;
+ len may be zero for this call (or any other).
+*/
int XMLPARSEAPI
-XML_Parse(XML_Parser parser, const char *s, int len, int isFinal);
+xmlrpc_XML_Parse(XML_Parser const parser, const char * const s, int const len, int const isFinal);
void XMLPARSEAPI *
-XML_GetBuffer(XML_Parser parser, int len);
+xmlrpc_XML_GetBuffer(XML_Parser parser, int len);
int XMLPARSEAPI
-XML_ParseBuffer(XML_Parser parser, int len, int isFinal);
+xmlrpc_XML_ParseBuffer(XML_Parser const parser, int const len, int const isFinal);
-/* Creates an XML_Parser object that can parse an external general entity;
-context is a '\0'-terminated string specifying the parse context;
-encoding is a '\0'-terminated string giving the name of the externally specified encoding,
-or null if there is no externally specified encoding.
-The context string consists of a sequence of tokens separated by formfeeds (\f);
-a token consisting of a name specifies that the general entity of the name
-is open; a token of the form prefix=uri specifies the namespace for a particular
-prefix; a token of the form =uri specifies the default namespace.
-This can be called at any point after the first call to an ExternalEntityRefHandler
-so longer as the parser has not yet been freed.
-The new parser is completely independent and may safely be used in a separate thread.
-The handlers and userData are initialized from the parser argument.
-Returns 0 if out of memory. Otherwise returns a new XML_Parser object. */
+/* Creates an XML_Parser object that can parse an external general
+ entity; context is a '\0'-terminated string specifying the parse
+ context; encoding is a '\0'-terminated string giving the name of the
+ externally specified encoding, or null if there is no externally
+ specified encoding. The context string consists of a sequence of
+ tokens separated by formfeeds (\f); a token consisting of a name
+ specifies that the general entity of the name is open; a token of the
+ form prefix=uri specifies the namespace for a particular prefix; a
+ token of the form =uri specifies the default namespace. This can be
+ called at any point after the first call to an
+ ExternalEntityRefHandler so longer as the parser has not yet been
+ freed. The new parser is completely independent and may safely be
+ used in a separate thread. The handlers and userData are initialized
+ from the parser argument. Returns 0 if out of memory. Otherwise
+ returns a new XML_Parser object.
+*/
XML_Parser XMLPARSEAPI
-XML_ExternalEntityParserCreate(XML_Parser parser,
- const XML_Char *context,
- const XML_Char *encoding);
+xmlrpc_XML_ExternalEntityParserCreate(XML_Parser parser,
+ const XML_Char *context,
+ const XML_Char *encoding);
enum XML_ParamEntityParsing {
XML_PARAM_ENTITY_PARSING_NEVER,
@@ -438,27 +455,27 @@
};
/* Controls parsing of parameter entities (including the external DTD
-subset). If parsing of parameter entities is enabled, then references
-to external parameter entities (including the external DTD subset)
-will be passed to the handler set with
-XML_SetExternalEntityRefHandler. The context passed will be 0.
-Unlike external general entities, external parameter entities can only
-be parsed synchronously. If the external parameter entity is to be
-parsed, it must be parsed during the call to the external entity ref
-handler: the complete sequence of XML_ExternalEntityParserCreate,
-XML_Parse/XML_ParseBuffer and XML_ParserFree calls must be made during
-this call. After XML_ExternalEntityParserCreate has been called to
-create the parser for the external parameter entity (context must be 0
-for this call), it is illegal to make any calls on the old parser
-until XML_ParserFree has been called on the newly created parser. If
-the library has been compiled without support for parameter entity
-parsing (ie without XML_DTD being defined), then
-XML_SetParamEntityParsing will return 0 if parsing of parameter
-entities is requested; otherwise it will return non-zero. */
-
+ subset). If parsing of parameter entities is enabled, then references
+ to external parameter entities (including the external DTD subset)
+ will be passed to the handler set with
+ XML_SetExternalEntityRefHandler. The context passed will be 0.
+ Unlike external general entities, external parameter entities can only
+ be parsed synchronously. If the external parameter entity is to be
+ parsed, it must be parsed during the call to the external entity ref
+ handler: the complete sequence of XML_ExternalEntityParserCreate,
+ XML_Parse/XML_ParseBuffer and XML_ParserFree calls must be made during
+ this call. After XML_ExternalEntityParserCreate has been called to
+ create the parser for the external parameter entity (context must be 0
+ for this call), it is illegal to make any calls on the old parser
+ until XML_ParserFree has been called on the newly created parser. If
+ the library has been compiled without support for parameter entity
+ parsing (ie without XML_DTD being defined), then
+ XML_SetParamEntityParsing will return 0 if parsing of parameter
+ entities is requested; otherwise it will return non-zero.
+*/
int XMLPARSEAPI
-XML_SetParamEntityParsing(XML_Parser parser,
- enum XML_ParamEntityParsing parsing);
+xmlrpc_XML_SetParamEntityParsing(XML_Parser parser,
+ enum XML_ParamEntityParsing parsing);
enum XML_Error {
XML_ERROR_NONE,
@@ -486,27 +503,38 @@
XML_ERROR_NOT_STANDALONE
};
-/* If XML_Parse or XML_ParseBuffer have returned 0, then XML_GetErrorCode
-returns information about the error. */
+/* If xmlrpc_XML_Parse or xmlrpc_XML_ParseBuffer have returned 0, then
+ xmlrpc_XML_GetErrorString and xmlrpc_XML_GetErrorCode return
+ information about the error.
+*/
+
+enum XML_Error XMLPARSEAPI
+xmlrpc_XML_GetErrorCode(XML_Parser const parser);
-enum XML_Error XMLPARSEAPI XML_GetErrorCode(XML_Parser parser);
+const char * XMLPARSEAPI
+xmlrpc_XML_GetErrorString(XML_Parser const parser);
/* These functions return information about the current parse location.
-They may be called when XML_Parse or XML_ParseBuffer return 0;
-in this case the location is the location of the character at which
-the error was detected.
-They may also be called from any other callback called to report
-some parse event; in this the location is the location of the first
-of the sequence of characters that generated the event. */
-
-int XMLPARSEAPI XML_GetCurrentLineNumber(XML_Parser parser);
-int XMLPARSEAPI XML_GetCurrentColumnNumber(XML_Parser parser);
-long XMLPARSEAPI XML_GetCurrentByteIndex(XML_Parser parser);
+ They may be called when XML_Parse or XML_ParseBuffer return 0;
+ in this case the location is the location of the character at which
+ the error was detected.
+ They may also be called from any other callback called to report
+ some parse event; in this the location is the location of the first
+ of the sequence of characters that generated the event.
+*/
+
+int XMLPARSEAPI
+xmlrpc_XML_GetCurrentLineNumber(XML_Parser parser);
+int XMLPARSEAPI
+xmlrpc_XML_GetCurrentColumnNumber(XML_Parser parser);
+long XMLPARSEAPI
+xmlrpc_XML_GetCurrentByteIndex(XML_Parser parser);
/* Return the number of bytes in the current event.
Returns 0 if the event is in an internal entity. */
-int XMLPARSEAPI XML_GetCurrentByteCount(XML_Parser parser);
+int XMLPARSEAPI
+xmlrpc_XML_GetCurrentByteCount(XML_Parser parser);
/* For backwards compatibility with previous versions. */
#define XML_GetErrorLineNumber XML_GetCurrentLineNumber
@@ -515,13 +543,14 @@
/* Frees memory used by the parser. */
void XMLPARSEAPI
-XML_ParserFree(XML_Parser parser);
+xmlrpc_XML_ParserFree(XML_Parser parser);
/* Returns a string describing the error. */
-const XML_LChar XMLPARSEAPI *XML_ErrorString(int code);
+const XML_LChar XMLPARSEAPI *
+xmlrpc_XML_ErrorString(int const code);
#ifdef __cplusplus
}
#endif
-#endif /* not XmlParse_INCLUDED */
+#endif
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmltok/Makefile
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmltok/Makefile (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmltok/Makefile Fri May 23 16:56:24 2008
@@ -1,8 +1,23 @@
-ifeq ($(SRCDIR)x,x)
-SRCDIR = $(CURDIR)/../../..
+###############################################################################
+# This directory builds libxmlrpc_xmltok, an XML token parser. This is
+# essentially the separately distributed Expat library from 2001, but
+# with slight changes. The main reason it is bundled with Xmlrpc-c is
+# to make the latter easier to build and use.
+#
+# The library is about XML in general. There is nothing specific to
+# XML-RPC here.
+###############################################################################
+
+ifeq ($(SRCDIR),)
+ updir = $(shell echo $(dir $(1)) | sed 's/.$$//')
+ EXPATDIR := $(call updir,$(CURDIR))
+ LIBDIR := $(call updir,$(EXPATDIR))
+ SRCDIR := $(call updir,$(LIBDIR))
+ BLDDIR := $(SRCDIR)
endif
+SUBDIR := lib/expat/xmltok
-include $(SRCDIR)/Makefile.config
+include $(BLDDIR)/config.mk
# I can't figure out what XML_BYTE_ORDER is, but it doesn't look like the
# code has ever defined it. That means it's treated like 0 in #if. Since
@@ -11,16 +26,54 @@
CFLAGS = $(CFLAGS_COMMON) -DXML_BYTE_ORDER=0 $(CFLAGS_PERSONAL) $(CADD)
-LIBLDFLAGS = $(LDFLAGS_VERSINFO) -rpath $(LIBINST_DIR) $(LADD)
-
-INCLUDES = -I$(SRCDIR) -I$(SRCDIR)/lib/util/include
+# -I. is necessary when blddir != srcdir
+INCLUDES = -I. -I$(BLDDIR) -I$(SRCDIR)/lib/util/include
default: all
-include $(SRCDIR)/Makefile.common
+TARGET_LIBRARY_NAMES := libxmlrpc_xmltok
+
+STATIC_LIBRARIES_TO_INSTALL = libxmlrpc_xmltok.a
+
+SHARED_LIBS_TO_BUILD := libxmlrpc_xmltok
+SHARED_LIBS_TO_INSTALL := libxmlrpc_xmltok
+
+TARGET_MODS = xmltok xmlrole
+
+OMIT_XMLTOK_LIB_RULE = Y
+MAJ=3
+ # Major number of shared libraries in this directory
+
+include $(SRCDIR)/common.mk
+
+XMLTOK_SHLIB = $(call shlibfn,libxmlrpc_xmltok)
+#XMLTOK_SHLIB is e.g. libxmlrpc_xmltok.so.3.1
+XMLTOK_SHLIBLE = $(call shliblefn,libxmlrpc_xmltok)
+#XMLTOK_SHLIBLE is e.g. libxmlrpc_xmltok.so
+
+ifneq ($(SHARED_LIB_TYPE),NONE)
+ TARGET_SHARED_LIBS := $(XMLTOK_SHLIB) $(XMLTOK_SHLIBLE)
+ endif
.PHONY: all
-all: libxmlrpc_xmltok.la
+all: libxmlrpc_xmltok.a $(TARGET_SHARED_LIBS) $(TARGET_SHARED_LE_LIBS)
+
+# Rule for this is in common.mk, courtesy of TARGET_SHARED_LIBRARIES:
+$(XMLTOK_SHLIB): $(TARGET_MODS:%=%.osh)
+$(XMLTOK_SHLIB): LIBOBJECTS = $(TARGET_MODS:%=%.osh)
+
+# Rule for this is in common.mk, courtesy of TARGET_STATIC_LIBRARIES:
+
+libxmlrpc_xmltok.a: $(TARGET_MODS:%=%.o)
+libxmlrpc_xmltok.a: LIBOBJECTS = $(TARGET_MODS:%=%.o)
+
+#-----------------------------------------------------------------------------
+# RULES TO COMPILE OBJECT MODULES FOR LIBRARIES
+#-----------------------------------------------------------------------------
+
+# Rules to compile object modules from which to build the static and shared
+# library are in common.mk, courtesy of TARGET_MODS.
+
.PHONY: clean
clean: clean-common
@@ -41,26 +94,15 @@
.PHONY: dep
dep: dep-common
-LTLIBRARIES_TO_INSTALL = libxmlrpc_xmltok.la
-
-LIBXMLRPC_XMLTOK_OBJS = xmltok.lo xmlrole.lo
-
-libxmlrpc_xmltok.la: $(LIBXMLRPC_XMLTOK_OBJS)
- $(LIBTOOL) --mode=link $(CCLD) -o $@ $(LIBLDFLAGS) $^
-
-$(LIBXMLRPC_XMLTOK_OBJS):%.lo:%.c
- $(LIBTOOL) --mode=compile $(CC) -c $(INCLUDES) $(LIBXML_INCLUDES) \
- $(CFLAGS) $<
-
GENNMTAB = ../gennmtab/gennmtab
nametab.h: $(GENNMTAB)
rm -f $@
- $(GENNMTAB) >$@ || rm -f $@
+ $(GENNMTAB) >$@
$(GENNMTAB):
$(MAKE) -C $(dir $@) $(notdir $@)
-xmltok.lo: nametab.h
+xmltok.o xmltok.osh: nametab.h
include Makefile.depend
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmltok/xmldef.h
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmltok/xmldef.h (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmltok/xmldef.h Fri May 23 16:56:24 2008
@@ -8,7 +8,9 @@
#ifdef XML_WINLIB
#define WIN32_LEAN_AND_MEAN
-#define STRICT
+#ifndef STRICT
+#define STRICT 1
+#endif
#include <windows.h>
#define malloc(x) HeapAlloc(GetProcessHeap(), 0, (x))
@@ -44,9 +46,4 @@
#define XML_UNICODE
#endif
-/* Enable external parameter entity parsing in expat */
-#ifndef XML_DTD
-#define XML_DTD 1
-#endif
-
#endif /* MOZILLA_CLIENT */
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmltok/xmlrole.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmltok/xmlrole.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmltok/xmlrole.c Fri May 23 16:56:24 2008
@@ -43,14 +43,10 @@
#define MIN_BYTES_PER_CHAR(enc) ((enc)->minBytesPerChar)
#endif
-#ifdef XML_DTD
#define setTopLevel(state) \
((state)->handler = ((state)->documentEntity \
? internalSubset \
: externalSubset1))
-#else /* not XML_DTD */
-#define setTopLevel(state) ((state)->handler = internalSubset)
-#endif /* not XML_DTD */
typedef int PROLOG_HANDLER(PROLOG_STATE *state,
int tok,
@@ -69,10 +65,8 @@
attlist7, attlist8, attlist9,
element0, element1, element2, element3, element4, element5, element6,
element7,
-#ifdef XML_DTD
externalSubset0, externalSubset1,
condSect0, condSect1, condSect2,
-#endif /* XML_DTD */
declClose,
error;
@@ -335,7 +329,7 @@
return common(state, tok);
}
-#ifdef XML_DTD
+
static
int externalSubset0(PROLOG_STATE *state,
@@ -380,7 +374,7 @@
return common(state, tok);
}
-#endif /* XML_DTD */
+
static
int entity0(PROLOG_STATE *state,
@@ -1124,7 +1118,7 @@
return common(state, tok);
}
-#ifdef XML_DTD
+
static
int condSect0(PROLOG_STATE *state,
@@ -1150,42 +1144,46 @@
return common(state, tok);
}
-static
-int condSect1(PROLOG_STATE *state,
- int tok,
- const char *ptr,
- const char *end,
- const ENCODING *enc)
-{
- switch (tok) {
- case XML_TOK_PROLOG_S:
- return XML_ROLE_NONE;
- case XML_TOK_OPEN_BRACKET:
- state->handler = externalSubset1;
- state->includeLevel += 1;
- return XML_ROLE_NONE;
- }
- return common(state, tok);
+
+
+static int
+condSect1(PROLOG_STATE * state,
+ int tok,
+ const char * ptr ATTR_UNUSED,
+ const char * end ATTR_UNUSED,
+ const ENCODING * enc ATTR_UNUSED) {
+
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_OPEN_BRACKET:
+ state->handler = externalSubset1;
+ state->includeLevel += 1;
+ return XML_ROLE_NONE;
+ }
+ return common(state, tok);
}
-static
-int condSect2(PROLOG_STATE *state,
- int tok,
- const char *ptr,
- const char *end,
- const ENCODING *enc)
-{
- switch (tok) {
- case XML_TOK_PROLOG_S:
- return XML_ROLE_NONE;
- case XML_TOK_OPEN_BRACKET:
- state->handler = externalSubset1;
- return XML_ROLE_IGNORE_SECT;
- }
- return common(state, tok);
+
+
+static int
+condSect2(PROLOG_STATE * state,
+ int tok,
+ const char * ptr ATTR_UNUSED,
+ const char * end ATTR_UNUSED,
+ const ENCODING * enc ATTR_UNUSED) {
+
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_OPEN_BRACKET:
+ state->handler = externalSubset1;
+ return XML_ROLE_IGNORE_SECT;
+ }
+ return common(state, tok);
}
-#endif /* XML_DTD */
+
static
int declClose(PROLOG_STATE *state,
@@ -1237,30 +1235,28 @@
static
int common(PROLOG_STATE *state, int tok ATTR_UNUSED)
{
-#ifdef XML_DTD
if (!state->documentEntity && tok == XML_TOK_PARAM_ENTITY_REF)
return XML_ROLE_INNER_PARAM_ENTITY_REF;
-#endif
state->handler = error;
return XML_ROLE_ERROR;
}
-void XmlPrologStateInit(PROLOG_STATE *state)
-{
- state->handler = prolog0;
-#ifdef XML_DTD
- state->documentEntity = 1;
- state->includeLevel = 0;
-#endif /* XML_DTD */
-}
-#ifdef XML_DTD
-void XmlPrologStateInitExternalEntity(PROLOG_STATE *state)
-{
- state->handler = externalSubset0;
- state->documentEntity = 0;
- state->includeLevel = 0;
+void
+xmlrpc_XmlPrologStateInit(PROLOG_STATE * const state) {
+
+ state->handler = prolog0;
+ state->documentEntity = 1;
+ state->includeLevel = 0;
}
-#endif /* XML_DTD */
+
+
+void
+xmlrpc_XmlPrologStateInitExternalEntity(PROLOG_STATE * const state) {
+
+ state->handler = externalSubset0;
+ state->documentEntity = 0;
+ state->includeLevel = 0;
+}
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmltok/xmlrole.h
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmltok/xmlrole.h (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmltok/xmlrole.h Fri May 23 16:56:24 2008
@@ -62,11 +62,9 @@
XML_ROLE_CONTENT_ELEMENT_REP,
XML_ROLE_CONTENT_ELEMENT_OPT,
XML_ROLE_CONTENT_ELEMENT_PLUS,
-#ifdef XML_DTD
XML_ROLE_TEXT_DECL,
XML_ROLE_IGNORE_SECT,
XML_ROLE_INNER_PARAM_ENTITY_REF,
-#endif /* XML_DTD */
XML_ROLE_PARAM_ENTITY_REF,
XML_ROLE_EXTERNAL_GENERAL_ENTITY_NO_NOTATION
};
@@ -78,16 +76,15 @@
const char *end,
const ENCODING *enc);
unsigned level;
-#ifdef XML_DTD
unsigned includeLevel;
int documentEntity;
-#endif /* XML_DTD */
} PROLOG_STATE;
-void XMLTOKAPI XmlPrologStateInit(PROLOG_STATE *);
-#ifdef XML_DTD
-void XMLTOKAPI XmlPrologStateInitExternalEntity(PROLOG_STATE *);
-#endif /* XML_DTD */
+XMLTOKAPI void
+xmlrpc_XmlPrologStateInit(PROLOG_STATE * const state);
+
+XMLTOKAPI void
+xmlrpc_XmlPrologStateInitExternalEntity(PROLOG_STATE * const state);
#define XmlTokenRole(state, tok, ptr, end, enc) \
(((state)->handler)(state, tok, ptr, end, enc))
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmltok/xmltok.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmltok/xmltok.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmltok/xmltok.c Fri May 23 16:56:24 2008
@@ -8,11 +8,7 @@
#include "xmltok.h"
#include "nametab.h"
-#ifdef XML_DTD
#define IGNORE_SECTION_TOK_VTABLE , PREFIX(ignoreSectionTok)
-#else
-#define IGNORE_SECTION_TOK_VTABLE /* as nothing */
-#endif
#define VTABLE1 \
{ PREFIX(prologTok), PREFIX(contentTok), \
@@ -321,7 +317,6 @@
*toP = to;
}
-#ifdef XML_NS
static const struct normal_encoding utf8_encoding_ns = {
{ VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
{
@@ -330,7 +325,6 @@
},
STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
};
-#endif
static const struct normal_encoding utf8_encoding = {
{ VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
@@ -343,8 +337,6 @@
STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
};
-#ifdef XML_NS
-
static const struct normal_encoding internal_utf8_encoding_ns = {
{ VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
{
@@ -354,8 +346,6 @@
STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
};
-#endif
-
static const struct normal_encoding internal_utf8_encoding = {
{ VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
{
@@ -401,8 +391,6 @@
*(*toP)++ = (unsigned char)*(*fromP)++;
}
-#ifdef XML_NS
-
static const struct normal_encoding latin1_encoding_ns = {
{ VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 },
{
@@ -412,8 +400,6 @@
STANDARD_VTABLE(sb_) NULL_NORMAL_VTABLE
};
-#endif
-
static const struct normal_encoding latin1_encoding = {
{ VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 },
{
@@ -434,19 +420,15 @@
*(*toP)++ = *(*fromP)++;
}
-#ifdef XML_NS
-
static const struct normal_encoding ascii_encoding_ns = {
{ VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 },
{
#include "asciitab.h"
/* BT_NONXML == 0 */
},
- STANDARD_VTABLE(sb_)
+ STANDARD_VTABLE(sb_) NULL_NORMAL_VTABLE
};
-#endif
-
static const struct normal_encoding ascii_encoding = {
{ VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 },
{
@@ -651,8 +633,6 @@
#endif /* not XML_MIN_SIZE */
-#ifdef XML_NS
-
static const struct normal_encoding little2_encoding_ns = {
{ VTABLE, 2, 0,
#if XML_BYTE_ORDER == 12
@@ -668,8 +648,6 @@
STANDARD_VTABLE(little2_) NULL_NORMAL_VTABLE
};
-#endif
-
static const struct normal_encoding little2_encoding = {
{ VTABLE, 2, 0,
#if XML_BYTE_ORDER == 12
@@ -689,8 +667,6 @@
#if XML_BYTE_ORDER != 21
-#ifdef XML_NS
-
static const struct normal_encoding internal_little2_encoding_ns = {
{ VTABLE, 2, 0, 1 },
{
@@ -700,8 +676,6 @@
STANDARD_VTABLE(little2_) NULL_NORMAL_VTABLE
};
-#endif
-
static const struct normal_encoding internal_little2_encoding = {
{ VTABLE, 2, 0, 1 },
{
@@ -790,8 +764,6 @@
#endif /* not XML_MIN_SIZE */
-#ifdef XML_NS
-
static const struct normal_encoding big2_encoding_ns = {
{ VTABLE, 2, 0,
#if XML_BYTE_ORDER == 21
@@ -807,8 +779,6 @@
STANDARD_VTABLE(big2_) NULL_NORMAL_VTABLE
};
-#endif
-
static const struct normal_encoding big2_encoding = {
{ VTABLE, 2, 0,
#if XML_BYTE_ORDER == 21
@@ -828,19 +798,15 @@
#if XML_BYTE_ORDER != 12
-#ifdef XML_NS
-
static const struct normal_encoding internal_big2_encoding_ns = {
{ VTABLE, 2, 0, 1 },
{
#include "iasciitab.h"
#include "latin1tab.h"
},
- STANDARD_VTABLE(big2_)
+ STANDARD_VTABLE(big2_) NULL_NORMAL_VTABLE
};
-#endif
-
static const struct normal_encoding internal_big2_encoding = {
{ VTABLE, 2, 0, 1 },
{
@@ -1119,8 +1085,12 @@
return result;
}
-int XmlUtf8Encode(int c, char *buf)
-{
+
+
+int
+xmlrpc_XmlUtf8Encode(int const c,
+ char * const buf) {
+
enum {
/* minN is minimum legal resulting value for N byte sequence */
min2 = 0x80,
@@ -1155,23 +1125,33 @@
return 0;
}
-int XmlUtf16Encode(int charNum, unsigned short *buf)
-{
- if (charNum < 0)
+
+
+int
+xmlrpc_XmlUtf16Encode(int const charNumArg,
+ unsigned short * const buf) {
+
+ int charNum;
+
+ charNum = charNumArg; /* initial value */
+
+ if (charNum < 0)
+ return 0;
+ if (charNum < 0x10000) {
+ buf[0] = charNum;
+ return 1;
+ }
+ if (charNum < 0x110000) {
+ charNum -= 0x10000;
+ buf[0] = (charNum >> 10) + 0xD800;
+ buf[1] = (charNum & 0x3FF) + 0xDC00;
+ return 2;
+ }
return 0;
- if (charNum < 0x10000) {
- buf[0] = charNum;
- return 1;
- }
- if (charNum < 0x110000) {
- charNum -= 0x10000;
- buf[0] = (charNum >> 10) + 0xD800;
- buf[1] = (charNum & 0x3FF) + 0xDC00;
- return 2;
- }
- return 0;
}
+
+
struct unknown_encoding {
struct normal_encoding normal;
int (*convert)(void *userData, const char *p);
@@ -1180,11 +1160,16 @@
char utf8[256][4];
};
-int XmlSizeOfUnknownEncoding(void)
-{
- return sizeof(struct unknown_encoding);
+
+
+int
+xmlrpc_XmlSizeOfUnknownEncoding(void) {
+
+ return sizeof(struct unknown_encoding);
}
+
+
static
int unknown_isName(const ENCODING *enc, const char *p)
{
@@ -1229,7 +1214,7 @@
if (n == 0) {
int c = ((const struct unknown_encoding *)enc)
->convert(((const struct unknown_encoding *)enc)->userData, *fromP);
- n = XmlUtf8Encode(c, buf);
+ n = xmlrpc_XmlUtf8Encode(c, buf);
if (n > toLim - *toP)
break;
utf8 = buf;
@@ -1268,11 +1253,11 @@
}
ENCODING *
-XmlInitUnknownEncoding(void *mem,
- int *table,
- int (*convert)(void *userData, const char *p),
- void *userData)
-{
+xmlrpc_XmlInitUnknownEncoding(void * const mem,
+ int * const table,
+ int (*convert)(void *userData, const char *p),
+ void * const userData) {
+
int i;
struct unknown_encoding *e = mem;
for (i = 0; i < (int)sizeof(struct normal_encoding); i++)
@@ -1324,7 +1309,7 @@
e->normal.type[i] = BT_NAME;
else
e->normal.type[i] = BT_OTHER;
- e->utf8[i][0] = (char)XmlUtf8Encode(c, e->utf8[i] + 1);
+ e->utf8[i][0] = (char)xmlrpc_XmlUtf8Encode(c, e->utf8[i] + 1);
e->utf16[i] = c;
}
}
@@ -1428,11 +1413,6 @@
encPtr = enc->encPtr;
if (ptr + 1 == end) {
/* only a single byte available for auto-detection */
-#ifndef XML_DTD /* FIXME */
- /* a well-formed document entity must have more than one byte */
- if (state != XML_CONTENT_STATE)
- return XML_TOK_PARTIAL;
-#endif
/* so we're parsing an external text entity... */
/* if UTF-16 was externally specified, then we need at least 2 bytes */
switch (INIT_ENC_INDEX(enc)) {
@@ -1536,8 +1516,6 @@
#undef NS
#undef ns
-#ifdef XML_NS
-
#define NS(x) x ## NS
#define ns(x) x ## _ns
@@ -1547,15 +1525,14 @@
#undef ns
ENCODING *
-XmlInitUnknownEncodingNS(void *mem,
- int *table,
- int (*convert)(void *userData, const char *p),
- void *userData)
-{
- ENCODING *enc = XmlInitUnknownEncoding(mem, table, convert, userData);
- if (enc)
- ((struct normal_encoding *)enc)->type[ASCII_COLON] = BT_COLON;
- return enc;
+xmlrpc_XmlInitUnknownEncodingNS(void * const mem,
+ int * const table,
+ int (*convert)(void *userData, const char *p),
+ void * const userData) {
+
+ ENCODING * const enc =
+ xmlrpc_XmlInitUnknownEncoding(mem, table, convert, userData);
+ if (enc)
+ ((struct normal_encoding *)enc)->type[ASCII_COLON] = BT_COLON;
+ return enc;
}
-
-#endif /* XML_NS */
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmltok/xmltok.h
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmltok/xmltok.h (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmltok/xmltok.h Fri May 23 16:56:24 2008
@@ -83,22 +83,14 @@
for a name with a colon. */
#define XML_TOK_PREFIXED_NAME 41
-#ifdef XML_DTD
#define XML_TOK_IGNORE_SECT 42
-#endif /* XML_DTD */
-#ifdef XML_DTD
#define XML_N_STATES 4
-#else /* not XML_DTD */
-#define XML_N_STATES 3
-#endif /* not XML_DTD */
#define XML_PROLOG_STATE 0
#define XML_CONTENT_STATE 1
#define XML_CDATA_SECTION_STATE 2
-#ifdef XML_DTD
#define XML_IGNORE_SECTION_STATE 3
-#endif /* XML_DTD */
#define XML_N_LITERAL_TYPES 2
#define XML_ATTRIBUTE_VALUE_LITERAL 0
@@ -198,13 +190,9 @@
#define XmlCdataSectionTok(enc, ptr, end, nextTokPtr) \
XmlTok(enc, XML_CDATA_SECTION_STATE, ptr, end, nextTokPtr)
-#ifdef XML_DTD
-
#define XmlIgnoreSectionTok(enc, ptr, end, nextTokPtr) \
XmlTok(enc, XML_IGNORE_SECTION_STATE, ptr, end, nextTokPtr)
-#endif /* XML_DTD */
-
/* This is used for performing a 2nd-level tokenization on
the content of a literal that has already been returned by XmlTok. */
@@ -254,46 +242,73 @@
const ENCODING **encPtr;
} INIT_ENCODING;
-int XMLTOKAPI XmlParseXmlDecl(int isGeneralTextEntity,
- const ENCODING *enc,
- const char *ptr,
- const char *end,
- const char **badPtr,
- const char **versionPtr,
- const char **encodingNamePtr,
- const ENCODING **namedEncodingPtr,
- int *standalonePtr);
-
-int XMLTOKAPI XmlInitEncoding(INIT_ENCODING *, const ENCODING **, const char *name);
-const ENCODING XMLTOKAPI *XmlGetUtf8InternalEncoding(void);
-const ENCODING XMLTOKAPI *XmlGetUtf16InternalEncoding(void);
-int XMLTOKAPI XmlUtf8Encode(int charNumber, char *buf);
-int XMLTOKAPI XmlUtf16Encode(int charNumber, unsigned short *buf);
-
-int XMLTOKAPI XmlSizeOfUnknownEncoding(void);
-ENCODING XMLTOKAPI *
-XmlInitUnknownEncoding(void *mem,
- int *table,
- int (*conv)(void *userData, const char *p),
- void *userData);
-
-int XMLTOKAPI XmlParseXmlDeclNS(int isGeneralTextEntity,
- const ENCODING *enc,
- const char *ptr,
- const char *end,
- const char **badPtr,
- const char **versionPtr,
- const char **encodingNamePtr,
- const ENCODING **namedEncodingPtr,
- int *standalonePtr);
-int XMLTOKAPI XmlInitEncodingNS(INIT_ENCODING *, const ENCODING **, const char *name);
-const ENCODING XMLTOKAPI *XmlGetUtf8InternalEncodingNS(void);
-const ENCODING XMLTOKAPI *XmlGetUtf16InternalEncodingNS(void);
-ENCODING XMLTOKAPI *
-XmlInitUnknownEncodingNS(void *mem,
- int *table,
- int (*conv)(void *userData, const char *p),
- void *userData);
+XMLTOKAPI int
+xmlrpc_XmlParseXmlDecl(int const isGeneralTextEntity,
+ const ENCODING * const enc,
+ const char * const ptr,
+ const char * const end,
+ const char ** const badPtr,
+ const char ** const versionPtr,
+ const char ** const encodingNamePtr,
+ const ENCODING ** const namedEncodingPtr,
+ int * const standalonePtr);
+
+XMLTOKAPI const ENCODING *
+xmlrpc_XmlGetUtf8InternalEncoding(void);
+
+XMLTOKAPI const ENCODING *
+xmlrpc_XmlGetUtf16InternalEncoding(void);
+
+XMLTOKAPI int
+xmlrpc_XmlInitEncoding(INIT_ENCODING * const p,
+ const ENCODING ** const encPtr,
+ const char * const name);
+
+XMLTOKAPI int
+xmlrpc_XmlUtf8Encode(int const c,
+ char * const buf);
+
+XMLTOKAPI int
+xmlrpc_XmlUtf16Encode(int const charNum,
+ unsigned short * const buf);
+
+XMLTOKAPI int
+xmlrpc_XmlSizeOfUnknownEncoding(void);
+
+XMLTOKAPI ENCODING *
+xmlrpc_XmlInitUnknownEncoding(void * const mem,
+ int * const table,
+ int (*convert)(void *userData, const char *p),
+ void * const userData);
+
+int
+xmlrpc_XmlParseXmlDeclNS(int const isGeneralTextEntity,
+ const ENCODING * const enc,
+ const char * const ptr,
+ const char * const end,
+ const char ** const badPtr,
+ const char ** const versionPtr,
+ const char ** const encodingNamePtr,
+ const ENCODING ** const namedEncodingPtr,
+ int * const standalonePtr);
+
+int
+xmlrpc_XmlInitEncodingNS(INIT_ENCODING * const p,
+ const ENCODING ** const encPtr,
+ const char * const name);
+
+const ENCODING *
+xmlrpc_XmlGetUtf8InternalEncodingNS(void);
+
+const ENCODING *
+xmlrpc_XmlGetUtf16InternalEncodingNS(void);
+
+ENCODING *
+xmlrpc_XmlInitUnknownEncodingNS(void * const mem,
+ int * const table,
+ int (*convert)(void *userData, const char *p),
+ void * const userData);
+
#ifdef __cplusplus
}
#endif
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmltok/xmltok_impl.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmltok/xmltok_impl.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmltok/xmltok_impl.c Fri May 23 16:56:24 2008
@@ -410,12 +410,10 @@
}
}
return XML_TOK_PARTIAL;
-#ifdef XML_NS
case BT_COLON:
/* no need to check qname syntax here, since end-tag must match exactly */
ptr += MINBPC(enc);
break;
-#endif
case BT_GT:
*nextTokPtr = ptr + MINBPC(enc);
return XML_TOK_END_TAG;
@@ -527,13 +525,10 @@
int PREFIX(scanAtts)(const ENCODING *enc, const char *ptr, const char *end,
const char **nextTokPtr)
{
-#ifdef XML_NS
int hadColon = 0;
-#endif
while (ptr != end) {
switch (BYTE_TYPE(enc, ptr)) {
CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
-#ifdef XML_NS
case BT_COLON:
if (hadColon) {
*nextTokPtr = ptr;
@@ -550,7 +545,6 @@
return XML_TOK_INVALID;
}
break;
-#endif
case BT_S: case BT_CR: case BT_LF:
for (;;) {
int t;
@@ -575,9 +569,7 @@
case BT_EQUALS:
{
int open;
-#ifdef XML_NS
hadColon = 0;
-#endif
for (;;) {
ptr += MINBPC(enc);
@@ -687,9 +679,7 @@
int PREFIX(scanLt)(const ENCODING *enc, const char *ptr, const char *end,
const char **nextTokPtr)
{
-#ifdef XML_NS
int hadColon;
-#endif
if (ptr == end)
return XML_TOK_PARTIAL;
switch (BYTE_TYPE(enc, ptr)) {
@@ -713,14 +703,11 @@
*nextTokPtr = ptr;
return XML_TOK_INVALID;
}
-#ifdef XML_NS
hadColon = 0;
-#endif
/* we have a start-tag */
while (ptr != end) {
switch (BYTE_TYPE(enc, ptr)) {
CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
-#ifdef XML_NS
case BT_COLON:
if (hadColon) {
*nextTokPtr = ptr;
@@ -737,7 +724,6 @@
return XML_TOK_INVALID;
}
break;
-#endif
case BT_S: case BT_CR: case BT_LF:
{
ptr += MINBPC(enc);
@@ -1117,9 +1103,7 @@
case BT_DIGIT:
case BT_NAME:
case BT_MINUS:
-#ifdef XML_NS
case BT_COLON:
-#endif
tok = XML_TOK_NMTOKEN;
ptr += MINBPC(enc);
break;
@@ -1147,7 +1131,6 @@
case BT_S: case BT_CR: case BT_LF:
*nextTokPtr = ptr;
return tok;
-#ifdef XML_NS
case BT_COLON:
ptr += MINBPC(enc);
switch (tok) {
@@ -1167,7 +1150,6 @@
break;
}
break;
-#endif
case BT_PLUS:
if (tok == XML_TOK_NMTOKEN) {
*nextTokPtr = ptr;
@@ -1307,7 +1289,7 @@
return XML_TOK_DATA_CHARS;
}
-#ifdef XML_DTD
+
static
int PREFIX(ignoreSectionTok)(const ENCODING *enc, const char *ptr, const char *end,
@@ -1360,7 +1342,7 @@
return XML_TOK_PARTIAL;
}
-#endif /* XML_DTD */
+
static
int PREFIX(isPublicId)(const ENCODING *enc, const char *ptr, const char *end,
@@ -1388,9 +1370,7 @@
case BT_AST:
case BT_PERCNT:
case BT_NUM:
-#ifdef XML_NS
case BT_COLON:
-#endif
break;
case BT_S:
if (CHAR_MATCHES(enc, ptr, ASCII_TAB)) {
@@ -1626,9 +1606,7 @@
break;
case BT_NONASCII:
case BT_NMSTRT:
-#ifdef XML_NS
case BT_COLON:
-#endif
case BT_HEX:
case BT_DIGIT:
case BT_NAME:
@@ -1657,9 +1635,7 @@
case BT_LEAD4:
case BT_NONASCII:
case BT_NMSTRT:
-#ifdef XML_NS
case BT_COLON:
-#endif
case BT_HEX:
case BT_DIGIT:
case BT_NAME:
@@ -1700,9 +1676,7 @@
#undef LEAD_CASE
case BT_NONASCII:
case BT_NMSTRT:
-#ifdef XML_NS
case BT_COLON:
-#endif
case BT_HEX:
case BT_DIGIT:
case BT_NAME:
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmltok/xmltok_ns.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmltok/xmltok_ns.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmltok/xmltok_ns.c Fri May 23 16:56:24 2008
@@ -1,17 +1,23 @@
-const ENCODING *NS(XmlGetUtf8InternalEncoding)(void)
-{
- return &ns(internal_utf8_encoding).enc;
+const ENCODING *
+NS(xmlrpc_XmlGetUtf8InternalEncoding)(void) {
+
+ return &ns(internal_utf8_encoding).enc;
}
-const ENCODING *NS(XmlGetUtf16InternalEncoding)(void)
-{
+
+
+const ENCODING *
+NS(xmlrpc_XmlGetUtf16InternalEncoding)(void) {
+
#if XML_BYTE_ORDER == 12
- return &ns(internal_little2_encoding).enc;
+ return &ns(internal_little2_encoding).enc;
#elif XML_BYTE_ORDER == 21
- return &ns(internal_big2_encoding).enc;
+ return &ns(internal_big2_encoding).enc;
#else
- const short n = 1;
- return *(const char *)&n ? &ns(internal_little2_encoding).enc : &ns(internal_big2_encoding).enc;
+ const short n = 1;
+ return *(const char *)&n ?
+ &ns(internal_little2_encoding).enc :
+ &ns(internal_big2_encoding).enc;
#endif
}
@@ -40,20 +46,27 @@
return initScan(NS(encodings), (const INIT_ENCODING *)enc, XML_CONTENT_STATE, ptr, end, nextTokPtr);
}
-int NS(XmlInitEncoding)(INIT_ENCODING *p, const ENCODING **encPtr, const char *name)
-{
- int i = getEncodingIndex(name);
- if (i == UNKNOWN_ENC)
- return 0;
- SET_INIT_ENC_INDEX(p, i);
- p->initEnc.scanners[XML_PROLOG_STATE] = NS(initScanProlog);
- p->initEnc.scanners[XML_CONTENT_STATE] = NS(initScanContent);
- p->initEnc.updatePosition = initUpdatePosition;
- p->encPtr = encPtr;
- *encPtr = &(p->initEnc);
- return 1;
+
+
+int
+NS(xmlrpc_XmlInitEncoding)(INIT_ENCODING * const p,
+ const ENCODING ** const encPtr,
+ const char * const name) {
+
+ int i = getEncodingIndex(name);
+ if (i == UNKNOWN_ENC)
+ return 0;
+ SET_INIT_ENC_INDEX(p, i);
+ p->initEnc.scanners[XML_PROLOG_STATE] = NS(initScanProlog);
+ p->initEnc.scanners[XML_CONTENT_STATE] = NS(initScanContent);
+ p->initEnc.updatePosition = initUpdatePosition;
+ p->encPtr = encPtr;
+ *encPtr = &(p->initEnc);
+ return 1;
}
+
+
static
const ENCODING *NS(findEncoding)(const ENCODING *enc, const char *ptr, const char *end)
{
@@ -73,24 +86,27 @@
return NS(encodings)[i];
}
-int NS(XmlParseXmlDecl)(int isGeneralTextEntity,
- const ENCODING *enc,
- const char *ptr,
- const char *end,
- const char **badPtr,
- const char **versionPtr,
- const char **encodingName,
- const ENCODING **encoding,
- int *standalone)
-{
+
+
+int
+NS(xmlrpc_XmlParseXmlDecl)(int const isGeneralTextEntity,
+ const ENCODING * const enc,
+ const char * const ptr,
+ const char * const end,
+ const char ** const badPtr,
+ const char ** const versionPtr,
+ const char ** const encodingName,
+ const ENCODING ** const encoding,
+ int * const standalone) {
+
return doParseXmlDecl(NS(findEncoding),
- isGeneralTextEntity,
- enc,
- ptr,
- end,
- badPtr,
- versionPtr,
- encodingName,
- encoding,
- standalone);
+ isGeneralTextEntity,
+ enc,
+ ptr,
+ end,
+ badPtr,
+ versionPtr,
+ encodingName,
+ encoding,
+ standalone);
}
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmlwf/xmlfile.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmlwf/xmlfile.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmlwf/xmlfile.c Fri May 23 16:56:24 2008
@@ -13,7 +13,7 @@
#include "xmltchar.h"
#include "filemap.h"
-#ifdef _MSC_VER
+#if MSVCRT
#include <io.h>
#endif
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmlwf/xmlwf.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmlwf/xmlwf.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/expat/xmlwf/xmlwf.c Fri May 23 16:56:24 2008
@@ -13,7 +13,7 @@
#include "xmlfile.h"
#include "xmltchar.h"
-#ifdef _MSC_VER
+#if MSVCRT
#include <crtdbg.h>
#endif
@@ -584,7 +584,7 @@
int requireStandalone = 0;
int paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
-#ifdef _MSC_VER
+#if MSVCRT
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF);
#endif
Added: freeswitch/trunk/libs/xmlrpc-c/lib/libutil/Makefile
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/libutil/Makefile Fri May 23 16:56:24 2008
@@ -0,0 +1,95 @@
+###############################################################################
+# This directory builds libxmlrpc_util, which contains utility
+# functions that are used by the Xmlprc-c # libraries, and also
+# directly by Xmlrpc-c programs.
+#
+# The functions in this library are characterized by being general purpose
+# programming functions, such as one might wish were in the standard C
+# library, which have nothing in particular to do with XML-RPC.
+###############################################################################
+
+ifeq ($(SRCDIR),)
+ updir = $(shell echo $(dir $(1)) | sed 's/.$$//')
+ LIBDIR := $(call updir,$(CURDIR))
+ SRCDIR := $(call updir,$(LIBDIR))
+ BLDDIR := $(SRCDIR)
+endif
+SUBDIR := lib/libutil
+
+include $(BLDDIR)/config.mk
+
+default: all
+
+TARGET_LIBRARY_NAMES := libxmlrpc_util
+
+STATIC_LIBRARIES_TO_INSTALL = libxmlrpc_util.a
+
+SHARED_LIBS_TO_BUILD := libxmlrpc_util
+SHARED_LIBS_TO_INSTALL := libxmlrpc_util
+
+TARGET_MODS = \
+ asprintf \
+ error \
+ make_printable \
+ memblock \
+ select \
+ sleep \
+ time \
+ utf8 \
+
+OMIT_LIBXMLRPC_UTIL_RULE=Y
+MAJ=3
+ # Major number of shared libraries in this directory
+
+include $(SRCDIR)/common.mk
+
+CFLAGS = $(CFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD)
+
+INCLUDES = -I$(BLDDIR) -Isrcdir \
+ -I$(BLDDIR)/include -Isrcdir/include -Isrcdir/lib/util/include
+
+UTIL_SHLIB = $(call shlibfn,libxmlrpc_util)
+#UTIL_SHLIB is e.g. libxmlrpc_util.so.3.1
+UTIL_SHLIBLE = $(call shliblefn,libxmlrpc_util)
+#UTIL_SHLIBLE is e.g. libxmlrpc_util.so
+
+ifneq ($(SHARED_LIB_TYPE),NONE)
+ TARGET_SHARED_LIBS := $(UTIL_SHLIB) $(UTIL_SHLIBLE)
+ endif
+
+# This 'common.mk' dependency makes sure the symlinks get built before
+# this make file is used for anything.
+
+$(SRCDIR)/common.mk: srcdir blddir
+
+.PHONY: all
+all: libxmlrpc_util.a $(TARGET_SHARED_LIBS) $(TARGET_SHARED_LE_LIBS)
+
+# Rule for this is in common.mk, courtesy of TARGET_LIBRARY_NAMES:
+$(UTIL_SHLIB): $(TARGET_MODS:%=%.osh)
+$(UTIL_SHLIB): LIBOBJECTS = $(TARGET_MODS:%=%.osh)
+
+# Rule for this is in common.mk, courtesy of TARGET_LIBRARY_NAMES:
+
+libxmlrpc_util.a: $(TARGET_MODS:%=%.o)
+libxmlrpc_util.a: LIBOBJECTS = $(TARGET_MODS:%=%.o)
+
+#-----------------------------------------------------------------------------
+# RULES TO COMPILE OBJECT MODULES FOR LIBRARIES
+#-----------------------------------------------------------------------------
+
+# Rules to compile object modules from which to build the static and shared
+# library are in common.mk, courtesy of TARGET_MODS.
+
+.PHONY: install
+install: install-common
+
+.PHONY: clean distclean
+clean: clean-common
+
+distclean: clean distclean-common
+
+.PHONY: dep
+dep: dep-common
+
+include Makefile.depend
Added: freeswitch/trunk/libs/xmlrpc-c/lib/libutil/asprintf.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/libutil/asprintf.c Fri May 23 16:56:24 2008
@@ -0,0 +1,116 @@
+#define _GNU_SOURCE
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "xmlrpc_config.h" /* For HAVE_ASPRINTF, __inline__ */
+#include "xmlrpc-c/string_int.h"
+
+
+
+static __inline__ void
+simpleVasprintf(char ** const retvalP,
+ const char * const fmt,
+ va_list varargs) {
+/*----------------------------------------------------------------------------
+ This is a poor man's implementation of vasprintf(), of GNU fame.
+-----------------------------------------------------------------------------*/
+ size_t const initialSize = 4096;
+ char * result;
+
+ result = malloc(initialSize);
+ if (result != NULL) {
+ size_t bytesNeeded;
+ bytesNeeded = XMLRPC_VSNPRINTF(result, initialSize, fmt, varargs);
+ if (bytesNeeded > initialSize) {
+ free(result);
+ result = malloc(bytesNeeded);
+ if (result != NULL)
+ XMLRPC_VSNPRINTF(result, bytesNeeded, fmt, varargs);
+ } else if (bytesNeeded == initialSize) {
+ if (result[initialSize-1] != '\0') {
+ /* This is one of those old systems where vsnprintf()
+ returns the number of bytes it used, instead of the
+ number that it needed, and it in fact needed more than
+ we gave it. Rather than mess with this highly unlikely
+ case (old system and string > 4095 characters), we just
+ treat this like an out of memory failure.
+ */
+ free(result);
+ result = NULL;
+ }
+ }
+ }
+ *retvalP = result;
+}
+
+
+
+const char * const xmlrpc_strsol = "[insufficient memory to build string]";
+
+
+
+void
+xmlrpc_vasprintf(const char ** const retvalP,
+ const char * const fmt,
+ va_list varargs) {
+
+ char * string;
+
+#if HAVE_ASPRINTF
+ vasprintf(&string, fmt, varargs);
+#else
+ simpleVasprintf(&string, fmt, varargs);
+#endif
+
+ if (string == NULL)
+ *retvalP = xmlrpc_strsol;
+ else
+ *retvalP = string;
+}
+
+
+
+void GNU_PRINTF_ATTR(2,3)
+xmlrpc_asprintf(const char ** const retvalP, const char * const fmt, ...) {
+
+ va_list varargs; /* mysterious structure used by variable arg facility */
+
+ va_start(varargs, fmt); /* start up the mysterious variable arg facility */
+
+ xmlrpc_vasprintf(retvalP, fmt, varargs);
+
+ va_end(varargs);
+}
+
+
+
+const char *
+xmlrpc_strdupnull(const char * const string) {
+
+ if (string)
+ return strdup(string);
+ else
+ return NULL;
+}
+
+
+
+void
+xmlrpc_strfree(const char * const string) {
+
+ if (string != xmlrpc_strsol)
+ free((void *)string);
+}
+
+
+
+void
+xmlrpc_strfreenull(const char * const string) {
+
+ if (string)
+ xmlrpc_strfree(string);
+}
+
+
+
Added: freeswitch/trunk/libs/xmlrpc-c/lib/libutil/error.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/libutil/error.c Fri May 23 16:56:24 2008
@@ -0,0 +1,163 @@
+/* Copyright information is at end of file */
+
+#include "xmlrpc_config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include "xmlrpc-c/util_int.h"
+#include "xmlrpc-c/string_int.h"
+#include "xmlrpc-c/util.h"
+
+
+
+void
+xmlrpc_assertion_failed(const char * const fileName,
+ int const lineNumber) {
+
+ fprintf(stderr, "%s:%d: assertion failed\n", fileName, lineNumber);
+ abort();
+}
+
+
+
+static const char * const default_fault_string =
+ "Not enough memory for error message";
+
+void xmlrpc_env_init (xmlrpc_env* env)
+{
+ XMLRPC_ASSERT(env != NULL);
+
+ env->fault_occurred = 0;
+ env->fault_code = 0;
+ env->fault_string = NULL;
+}
+
+void
+xmlrpc_env_clean(xmlrpc_env * const envP) {
+
+ XMLRPC_ASSERT(envP != NULL);
+ XMLRPC_ASSERT(envP->fault_string != XMLRPC_BAD_POINTER);
+
+ /* env->fault_string may be one of three things:
+ ** 1) a NULL pointer
+ ** 2) a pointer to the default_fault_string
+ ** 3) a pointer to a malloc'd fault string
+ ** If we have case (3), we'll need to free it. */
+ if (envP->fault_string && envP->fault_string != default_fault_string)
+ free(envP->fault_string);
+ envP->fault_string = XMLRPC_BAD_POINTER;
+}
+
+
+
+void
+xmlrpc_env_set_fault(xmlrpc_env * const envP,
+ int const faultCode,
+ const char * const faultDescription) {
+
+ char * buffer;
+
+ XMLRPC_ASSERT(envP != NULL);
+ XMLRPC_ASSERT(faultDescription != NULL);
+
+ /* Clean up any leftover pointers. */
+ xmlrpc_env_clean(envP);
+
+ envP->fault_occurred = 1;
+ envP->fault_code = faultCode;
+
+ /* Try to copy the fault string. If this fails, use a default. */
+ buffer = strdup(faultDescription);
+ if (buffer == NULL)
+ envP->fault_string = (char *)default_fault_string;
+ else {
+ xmlrpc_force_to_utf8(buffer);
+ xmlrpc_force_to_xml_chars(buffer);
+ envP->fault_string = buffer;
+ }
+}
+
+
+
+void
+xmlrpc_set_fault_formatted_v(xmlrpc_env * const envP,
+ int const code,
+ const char * const format,
+ va_list const args) {
+
+ const char * faultDescription;
+
+ xmlrpc_vasprintf(&faultDescription, format, args);
+
+ xmlrpc_env_set_fault(envP, code, faultDescription);
+
+ xmlrpc_strfree(faultDescription);
+}
+
+
+
+void
+xmlrpc_env_set_fault_formatted(xmlrpc_env * const envP,
+ int const code,
+ const char * const format,
+ ...) {
+ va_list args;
+
+ XMLRPC_ASSERT(envP != NULL);
+ XMLRPC_ASSERT(format != NULL);
+
+ /* Print our error message to the buffer. */
+ va_start(args, format);
+ xmlrpc_set_fault_formatted_v(envP, code, format, args);
+ va_end(args);
+}
+
+
+
+void
+xmlrpc_faultf(xmlrpc_env * const envP,
+ const char * const format,
+ ...) {
+
+ va_list args;
+
+ XMLRPC_ASSERT(envP != NULL);
+ XMLRPC_ASSERT(format != NULL);
+
+ /* Print our error message to the buffer. */
+ va_start(args, format);
+ xmlrpc_set_fault_formatted_v(envP, XMLRPC_INTERNAL_ERROR, format, args);
+ va_end(args);
+
+}
+
+
+
+/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR 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. */
+
Added: freeswitch/trunk/libs/xmlrpc-c/lib/libutil/make_printable.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/libutil/make_printable.c Fri May 23 16:56:24 2008
@@ -0,0 +1,101 @@
+#define _GNU_SOURCE
+
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "xmlrpc_config.h"
+#include "xmlrpc-c/string_int.h"
+
+
+
+const char *
+xmlrpc_makePrintable_lp(const char * const input,
+ size_t const inputLength) {
+/*----------------------------------------------------------------------------
+ Convert an arbitrary string of characters in length-pointer form to
+ printable ASCII. E.g. convert newlines to "\n".
+
+ Return the result in newly malloc'ed storage. Return NULL if we can't
+ get the storage.
+-----------------------------------------------------------------------------*/
+ char * output;
+
+ output = malloc(inputLength*4+1);
+ /* Worst case, we render a character like \x01 -- 4 characters */
+
+ if (output != NULL) {
+ unsigned int inputCursor, outputCursor;
+
+ for (inputCursor = 0, outputCursor = 0;
+ inputCursor < inputLength;
+ ++inputCursor) {
+
+ if (0) {
+ } else if (input[inputCursor] == '\\') {
+ output[outputCursor++] = '\\';
+ output[outputCursor++] = '\\';
+ } else if (input[inputCursor] == '\n') {
+ output[outputCursor++] = '\\';
+ output[outputCursor++] = 'n';
+ } else if (input[inputCursor] == '\t') {
+ output[outputCursor++] = '\\';
+ output[outputCursor++] = 't';
+ } else if (input[inputCursor] == '\a') {
+ output[outputCursor++] = '\\';
+ output[outputCursor++] = 'a';
+ } else if (input[inputCursor] == '\r') {
+ output[outputCursor++] = '\\';
+ output[outputCursor++] = 'r';
+ } else if (isprint(input[inputCursor])) {
+ output[outputCursor++] = input[inputCursor];
+ } else {
+ snprintf(&output[outputCursor], 5, "\\x%02x",
+ input[inputCursor]);
+ outputCursor += 4;
+ }
+ }
+ output[outputCursor++] = '\0';
+ }
+ return output;
+}
+
+
+
+const char *
+xmlrpc_makePrintable(const char * const input) {
+/*----------------------------------------------------------------------------
+ Convert an arbitrary string of characters (NUL-terminated, though) to
+ printable ASCII. E.g. convert newlines to "\n".
+
+ Return the result in newly malloc'ed storage. Return NULL if we can't
+ get the storage.
+-----------------------------------------------------------------------------*/
+ return xmlrpc_makePrintable_lp(input, strlen(input));
+}
+
+
+
+const char *
+xmlrpc_makePrintableChar(char const input) {
+/*----------------------------------------------------------------------------
+ Return an ASCIIZ string consisting of the character 'input',
+ properly escaped so as to be printable. E.g., in C notation, '\n'
+ turns into "\\n"
+-----------------------------------------------------------------------------*/
+ const char * retval;
+
+ if (input == '\0')
+ retval = strdup("\\0");
+ else {
+ char buffer[2];
+
+ buffer[0] = input;
+ buffer[1] = '\0';
+
+ retval = xmlrpc_makePrintable(buffer);
+ }
+ return retval;
+}
Added: freeswitch/trunk/libs/xmlrpc-c/lib/libutil/memblock.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/libutil/memblock.c Fri May 23 16:56:24 2008
@@ -0,0 +1,214 @@
+/* Copyright information is at end of file */
+#include "xmlrpc_config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "xmlrpc-c/util_int.h"
+#include "xmlrpc-c/util.h"
+
+#ifdef EFENCE
+ /* when looking for corruption don't allocate extra slop */
+#define BLOCK_ALLOC_MIN (1)
+#else
+#define BLOCK_ALLOC_MIN (16)
+#endif
+#define BLOCK_ALLOC_MAX (128 * 1024 * 1024)
+
+
+xmlrpc_mem_block *
+xmlrpc_mem_block_new(xmlrpc_env * const env,
+ size_t const size) {
+
+ xmlrpc_mem_block* block;
+
+ XMLRPC_ASSERT_ENV_OK(env);
+
+ block = (xmlrpc_mem_block*) malloc(sizeof(xmlrpc_mem_block));
+ XMLRPC_FAIL_IF_NULL(block, env, XMLRPC_INTERNAL_ERROR,
+ "Can't allocate memory block");
+
+ xmlrpc_mem_block_init(env, block, size);
+ XMLRPC_FAIL_IF_FAULT(env);
+
+ cleanup:
+ if (env->fault_occurred) {
+ if (block)
+ free(block);
+ return NULL;
+ } else {
+ return block;
+ }
+}
+
+/* Destroy an existing xmlrpc_mem_block, and everything it contains. */
+void
+xmlrpc_mem_block_free(xmlrpc_mem_block * const blockP) {
+
+ XMLRPC_ASSERT(blockP != NULL);
+ XMLRPC_ASSERT(blockP->_block != NULL);
+
+ xmlrpc_mem_block_clean(blockP);
+ free(blockP);
+}
+
+
+
+/* Initialize the contents of the provided xmlrpc_mem_block. */
+void
+xmlrpc_mem_block_init(xmlrpc_env * const envP,
+ xmlrpc_mem_block * const blockP,
+ size_t const size) {
+
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT(blockP != NULL);
+
+ blockP->_size = size;
+ if (size < BLOCK_ALLOC_MIN)
+ blockP->_allocated = BLOCK_ALLOC_MIN;
+ else
+ blockP->_allocated = size;
+
+ blockP->_block = (void*) malloc(blockP->_allocated);
+ if (!blockP->_block)
+ xmlrpc_faultf(envP, "Can't allocate %u-byte memory block",
+ blockP->_allocated);
+}
+
+
+
+/* Deallocate the contents of the provided xmlrpc_mem_block, but not
+ the block itself.
+*/
+void
+xmlrpc_mem_block_clean(xmlrpc_mem_block * const blockP) {
+
+ XMLRPC_ASSERT(blockP != NULL);
+ XMLRPC_ASSERT(blockP->_block != NULL);
+
+ free(blockP->_block);
+ blockP->_block = XMLRPC_BAD_POINTER;
+}
+
+
+
+/* Get the size of the xmlrpc_mem_block. */
+size_t
+xmlrpc_mem_block_size(const xmlrpc_mem_block * const blockP) {
+
+ XMLRPC_ASSERT(blockP != NULL);
+ return blockP->_size;
+}
+
+
+
+/* Get the contents of the xmlrpc_mem_block. */
+void *
+xmlrpc_mem_block_contents(const xmlrpc_mem_block * const blockP) {
+
+ XMLRPC_ASSERT(blockP != NULL);
+ return blockP->_block;
+}
+
+
+
+/* Resize an xmlrpc_mem_block, preserving as much of the contents as
+ possible.
+*/
+void
+xmlrpc_mem_block_resize (xmlrpc_env * const envP,
+ xmlrpc_mem_block * const blockP,
+ size_t const size) {
+
+ size_t proposed_alloc;
+ void* new_block;
+
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT(blockP != NULL);
+
+ /* Check to see if we already have enough space. Maybe we'll get lucky. */
+ if (size <= blockP->_allocated) {
+ blockP->_size = size;
+ return;
+ }
+
+ /* Calculate a new allocation size. */
+#ifdef EFENCE
+ proposed_alloc = size;
+#else
+ proposed_alloc = blockP->_allocated;
+ while (proposed_alloc < size && proposed_alloc <= BLOCK_ALLOC_MAX)
+ proposed_alloc *= 2;
+#endif /* DEBUG_MEM_ERRORS */
+
+ if (proposed_alloc > BLOCK_ALLOC_MAX)
+ XMLRPC_FAIL(envP, XMLRPC_INTERNAL_ERROR, "Memory block too large");
+
+ /* Allocate our new memory block. */
+ new_block = (void*) malloc(proposed_alloc);
+ XMLRPC_FAIL_IF_NULL(new_block, envP, XMLRPC_INTERNAL_ERROR,
+ "Can't resize memory block");
+
+ /* Copy over our data and update the xmlrpc_mem_block struct. */
+ memcpy(new_block, blockP->_block, blockP->_size);
+ free(blockP->_block);
+ blockP->_block = new_block;
+ blockP->_size = size;
+ blockP->_allocated = proposed_alloc;
+
+ cleanup:
+ return;
+}
+
+
+
+void
+xmlrpc_mem_block_append(xmlrpc_env * const envP,
+ xmlrpc_mem_block * const blockP,
+ const void * const data,
+ size_t const len) {
+
+ int size;
+
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT(blockP != NULL);
+
+ size = blockP->_size;
+ xmlrpc_mem_block_resize(envP, blockP, size + len);
+ XMLRPC_FAIL_IF_FAULT(envP);
+
+ memcpy(((unsigned char*) blockP->_block) + size, data, len);
+
+ cleanup:
+ return;
+}
+
+
+
+/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR 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.
+*/
Added: freeswitch/trunk/libs/xmlrpc-c/lib/libutil/select.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/libutil/select.c Fri May 23 16:56:24 2008
@@ -0,0 +1,59 @@
+#define _XOPEN_SOURCE 600 /* Get pselect() in <sys/select.h> */
+
+#ifdef WIN32
+#include <winsock.h>
+#else
+/* In some systems (SUS), the select() interface comes from <sys/time.h>;
+ in others, from <sys/select.h>, and other from both. Including both
+ in this order appears to work on all.
+*/
+#include <sys/time.h>
+#include <sys/select.h>
+#endif
+#include <signal.h>
+
+#include "xmlrpc_config.h"
+
+#include "xmlrpc-c/select_int.h"
+
+
+/* xmlrpc_pselect() is just for use with sockets. In a POSIX system,
+ it technically works for any file descriptor, but in Windows, select()
+ is part of the socket facility.
+*/
+
+int
+xmlrpc_pselect(int const n,
+ fd_set * const readfdsP,
+ fd_set * const writefdsP,
+ fd_set * const exceptfdsP,
+ const xmlrpc_timespec * const timeoutP,
+ sigset_t * const sigmaskP) {
+
+ int retval;
+
+#if HAVE_PSELECT
+#if !HAVE_TIMESPEC
+ #error "Impossible configuration -- has pselect(), but not struct timespec"
+#else
+ retval = pselect(n, readfdsP, writefdsP, exceptfdsP, timeoutP, sigmaskP);
+#endif
+#else /* HAVE_PSELECT */
+ struct timeval timeout;
+
+ timeout.tv_sec = timeoutP->tv_sec;
+ timeout.tv_usec = timeoutP->tv_nsec/1000;
+#ifdef WIN32
+ retval = select(n, readfdsP, writefdsP, exceptfdsP, &timeout);
+#else
+ {
+ sigset_t origmask;
+ sigprocmask(SIG_SETMASK, sigmaskP, &origmask);
+ retval = select(n, readfdsP, writefdsP, exceptfdsP, &timeout);
+ sigprocmask(SIG_SETMASK, &origmask, NULL);
+ }
+#endif
+#endif
+
+ return retval;
+}
Added: freeswitch/trunk/libs/xmlrpc-c/lib/libutil/sleep.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/libutil/sleep.c Fri May 23 16:56:24 2008
@@ -0,0 +1,21 @@
+#include "bool.h"
+
+#include "xmlrpc-c/sleep_int.h"
+
+#ifdef WIN32
+#include <windows.h>
+#include <process.h>
+#else
+#include <unistd.h>
+#endif
+
+
+void
+xmlrpc_millisecond_sleep(unsigned int const milliseconds) {
+
+#ifdef WIN32
+ SleepEx(milliseconds, true);
+#else
+ usleep(milliseconds * 1000);
+#endif
+}
Added: freeswitch/trunk/libs/xmlrpc-c/lib/libutil/time.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/libutil/time.c Fri May 23 16:56:24 2008
@@ -0,0 +1,173 @@
+#include "xmlrpc_config.h"
+#include <assert.h>
+#include <time.h>
+
+#if !MSVCRT
+#include <sys/time.h>
+#endif
+
+#if MSVCRT
+#include <windows.h>
+#endif
+
+#include "xmlrpc-c/string_int.h"
+#include "xmlrpc-c/time_int.h"
+
+
+/* A note about struct timeval and Windows: There is a 'struct
+ timeval' type in Windows, but it is just an argument to select(),
+ which is just part of the sockets interface. It's defined
+ identically to the POSIX type of the same name, but not meant for
+ general timekeeping as the POSIX type is.
+*/
+
+#if HAVE_GETTIMEOFDAY
+static void
+gettimeofdayPosix(xmlrpc_timespec * const todP) {
+
+ struct timeval tv;
+
+ gettimeofday(&tv, NULL);
+
+ todP->tv_sec = tv.tv_sec;
+ todP->tv_nsec = tv.tv_usec * 1000;
+}
+#endif
+
+
+
+#if MSVCRT
+static void
+gettimeofdayWindows(xmlrpc_timespec * const todP) {
+
+ __int64 const epochOffset = 116444736000000000i64;
+ /* Number of 100-nanosecond units between the beginning of the
+ Windows epoch (Jan. 1, 1601) and the Unix epoch (Jan. 1, 1970).
+ */
+ FILETIME ft;
+ LARGE_INTEGER li;
+ __int64 t;
+
+ GetSystemTimeAsFileTime(&ft);
+ li.LowPart = ft.dwLowDateTime;
+ li.HighPart = ft.dwHighDateTime;
+ t = (li.QuadPart - epochOffset) * 100; /* nanoseconds */
+ todP->tv_sec = (long)(t / 1E9);
+ todP->tv_nsec = (long)(t - (__int64)todP->tv_sec * 1E9);
+}
+#endif
+
+
+
+void
+xmlrpc_gettimeofday(xmlrpc_timespec * const todP) {
+
+ assert(todP);
+
+#if HAVE_GETTIMEOFDAY
+ gettimeofdayPosix(todP);
+#else
+#if MSVCRT
+ gettimeofdayWindows(todP);
+#else
+ #error "We don't know how to get the time of day on this system"
+#endif
+#endif /* HAVE_GETTIMEOFDAY */
+}
+
+
+
+static bool
+isLeapYear(unsigned int const yearOfAd) {
+
+ return
+ (yearOfAd % 4) == 0 &&
+ ((yearOfAd % 100) != 0 || (yearOfAd % 400) == 0);
+}
+
+
+
+void
+xmlrpc_timegm(const struct tm * const tmP,
+ time_t * const timeValueP,
+ const char ** const errorP) {
+/*----------------------------------------------------------------------------
+ This does what GNU libc's timegm() does.
+-----------------------------------------------------------------------------*/
+ if (tmP->tm_year < 70 ||
+ tmP->tm_mon > 11 ||
+ tmP->tm_mon < 0 ||
+ tmP->tm_mday > 31 ||
+ tmP->tm_min > 60 ||
+ tmP->tm_sec > 60 ||
+ tmP->tm_hour > 24) {
+
+ xmlrpc_asprintf(errorP, "Invalid time specification; a member "
+ "of struct tm is out of range");
+ } else {
+ static unsigned int const monthDaysNonLeap[12] =
+ {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+ unsigned int totalDays;
+ unsigned int year;
+ unsigned int month;
+
+ totalDays = 0; /* initial value */
+
+ for (year = 70; year < (unsigned int)tmP->tm_year; ++year)
+ totalDays += isLeapYear(1900 + year) ? 366 : 365;
+
+ for (month = 0; month < (unsigned int)tmP->tm_mon; ++month)
+ totalDays += monthDaysNonLeap[month];
+
+ if (tmP->tm_mon > 1 && isLeapYear(1900 + tmP->tm_year))
+ totalDays += 1;
+
+ totalDays += tmP->tm_mday - 1;
+
+ *errorP = NULL;
+
+ *timeValueP = ((totalDays * 24 +
+ tmP->tm_hour) * 60 +
+ tmP->tm_min) * 60 +
+ tmP->tm_sec;
+ }
+}
+
+
+
+void
+xmlrpc_localtime(time_t const datetime,
+ struct tm * const tmP) {
+/*----------------------------------------------------------------------------
+ Convert datetime from standard to broken-down format in the local
+ time zone.
+
+ For Windows, this is not thread-safe. If you run a version of Abyss
+ with multiple threads, you can get arbitrary results here.
+-----------------------------------------------------------------------------*/
+#if HAVE_LOCALTIME_R
+ localtime_r(&datetime, tmP);
+#else
+ *tmP = *localtime(&datetime);
+#endif
+}
+
+
+
+void
+xmlrpc_gmtime(time_t const datetime,
+ struct tm * const resultP) {
+/*----------------------------------------------------------------------------
+ Convert datetime from standard to broken-down UTC format.
+
+ For Windows, this is not thread-safe. If you run a version of Abyss
+ with multiple threads, you can get arbitrary results here.
+-----------------------------------------------------------------------------*/
+
+#if HAVE_GMTIME_R
+ gmtime_r(&datetime, resultP);
+#else
+ *resultP = *gmtime(&datetime);
+#endif
+}
Added: freeswitch/trunk/libs/xmlrpc-c/lib/libutil/utf8.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/libutil/utf8.c Fri May 23 16:56:24 2008
@@ -0,0 +1,511 @@
+/* Copyright (C) 2001 by Eric Kidd. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR 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. */
+
+
+/*=========================================================================
+** XML-RPC UTF-8 Utilities
+**=========================================================================
+** Routines for validating, encoding and decoding UTF-8 data. We try to
+** be very, very strict about invalid UTF-8 data.
+**
+** All of the code in this file assumes that your machine represents
+** wchar_t as a 16-bit (or wider) character containing UCS-2 data. If this
+** assumption is incorrect, you may need to replace this file.
+**
+** For lots of information on Unicode and UTF-8 decoding, see:
+** http://www.cl.cam.ac.uk/~mgk25/unicode.html
+*/
+
+#include "int.h"
+
+#include "xmlrpc_config.h"
+#include "bool.h"
+#include "xmlrpc-c/base.h"
+
+/*=========================================================================
+** Tables and Constants
+**=========================================================================
+** We use a variety of tables and constants to help decode and validate
+** UTF-8 data.
+*/
+
+/* The number of bytes in a UTF-8 sequence starting with the character used
+** as the array index. A zero entry indicates an illegal initial byte.
+** This table was generated using a Perl script and information from the
+** UTF-8 standard.
+**
+** Fredrik Lundh's UTF-8 decoder Python 2.0 uses a similar table. But
+** since Python 2.0 has the icky CNRI license, I regenerated this
+** table from scratch and wrote my own decoder. */
+static unsigned char utf8_seq_length[256] = {
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 0, 0
+};
+
+/* The minimum legal character value for a UTF-8 sequence of the given
+** length. We have to check this to avoid accepting "overlong" UTF-8
+** sequences, which use more bytes than necessary to encode a given
+** character. Such sequences are commonly used by evil people to bypass
+** filters and security checks. This table is based on the UTF-8-test.txt
+** file by Markus Kuhn <mkuhn at acm.org>. */
+static uint32_t const utf8_min_char_for_length[] = {
+ 0, /* Length 0: Not used (meaningless) */
+ 0x0000, /* Length 1: Not used (special-cased) */
+ 0x0080, /* Length 2 */
+ 0x0800, /* Length 3 */
+ 0x00010000, /* Length 4 */
+ 0x00200000, /* Length 5 */
+ 0x04000000 /* Length 6 */
+};
+
+/* This is the maximum legal 16-byte (UCS-2) character. Again, this
+** information is based on UTF-8-test.txt. */
+#define UCS2_MAX_LEGAL_CHARACTER (0xFFFD)
+
+/* First and last UTF-16 surrogate characters. These are *not* legal UCS-2
+** characters--they're used to code for UCS-4 characters when using
+** UTF-16. They should never appear in decoded UTF-8 data! Again, these
+** could hypothetically be used to bypass security measures on some machines.
+** Based on UTF-8-test.txt. */
+#define UTF16_FIRST_SURROGATE (0xD800)
+#define UTF16_LAST_SURROGATE (0xDFFF)
+
+/* Is the character 'c' a UTF-8 continuation character? */
+#define IS_CONTINUATION(c) (((c) & 0xC0) == 0x80)
+
+#define MAX_ENCODED_BYTES (3)
+ /* Maximum number of bytes needed to encode in UTF-8 a character
+ in the Basic Multilingual Plane.
+ */
+
+
+#if HAVE_UNICODE_WCHAR
+
+
+static void
+decode_utf8(xmlrpc_env * const envP,
+ const char * const utf8_data,
+ size_t const utf8_len,
+ wchar_t * const ioBuff,
+ size_t * const outBuffLenP) {
+/*----------------------------------------------------------------------------
+ Decode to UCS-2 (or validates as UTF-8 that can be decoded to UCS-2)
+ a UTF-8 string. To validate, set ioBuff and outBuffLenP to NULL.
+ To decode, allocate a sufficiently large buffer, pass it as ioBuff,
+ and pass a pointer as as outBuffLenP. The data will be written to
+ the buffer, and the length to outBuffLenP.
+
+ We assume that wchar_t holds a single UCS-2 character in native-endian
+ byte ordering.
+-----------------------------------------------------------------------------*/
+ size_t i, length, out_pos;
+ char init, con1, con2;
+ wchar_t wc;
+
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT_PTR_OK(utf8_data);
+ XMLRPC_ASSERT((!ioBuff && !outBuffLenP) ||
+ (ioBuff && outBuffLenP));
+
+ /* Suppress GCC warning about possibly undefined variable. */
+ wc = 0;
+
+ i = 0;
+ out_pos = 0;
+ while (i < utf8_len) {
+ init = utf8_data[i];
+ if ((init & 0x80) == 0x00) {
+ /* Convert ASCII character to wide character. */
+ wc = init;
+ i++;
+ } else {
+ /* Look up the length of this UTF-8 sequence. */
+ length = utf8_seq_length[(unsigned char) init];
+
+ /* Check to make sure we have enough bytes to convert. */
+ if (i + length > utf8_len)
+ XMLRPC_FAIL(envP, XMLRPC_INVALID_UTF8_ERROR,
+ "Truncated UTF-8 sequence");
+
+ /* Decode a multibyte UTF-8 sequence. */
+ switch (length) {
+ case 0:
+ XMLRPC_FAIL(envP, XMLRPC_INVALID_UTF8_ERROR,
+ "Invalid UTF-8 initial byte");
+
+ case 2:
+ /* 110xxxxx 10xxxxxx */
+ con1 = utf8_data[i+1];
+ if (!IS_CONTINUATION(con1))
+ XMLRPC_FAIL(envP, XMLRPC_INVALID_UTF8_ERROR,
+ "UTF-8 sequence too short");
+ wc = ((((wchar_t) (init & 0x1F)) << 6) |
+ (((wchar_t) (con1 & 0x3F))));
+ break;
+
+ case 3:
+ /* 1110xxxx 10xxxxxx 10xxxxxx */
+ con1 = utf8_data[i+1];
+ con2 = utf8_data[i+2];
+ if (!IS_CONTINUATION(con1) || !IS_CONTINUATION(con2))
+ XMLRPC_FAIL(envP, XMLRPC_INVALID_UTF8_ERROR,
+ "UTF-8 sequence too short");
+ wc = ((((wchar_t) (init & 0x0F)) << 12) |
+ (((wchar_t) (con1 & 0x3F)) << 6) |
+ (((wchar_t) (con2 & 0x3F))));
+ break;
+
+ case 4:
+ /* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
+ case 5:
+ /* 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx */
+ case 6:
+ /* 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx */
+ /* This would require more than 16 bits in UTF-16, so
+ it can't be represented in UCS-2, so it's beyond
+ our capability. Characters in the BMP fit in 16
+ bits.
+ */
+ xmlrpc_env_set_fault_formatted(
+ envP, XMLRPC_INVALID_UTF8_ERROR,
+ "UTF-8 string contains a character not in the "
+ "Basic Multilingual Plane (first byte %08x)",
+ init);
+ goto cleanup;
+
+ default:
+ XMLRPC_ASSERT("Error in UTF-8 decoder tables");
+ }
+
+ /* Advance to the end of the sequence. */
+ i += length;
+
+ /* Check for illegal UCS-2 characters. */
+ if (wc > UCS2_MAX_LEGAL_CHARACTER)
+ XMLRPC_FAIL(envP, XMLRPC_INVALID_UTF8_ERROR,
+ "UCS-2 characters > U+FFFD are illegal");
+
+ /* Check for UTF-16 surrogates. */
+ if (UTF16_FIRST_SURROGATE <= wc && wc <= UTF16_LAST_SURROGATE)
+ XMLRPC_FAIL(envP, XMLRPC_INVALID_UTF8_ERROR,
+ "UTF-16 surrogates may not appear in UTF-8 data");
+
+ /* Check for overlong sequences. */
+ if ((uint32_t)wc < utf8_min_char_for_length[length])
+ XMLRPC_FAIL(envP, XMLRPC_INVALID_UTF8_ERROR,
+ "Overlong UTF-8 sequence not allowed");
+ }
+
+ /* If we have a buffer, write our character to it. */
+ if (ioBuff) {
+ ioBuff[out_pos++] = wc;
+ }
+ }
+
+ /* Record the number of characters we found. */
+ if (outBuffLenP)
+ *outBuffLenP = out_pos;
+
+ cleanup:
+ if (envP->fault_occurred) {
+ if (outBuffLenP)
+ *outBuffLenP = 0;
+ }
+}
+
+
+
+void
+xmlrpc_validate_utf8(xmlrpc_env * const env,
+ const char * const utf8_data,
+ size_t const utf8_len) {
+/*----------------------------------------------------------------------------
+ Validate that a string is valid UTF-8.
+-----------------------------------------------------------------------------*/
+
+ decode_utf8(env, utf8_data, utf8_len, NULL, NULL);
+}
+
+
+
+xmlrpc_mem_block *
+xmlrpc_utf8_to_wcs(xmlrpc_env * const envP,
+ const char * const utf8_data,
+ size_t const utf8_len) {
+/*----------------------------------------------------------------------------
+ Decode UTF-8 string to a "wide character string". This function
+ returns an xmlrpc_mem_block with an element type of wchar_t. Don't
+ try to intepret the block in a bytewise fashion--it won't work in
+ any useful or portable fashion.
+
+ For backward compatibility, we return a meaningful value even when we
+ fail. We return NULL when we fail.
+-----------------------------------------------------------------------------*/
+ xmlrpc_mem_block * wcsP;
+ size_t wcs_length;
+
+ /* Allocate a memory block large enough to hold any possible output.
+ We assume that each byte of the input may decode to a whcar_t.
+ */
+ wcsP = XMLRPC_MEMBLOCK_NEW(wchar_t, envP, utf8_len);
+ if (!envP->fault_occurred) {
+ /* Decode the UTF-8 data. */
+ decode_utf8(envP, utf8_data, utf8_len,
+ XMLRPC_MEMBLOCK_CONTENTS(wchar_t, wcsP),
+ &wcs_length);
+ if (!envP->fault_occurred) {
+ /* We can't have overrun our buffer. */
+ XMLRPC_ASSERT(wcs_length <= utf8_len);
+
+ /* Correct the length of the memory block. */
+ XMLRPC_MEMBLOCK_RESIZE(wchar_t, envP, wcsP, wcs_length);
+ }
+ if (envP->fault_occurred)
+ XMLRPC_MEMBLOCK_FREE(wchar_t, wcsP);
+ }
+ if (envP->fault_occurred)
+ return NULL;
+ else
+ return wcsP;
+}
+
+
+
+xmlrpc_mem_block *
+xmlrpc_wcs_to_utf8(xmlrpc_env * const envP,
+ const wchar_t * const wcs_data,
+ size_t const wcs_len) {
+/*----------------------------------------------------------------------------
+ Encode a "wide character string" as UTF-8.
+
+ For backward compatibility, we return a meaningful value even when we
+ fail. We return NULL when we fail.
+-----------------------------------------------------------------------------*/
+ size_t const estimate = wcs_len * MAX_ENCODED_BYTES;
+ /* Our conservative estimate of how big the output will be;
+ i.e. we know it won't be larger than this. For the estimate,
+ we assume that every wchar might encode to the maximum length.
+ */
+ xmlrpc_mem_block * utf8P;
+
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT_PTR_OK(wcs_data);
+
+ utf8P = XMLRPC_MEMBLOCK_NEW(char, envP, estimate);
+ if (!envP->fault_occurred) {
+ unsigned char * const buffer = XMLRPC_MEMBLOCK_CONTENTS(char, utf8P);
+ size_t bytesUsed;
+ size_t i;
+
+ bytesUsed = 0;
+ for (i = 0; i < wcs_len && !envP->fault_occurred; ++i) {
+ wchar_t const wc = wcs_data[i];
+ if (wc <= 0x007F)
+ buffer[bytesUsed++] = wc & 0x7F;
+ else if (wc <= 0x07FF) {
+ /* 110xxxxx 10xxxxxx */
+ buffer[bytesUsed++] = 0xC0 | (wc >> 6);
+ buffer[bytesUsed++] = 0x80 | (wc & 0x3F);
+ } else if (wc <= 0xFFFF) {
+ /* 1110xxxx 10xxxxxx 10xxxxxx */
+ buffer[bytesUsed++] = 0xE0 | (wc >> 12);
+ buffer[bytesUsed++] = 0x80 | ((wc >> 6) & 0x3F);
+ buffer[bytesUsed++] = 0x80 | (wc & 0x3F);
+ } else
+ xmlrpc_faultf(envP,
+ "Don't know how to encode UCS-4 characters yet");
+ }
+ if (!envP->fault_occurred) {
+ XMLRPC_ASSERT(bytesUsed <= estimate);
+
+ XMLRPC_MEMBLOCK_RESIZE(char, envP, utf8P, bytesUsed);
+ }
+ if (envP->fault_occurred)
+ XMLRPC_MEMBLOCK_FREE(char, utf8P);
+ }
+
+ if (envP->fault_occurred)
+ return NULL;
+ else
+ return utf8P;
+}
+
+
+
+#else /* HAVE_UNICODE_WCHAR */
+
+xmlrpc_mem_block *
+xmlrpc_utf8_to_wcs(xmlrpc_env * const envP,
+ const char * const utf8_data ATTR_UNUSED,
+ size_t const utf8_len ATTR_UNUSED) {
+
+ xmlrpc_faultf(envP, "INTERNAL ERROR: xmlrpc_utf8_to_wcs() called "
+ "on a system that doesn't do Unicode!");
+
+ return NULL;
+}
+#endif /* HAVE_UNICODE_WCHAR */
+
+
+void
+xmlrpc_force_to_utf8(char * const buffer) {
+/*----------------------------------------------------------------------------
+ Force the contents of 'buffer' to be valid UTF-8, any way possible.
+ The buffer ends with a NUL character, and the mutation does not make
+ it longer.
+
+ The most common reason for a string that's supposed to be UTF-8 not
+ to be UTF-8 is that it was supposed to be ASCII but instead
+ includes garbage with the high bit on (ASCII characters always have
+ the high bit off), or maybe a primitive 8-bit ASCII extension.
+ Therefore, we force it to UTF-8 by replacing some bytes that have
+ the high bit set with DEL (0x7F). That would leave the other
+ characters meaningful.
+-----------------------------------------------------------------------------*/
+ char * p;
+
+ for (p = &buffer[0]; *p;) {
+ uint const length = utf8_seq_length[(unsigned char) *p];
+
+ bool forceDel;
+ uint32_t decoded;
+
+ forceDel = false;
+ decoded = 0; /* suppress compiler warning; valid when !forceDel */
+
+ switch (length) {
+ case 1:
+ /* One-byte UTF-8 characters are easy. */
+ decoded = *p;
+ break;
+ case 2:
+ /* 110xxxxx 10xxxxxx */
+ if (!*(p+1) || !(*p+2))
+ forceDel = true;
+ else if (!IS_CONTINUATION(*(p+1)))
+ forceDel = true;
+ else
+ decoded =
+ ((uint32_t)(*(p+0) & 0x1F) << 6) |
+ ((uint32_t)(*(p+1) & 0x3F) << 0);
+ break;
+ case 3:
+ /* 1110xxxx 10xxxxxx 10xxxxxx */
+ if (!*(p+1) || !(*p+2) || !(*p+3))
+ forceDel = true;
+ else if (!IS_CONTINUATION(*(p+1)) || !IS_CONTINUATION(*(p+2)))
+ forceDel = true;
+ else
+ decoded =
+ ((uint32_t)(*(p+0) & 0x0F) << 12) |
+ ((uint32_t)(*(p+1) & 0x3F) << 6) |
+ ((uint32_t)(*(p+2) & 0x3F) << 0);
+ break;
+ default:
+ forceDel = true;
+ }
+
+ if (!forceDel) {
+ if (decoded > UCS2_MAX_LEGAL_CHARACTER)
+ forceDel = true;
+ else if (UTF16_FIRST_SURROGATE <= decoded &&
+ decoded <= UTF16_LAST_SURROGATE)
+ forceDel = true;
+ else if (decoded < utf8_min_char_for_length[length])
+ forceDel = true;
+ }
+
+ if (forceDel) {
+ /* Not a valid UTF-8 character, so replace the first byte
+ with a nice simple ASCII DEL.
+ */
+ *p = 0x7F;
+ p += 1;
+ } else
+ p += length;
+ }
+}
+
+
+
+void
+xmlrpc_force_to_xml_chars(char * const buffer) {
+/*----------------------------------------------------------------------------
+ Modify 'buffer' so that it contains nothing but valid XML
+ characters. The buffer ends with a NUL character, and the mutation
+ does not make it longer.
+
+ Note that the valid characters in an XML document are all Unicode
+ codepoints except the ASCII control characters, plus CR, LF, and
+ Tab.
+
+ We change all non-XML characters to DEL (0x7F).
+
+ Assume input is valid UTF-8.
+-----------------------------------------------------------------------------*/
+ char * p;
+
+ for (p = &buffer[0]; *p;) {
+ uint const length = utf8_seq_length[(unsigned char) *p];
+
+ if (length == 1) {
+ if (*p < 0x20 && *p != '\r' && *p != '\n' && *p != '\t')
+ /* Not valid XML. Force to DEL */
+ *p = 0x7f;
+ } else {
+ /* We assume here that all other UTF-8 characters are
+ valid XML, but it's apparently not actually true.
+ */
+ }
+
+ {
+ unsigned int i;
+ /* Advance to next UTF-8 character */
+ for (i = 0; i < length && *p; ++i)
+ ++p;
+ }
+ }
+}
+
+
+
+
+
+
+
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/libwww_transport/Makefile
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/libwww_transport/Makefile (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/libwww_transport/Makefile Fri May 23 16:56:24 2008
@@ -1,22 +1,38 @@
-ifeq ($(SRCDIR)x,x)
-SRCDIR = $(CURDIR)/../..
+ifeq ($(SRCDIR),)
+ updir = $(shell echo $(dir $(1)) | sed 's/.$$//')
+ LIBDIR := $(call updir,$(CURDIR))
+ SRCDIR := $(call updir,$(LIBDIR))
+ BLDDIR := $(SRCDIR)
endif
+SUBDIR := lib/libwww_transport
-include $(SRCDIR)/Makefile.config
+include $(BLDDIR)/config.mk
+
+default: all
+
+.PHONY: all
+all: xmlrpc_libwww_transport.o xmlrpc_libwww_transport.osh
+
+# Rules for the above dependencies are in common.mk,
+# courtesy of TARGET_MODS.
+
+TARGET_MODS = xmlrpc_libwww_transport
+
+OMIT_LIBWWW_TRANSPORT_RULE=Y
+
+include $(SRCDIR)/common.mk
LIBWWW_INCLUDES := $(shell libwww-config --cflags)
CFLAGS = $(CFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD)
-LDFLAGS = -lpthread $(LADD)
-INCLUDES = -I$(SRCDIR) -I$(SRCDIR)/include -I$(SRCDIR)/lib/util/include \
+INCLUDES = \
+ -I$(BLDDIR) \
+ -I$(BLDDIR)/include \
+ -I$(SRCDIR)/include \
+ -I$(SRCDIR)/lib/util/include \
$(LIBWWW_INCLUDES)
-default: all
-
-.PHONY: all
-all: xmlrpc_libwww_transport.lo
-
.PHONY: clean
clean: clean-common
@@ -35,11 +51,8 @@
.PHONY: dep
dep: dep-common
-include $(SRCDIR)/Makefile.common
-
include Makefile.depend
-xmlrpc_libwww_transport.lo:%.lo:%.c
- $(LIBTOOL) --mode=compile $(CC) -c $(INCLUDES) $(CFLAGS) $<
-
-
+# Need this dependency for those who don't use Makefile.depend.
+# Without it, version.h doesn't get created.
+xmlrpc_libwww_transport.o xmlrpc_libwww_transport.osh: version.h
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/libwww_transport/xmlrpc_libwww_transport.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/libwww_transport/xmlrpc_libwww_transport.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/libwww_transport/xmlrpc_libwww_transport.c Fri May 23 16:56:24 2008
@@ -29,10 +29,10 @@
#include "bool.h"
#include "mallocvar.h"
-#include "xmlrpc-c/base.h"
-#include "xmlrpc-c/base_int.h"
-#include "xmlrpc-c/client.h"
+
+#include "xmlrpc-c/string_int.h"
#include "xmlrpc-c/client_int.h"
+#include "xmlrpc-c/transport.h"
/* The libwww interface */
@@ -53,8 +53,6 @@
#include "WWWSSL.h"
#endif
-#include "xmlrpc_libwww_transport.h"
-
/* This value was discovered by Rick Blair. His efforts shaved two seconds
** off of every request processed. Many thanks. */
#define SMALLEST_LEGAL_LIBWWW_TIMEOUT (21)
@@ -86,10 +84,10 @@
int http_status;
/* Low-level information used by libwww. */
- HTRequest *request;
- HTChunk *response_data;
- HTParentAnchor *source_anchor;
- HTAnchor *dest_anchor;
+ HTRequest * request;
+ HTChunk * response_data;
+ HTParentAnchor * source_anchor;
+ HTAnchor * dest_anchor;
xmlrpc_transport_asynch_complete complete;
struct xmlrpc_call_info * callInfoP;
@@ -119,8 +117,11 @@
const char * const appversion) {
/* We initialize the library using a robot profile, because we don't
- ** care about redirects or HTTP authentication, and we want to
- ** reduce our application footprint as much as possible. */
+ care about redirects or HTTP authentication, and we want to
+ reduce our application footprint as much as possible.
+
+ This takes the place of HTLibInit().
+ */
HTProfile_newRobot(appname, appversion);
/* Ilya Goldberg <igg at mit.edu> provided the following code to access
@@ -168,11 +169,16 @@
int const flags,
const char * const appname,
const char * const appversion,
- const struct xmlrpc_xportparms * const transportParmsP ATTR_UNUSED,
+ const void * const transportParmsP ATTR_UNUSED,
size_t const parm_size ATTR_UNUSED,
struct xmlrpc_client_transport ** const handlePP) {
/*----------------------------------------------------------------------------
This does the 'create' operation for a Libwww client transport.
+
+ TODO: put 'appname' and 'appversion' in *transportParmsP and
+ deprecate the create() arguments. Reason: these are particular to
+ the Libwww transport. They're create() arguments because originally,
+ Libwww was the only transport.
-----------------------------------------------------------------------------*/
/* The Libwww transport is not re-entrant -- you can have only one
per program instance. Even if we changed the Xmlrpc-c code not
@@ -221,6 +227,7 @@
if (!(clientTransportP->saved_flags & XMLRPC_CLIENT_SKIP_LIBWWW_INIT)) {
HTProfile_delete();
+ /* This takes the place of HTLibTerminate() */
}
destroyCookieJar(clientTransportP->cookieJarP);
}
@@ -231,6 +238,44 @@
** HTTP Error Reporting
**=======================================================================*/
+static void
+formatLibwwwError(HTRequest * const requestP,
+ const char ** const msgP) {
+/*----------------------------------------------------------------------------
+ When something fails in a Libwww request, Libwww generates a stack
+ of error information (precious little information, of course, in the
+ Unix tradition) and attaches it to the request object. We make a message
+ out of that information.
+
+ We rely on Libwww's HTDialog_errorMessage() to do the bulk of the
+ formatting; we might be able to coax more information out of the request
+ if we interpreted the error stack directly.
+-----------------------------------------------------------------------------*/
+ HTList * const errStack = HTRequest_error(requestP);
+
+ if (errStack == NULL)
+ xmlrpc_asprintf(msgP, "Libwww supplied no error details");
+ else {
+ /* Get an error message from libwww. The middle three
+ parameters to HTDialog_errorMessage appear to be ignored.
+ XXX - The documentation for this API is terrible, so we may
+ be using it incorrectly.
+ */
+ const char * const msg =
+ HTDialog_errorMessage(requestP, HT_A_MESSAGE, HT_MSG_NULL,
+ "An error occurred", errStack);
+
+ if (msg == NULL)
+ xmlrpc_asprintf(msgP, "Libwww supplied some error detail, "
+ "but its HTDialog_errorMessage() subroutine "
+ "mysteriously failed to interpret it for us.");
+ else
+ *msgP = msg;
+ }
+}
+
+
+
static void
set_fault_from_http_request(xmlrpc_env * const envP,
int const status,
@@ -244,45 +289,20 @@
if (status == 200) {
/* No error. Don't set one in *envP */
} else {
- /* Get an error message from libwww. The middle three
- parameters to HTDialog_errorMessage appear to be ignored.
- XXX - The documentation for this API is terrible, so we may
- be using it incorrectly.
- */
- HTList * const errStack = HTRequest_error(requestP);
-
- if (errStack == NULL) {
- /* I think this is probably impossible, because we didn't get
- status 200, but I don't completely understand HTTP and libwww.
- */
+ const char * libwwwMsg;
+ formatLibwwwError(requestP, &libwwwMsg);
+
+ if (status == -1)
xmlrpc_env_set_fault_formatted(
envP, XMLRPC_NETWORK_ERROR,
- "HTTP error #%d occurred, but there was no additional "
- "error information supplied", status);
- } else {
- const char * const msg =
- HTDialog_errorMessage(requestP, HT_A_MESSAGE, HT_MSG_NULL,
- "An error occurred", errStack);
-
- if (msg == NULL)
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_NETWORK_ERROR,
- "HTTP error #%d occurred. Libwww's "
- "HTDialog_errorMessage() routine was mysteriously "
- "unable to interpret the additional error information, "
- "so we have none to report.", status);
- else {
- /* Set our fault. Note that this may inlcude line breaks,
- because 'msg' may. We should fix that. Formatting for
- display is none of our business at this level.
- */
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_NETWORK_ERROR,
- "HTTP error #%d occurred. libwww says %s", status, msg);
-
- xmlrpc_strfree(msg);
- }
+ "Unable to complete the HTTP request. %s", libwwwMsg);
+ else {
+ xmlrpc_env_set_fault_formatted(
+ envP, XMLRPC_NETWORK_ERROR,
+ "HTTP request completed with HTTp error %d. %s",
+ status, libwwwMsg);
}
+ xmlrpc_strfree(libwwwMsg);
}
}
@@ -400,7 +420,7 @@
HTAnchor ** const destAnchorPP,
const xmlrpc_server_info * const serverP) {
- *destAnchorPP = HTAnchor_findAddress(serverP->_server_url);
+ *destAnchorPP = HTAnchor_findAddress(serverP->serverUrl);
if (*destAnchorPP == NULL)
xmlrpc_env_set_fault_formatted(
@@ -460,9 +480,9 @@
HTRequest_setRqHd(rpcP->request, request_headers);
/* Send an authorization header if we need one. */
- if (serverP->_http_basic_auth)
+ if (serverP->allowedAuth.basic)
HTRequest_addCredentials(rpcP->request, "Authorization",
- serverP->_http_basic_auth);
+ (char *)serverP->basicAuthHdrValue);
/* Make sure there is no XML conversion handler to steal our data.
** The 'override' parameter is currently ignored by libwww, so our
@@ -509,8 +529,8 @@
rpcDestroy(rpc * const rpcP) {
XMLRPC_ASSERT_PTR_OK(rpcP);
- XMLRPC_ASSERT(rpcP->request != XMLRPC_BAD_POINTER);
- XMLRPC_ASSERT(rpcP->response_data != XMLRPC_BAD_POINTER);
+ XMLRPC_ASSERT(rpcP->request != NULL);
+ XMLRPC_ASSERT(rpcP->response_data != NULL);
/* Junji Kanemaru reports on 05.04.11 that with asynch calls, he
get a segfault, and reversing the order of deleting the request
@@ -524,9 +544,9 @@
*/
HTRequest_delete(rpcP->request);
- rpcP->request = XMLRPC_BAD_POINTER;
+ rpcP->request = NULL;
HTChunk_delete(rpcP->response_data);
- rpcP->response_data = XMLRPC_BAD_POINTER;
+ rpcP->response_data = NULL;
/* This anchor points to private data, so we're allowed to delete it. */
deleteSourceAnchor(rpcP->source_anchor);
@@ -557,6 +577,16 @@
rpc * const rpcP,
xmlrpc_mem_block ** const responseXmlPP) {
+ /* Implementation warning: A Libwww chunk has nothing to do with
+ an HTTP chunk. HTTP chunks (as in a chunked response) are not
+ visible to us; Libwww delivers the entire unchunked body to us
+ at once (we never see chunk headers and trailers). This
+ subroutine is about a Libwww chunk, which is just a memory
+ buffer. (Libwww is capable of delivering the response in a
+ number of ways other than a chunk, e.g. it can write it to a
+ file.
+ */
+
/* Check to make sure that w3c-libwww actually sent us some data.
** XXX - This may happen if libwww is shut down prematurely, believe it
** or not--we'll get a 200 OK and no data. Gag me with a bogus design
@@ -641,7 +671,7 @@
rpcP->request);
if (!ok)
xmlrpc_env_set_fault(
- envP, XMLRPC_INTERNAL_ERROR,
+ envP, XMLRPC_NETWORK_ERROR,
"Libwww HTPostAnchor() failed to start POST request");
else {
/* Run our event-processing loop. HTEventList_newLoop()
@@ -685,7 +715,7 @@
static void
register_asynch_call(void) {
XMLRPC_ASSERT(outstanding_asynch_calls >= 0);
- outstanding_asynch_calls++;
+ ++outstanding_asynch_calls;
}
@@ -694,7 +724,7 @@
unregister_asynch_call(void) {
XMLRPC_ASSERT(outstanding_asynch_calls > 0);
- outstanding_asynch_calls--;
+ --outstanding_asynch_calls;
if (outstanding_asynch_calls == 0)
HTEventList_stopLoop();
}
@@ -702,9 +732,9 @@
static int
-timer_callback(HTTimer * const timer ATTR_UNUSED,
+timer_callback(HTTimer * const timer ATTR_UNUSED,
void * const user_data ATTR_UNUSED,
- HTEventType const event) {
+ HTEventType const event ATTR_UNUSED) {
/*----------------------------------------------------------------------------
A handy timer callback which cancels the running event loop.
-----------------------------------------------------------------------------*/
@@ -900,7 +930,7 @@
rpcP->request);
if (!ok) {
unregister_asynch_call();
- xmlrpc_env_set_fault(envP, XMLRPC_INTERNAL_ERROR,
+ xmlrpc_env_set_fault(envP, XMLRPC_NETWORK_ERROR,
"Libwww (HTPostAnchor()) failed to start the "
"POST request.");
}
@@ -912,9 +942,12 @@
struct xmlrpc_client_transport_ops xmlrpc_libwww_transport_ops = {
+ NULL,
+ NULL,
&create,
&destroy,
&sendRequest,
&call,
&finishAsynch,
+ NULL,
};
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/util/Makefile
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/util/Makefile (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/util/Makefile Fri May 23 16:56:24 2008
@@ -1,23 +1,58 @@
-ifeq ($(SRCDIR)x,x)
-SRCDIR = $(CURDIR)/../..
-BUILDDIR = $(SRCDIR)
+###############################################################################
+# This directory builds object modules that provide utility functions that
+# programs can use. Not libraries, though -- just programs. The reason
+# we don't want any library to use object modules in here is that they'll
+# probably pollute the name space when users link those libraries to their
+# programs. In fact, if more than one Xmlrpc-c library includes one of these
+# modules, the libraries will conflict with each other.
+#
+# So a utility function that is to be used by libraries (and, optionally,
+# programs) should go in libxmlrpc_util. libxmlrpc_util is a prerequisite
+# for many Xmlrpc-c libraries, gets included in a program link only once,
+# and uses external symbol names that have the "xmlrpc_" prefix to avoid
+# collision with users' code.
+#
+# If we knew a portable way to link multiple object modules into one and
+# restrict the symbols exported by the whole, we could avoid this mess and
+# just link utility object modules into each Xmlrpc-c library.
+##############################################################################
+
+ifeq ($(SRCDIR),)
+ updir = $(shell echo $(dir $(1)) | sed 's/.$$//')
+ LIBDIR := $(call updir,$(CURDIR))
+ SRCDIR := $(call updir,$(LIBDIR))
+ BLDDIR := $(SRCDIR)
endif
+SUBDIR := lib/util
default: all
-include $(BUILDDIR)/Makefile.config
+include $(BLDDIR)/config.mk
-include $(SRCDIR)/Makefile.common
+OMIT_UTILS_RULE = Y
+
+include $(SRCDIR)/common.mk
+
+LIBOBJS = \
+ casprintf.o \
+ cmdline_parser.o \
+ cmdline_parser_cpp.o \
+ getoptx.o \
+ string_parser.o \
+ stripcaseeq.o \
.PHONY: all
-all: casprintf.lo cmdline_parser.lo getoptx.lo
+all: $(LIBOBJS)
-INCLUDES = -Iinclude -I$(BUILDDIR)
+INCLUDES = -I$(SRCDIR)/$(SUBDIR)/include -I$(BLDDIR)
CFLAGS = $(CFLAGS_COMMON) $(INCLUDES) $(CFLAGS_PERSONAL) $(CADD)
-%.lo:%.c
- $(LIBTOOL) --mode=compile $(CC) -c $(CFLAGS) $<
+%.o:%.c
+ $(CC) -c $(CFLAGS) $<
+
+%.o:%.cpp
+ $(CXX) -c $(CFLAGS) $<
include Makefile.depend
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/util/casprintf.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/util/casprintf.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/util/casprintf.c Fri May 23 16:56:24 2008
@@ -21,12 +21,12 @@
result = malloc(initialSize);
if (result != NULL) {
size_t bytesNeeded;
- bytesNeeded = vsnprintf(result, initialSize, fmt, varargs);
+ bytesNeeded = XMLRPC_VSNPRINTF(result, initialSize, fmt, varargs);
if (bytesNeeded > initialSize) {
free(result);
result = malloc(bytesNeeded);
if (result != NULL)
- vsnprintf(result, bytesNeeded, fmt, varargs);
+ XMLRPC_VSNPRINTF(result, bytesNeeded, fmt, varargs);
} else if (bytesNeeded == initialSize) {
if (result[initialSize-1] != '\0') {
/* This is one of those old systems where vsnprintf()
@@ -46,23 +46,31 @@
+const char * const strsol = "[Insufficient memory to build string]";
+
+
+
void
cvasprintf(const char ** const retvalP,
const char * const fmt,
va_list varargs) {
- char * retval;
+ char * string;
#if HAVE_ASPRINTF
- vasprintf(&retval, fmt, varargs);
+ vasprintf(&string, fmt, varargs);
#else
- simpleVasprintf(&retval, fmt, varargs);
+ simpleVasprintf(&string, fmt, varargs);
#endif
- *retvalP = retval;
+ if (string == NULL)
+ *retvalP = strsol;
+ else
+ *retvalP = string;
}
+
void GNU_PRINTF_ATTR(2,3)
casprintf(const char ** const retvalP, const char * const fmt, ...) {
@@ -79,5 +87,7 @@
void
strfree(const char * const string) {
- free((void *)string);
+
+ if (string != strsol)
+ free((void *)string);
}
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/util/cmdline_parser.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/util/cmdline_parser.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/util/cmdline_parser.c Fri May 23 16:56:24 2008
@@ -1,14 +1,17 @@
#include "xmlrpc_config.h" /* prereq for mallocvar.h -- defines __inline__ */
+#include <sys/types.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <limits.h>
-#include "mallocvar.h"
#include "bool.h"
+#include "int.h"
+#include "mallocvar.h"
#include "casprintf.h"
#include "getoptx.h"
+#include "string_parser.h"
#include "cmdline_parser.h"
@@ -19,9 +22,11 @@
enum optiontype type;
bool present;
union {
- unsigned int u;
- int i;
- const char * s;
+ unsigned int u;
+ int i;
+ const char * s;
+ uint64_t llu;
+ double d;
} value;
};
@@ -72,42 +77,108 @@
static void
+parseInt(enum optiontype const type,
+ const char * const optarg,
+ unsigned int * const valueUintP,
+ int * const valueIntP,
+ const char ** const errorP) {
+
+ if (optarg == NULL)
+ casprintf(errorP, "Option requires a value");
+ else if (strlen(optarg) == 0)
+ casprintf(errorP, "Numeric option value is null string");
+ else {
+ char * tailptr;
+ long const longvalue = strtol(optarg, &tailptr, 10);
+
+ if (*tailptr != '\0')
+ casprintf(errorP, "Non-numeric value "
+ "for numeric option value: '%s'", optarg);
+ else if (errno == ERANGE || longvalue > INT_MAX)
+ casprintf(errorP, "Numeric value out of range: %s", optarg);
+ else {
+ if (type == OPTTYPE_UINT) {
+ if (longvalue < 0)
+ casprintf(errorP, "Unsigned numeric value is "
+ "negative: %ld", longvalue);
+ else {
+ *errorP = NULL;
+ *valueUintP = (unsigned int) longvalue;
+ }
+ } else {
+ *errorP = NULL;
+ *valueIntP = (int) longvalue;
+ }
+ }
+ }
+}
+
+
+
+static void
+parseBinUint(const char * const optarg,
+ uint64_t * const valueP,
+ const char ** const errorP) {
+
+ if (optarg == NULL)
+ casprintf(errorP, "Option requires a value");
+ else if (strlen(optarg) == 0)
+ casprintf(errorP, "Numeric option value is null string");
+ else {
+ const char * error;
+ interpretBinUint(optarg, valueP, &error);
+
+ if (error) {
+ casprintf(errorP, "Invalid numeric option value '%s'. %s",
+ optarg, error);
+ strfree(error);
+ }
+ }
+}
+
+
+
+static void
+parseFloat(const char * const optarg,
+ double * const valueP,
+ const char ** const errorP) {
+
+ if (optarg == NULL)
+ casprintf(errorP, "Option requires a value");
+ else if (strlen(optarg) == 0)
+ casprintf(errorP, "Numeric option value is null string");
+ else {
+ char * tailptr;
+ double const doublevalue = strtod(optarg, &tailptr);
+
+ if (*tailptr != '\0')
+ casprintf(errorP, "Non-numeric value "
+ "for numeric option value: '%s'", optarg);
+ else if (errno == ERANGE)
+ casprintf(errorP, "Numeric value out of range: %s", optarg);
+ else {
+ *errorP = NULL;
+ *valueP = doublevalue;
+ }
+ }
+}
+
+
+
+static void
parseOptionValue(const char * const optarg,
struct optionDesc * const optionP,
const char ** const errorP) {
switch (optionP->type) {
+ case OPTTYPE_FLAG:
+ *errorP = NULL;
+ break;
+ case OPTTYPE_INT:
case OPTTYPE_UINT:
- case OPTTYPE_INT: {
- if (optarg == NULL)
- casprintf(errorP, "Option requires a value");
- else if (strlen(optarg) == 0)
- casprintf(errorP, "Numeric option value is null string");
- else {
- char * tailptr;
- long const longvalue = strtol(optarg, &tailptr, 10);
- if (*tailptr != '\0')
- casprintf(errorP, "Non-numeric value "
- "for numeric option value: '%s'", optarg);
- else if (errno == ERANGE || longvalue > INT_MAX)
- casprintf(errorP, "Numeric value out of range: %s", optarg);
- else {
- if (optionP->type == OPTTYPE_UINT) {
- if (longvalue < 0)
- casprintf(errorP, "Unsigned numeric value is "
- "negative: %ld", longvalue);
- else {
- *errorP = NULL;
- optionP->value.u = (unsigned int) longvalue;
- }
- } else {
- *errorP = NULL;
- optionP->value.u = (int) longvalue;
- }
- }
- }
- }
- break;
+ parseInt(optionP->type, optarg, &optionP->value.u, &optionP->value.i,
+ errorP);
+ break;
case OPTTYPE_STRING:
if (optarg == NULL)
casprintf(errorP, "Option requires a value");
@@ -116,8 +187,11 @@
optionP->value.s = strdup(optarg);
}
break;
- case OPTTYPE_FLAG:
- *errorP = NULL;
+ case OPTTYPE_BINUINT:
+ parseBinUint(optarg, &optionP->value.llu, errorP);
+ break;
+ case OPTTYPE_FLOAT:
+ parseFloat(optarg, &optionP->value.d, errorP);
break;
}
}
@@ -135,7 +209,7 @@
if (error)
casprintf(errorP, "Error in '%s' option: %s", optionP->name, error);
else
- optionP->present = TRUE;
+ optionP->present = true;
}
@@ -149,7 +223,8 @@
MALLOCARRAY(cpP->argumentArray, cpP->numArguments);
if (cpP->argumentArray == NULL) {
- fprintf(stderr, "Unable to allocate memory for argument array\n");
+ fprintf(stderr, "Unable to allocate memory for argument array "
+ "(%u arguments)\n", cpP->numArguments);
abort();
} else {
unsigned int i;
@@ -188,9 +263,9 @@
/* Set up initial assumption: No options present */
for (i = 0; i < cpP->numOptions; ++i)
- cpP->optionDescArray[i].present = FALSE;
+ cpP->optionDescArray[i].present = false;
- endOfOptions = FALSE; /* initial value */
+ endOfOptions = false; /* initial value */
while (!endOfOptions && !*errorP) {
int const opterr0 = 0;
@@ -419,6 +494,69 @@
+uint64_t
+cmd_getOptionValueBinUint(cmdlineParser const cpP,
+ const char * const name) {
+
+ struct optionDesc * const optionDescP = findOptionDesc(cpP, name);
+
+ uint64_t retval;
+
+ if (!optionDescP) {
+ fprintf(stderr, "cmdlineParser called incorrectly. "
+ "cmd_getOptionValueUint() called for undefined option '%s'\n",
+ name);
+ abort();
+ } else {
+ if (optionDescP->type != OPTTYPE_BINUINT) {
+ fprintf(stderr, "cmdlineParser called incorrectly. "
+ "cmd_getOptionValueBinUint() called for "
+ "non-OPTTYPE_BINUINT "
+ "option '%s'\n", optionDescP->name);
+ abort();
+ } else {
+ if (optionDescP->present)
+ retval = optionDescP->value.llu;
+ else
+ retval = 0;
+ }
+ }
+ return retval;
+}
+
+
+
+double
+cmd_getOptionValueFloat(cmdlineParser const cpP,
+ const char * const name) {
+
+ struct optionDesc * const optionDescP = findOptionDesc(cpP, name);
+
+ double retval;
+
+ if (!optionDescP) {
+ fprintf(stderr, "cmdlineParser called incorrectly. "
+ "cmd_getOptionValueInt() called for undefined option '%s'\n",
+ name);
+ abort();
+ } else {
+ if (optionDescP->type != OPTTYPE_FLOAT) {
+ fprintf(stderr, "cmdlineParser called incorrectly. "
+ "cmd_getOptionValueInt() called for non-float "
+ "option '%s'\n", optionDescP->name);
+ abort();
+ } else {
+ if (optionDescP->present)
+ retval = optionDescP->value.d;
+ else
+ retval = 0.0;
+ }
+ }
+ return retval;
+}
+
+
+
unsigned int
cmd_argumentCount(cmdlineParser const cpP) {
Added: freeswitch/trunk/libs/xmlrpc-c/lib/util/cmdline_parser_cpp.cpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/util/cmdline_parser_cpp.cpp Fri May 23 16:56:24 2008
@@ -0,0 +1,157 @@
+#include <string>
+#include <stdexcept>
+
+#include "girstring.h"
+#include "casprintf.h"
+#include "cmdline_parser.h"
+
+#include "cmdline_parser.hpp"
+
+using namespace std;
+
+
+
+static enum optiontype
+optTypeConvert(
+ CmdlineParser::optType const arg) {
+
+ enum optiontype retval;
+
+ retval = OPTTYPE_FLAG; // defeat compiler warning
+
+ switch (arg) {
+ case CmdlineParser::FLAG: retval = OPTTYPE_FLAG; break;
+ case CmdlineParser::INT: retval = OPTTYPE_INT; break;
+ case CmdlineParser::UINT: retval = OPTTYPE_UINT; break;
+ case CmdlineParser::STRING: retval = OPTTYPE_STRING; break;
+ case CmdlineParser::BINUINT: retval = OPTTYPE_BINUINT; break;
+ case CmdlineParser::FLOAT: retval = OPTTYPE_FLOAT; break;
+ }
+ return retval;
+}
+
+
+
+CmdlineParser::CmdlineParser() {
+
+ this->cp = cmd_createOptionParser();
+}
+
+
+
+CmdlineParser::~CmdlineParser() {
+ cmd_destroyOptionParser(this->cp);
+}
+
+
+
+void
+CmdlineParser::defineOption(
+ string const optionName,
+ optType const optionType) {
+
+ cmd_defineOption(this->cp, optionName.c_str(),
+ optTypeConvert(optionType));
+}
+
+
+
+void
+CmdlineParser::processOptions(
+ int const argc,
+ const char ** const argv) {
+
+ const char * error;
+
+ cmd_processOptions(this->cp, argc, argv, &error);
+ if (error) {
+ string const errorS(error);
+ strfree(error);
+ throw(runtime_error(errorS));
+ }
+}
+
+
+
+bool
+CmdlineParser::optionIsPresent(
+ string const optionName) const {
+
+ return (cmd_optionIsPresent(this->cp, optionName.c_str()) ? true : false);
+}
+
+
+
+int
+CmdlineParser::getOptionValueInt(
+ string const optionName) const {
+
+ return cmd_getOptionValueInt(this->cp, optionName.c_str());
+}
+
+
+
+unsigned int
+CmdlineParser::getOptionValueUint(
+ string const optionName) const {
+
+ return cmd_getOptionValueUint(this->cp, optionName.c_str());
+}
+
+
+
+unsigned long long
+CmdlineParser::getOptionValueBinUint(
+ string const optionName) const {
+
+ return cmd_getOptionValueBinUint(this->cp, optionName.c_str());
+}
+
+
+
+double
+CmdlineParser::getOptionValueFloat(
+ string const optionName) const {
+
+ return cmd_getOptionValueFloat(this->cp, optionName.c_str());
+}
+
+
+
+string
+CmdlineParser::getOptionValueString(
+ string const optionName) const {
+
+ const char * const value =
+ cmd_getOptionValueString(this->cp, optionName.c_str());
+
+ string retval;
+
+ if (value) {
+ retval = string(value);
+ strfree(value);
+ } else
+ retval = "";
+
+ return retval;
+}
+
+
+
+unsigned int
+CmdlineParser::argumentCount() const {
+
+ return cmd_argumentCount(this->cp);
+}
+
+
+
+string
+CmdlineParser::getArgument(
+ unsigned int const argNumber) const {
+
+ const char * const value = cmd_getArgument(this->cp, argNumber);
+ string const retval(value);
+ strfree(value);
+ return retval;
+}
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/util/getoptx.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/util/getoptx.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/util/getoptx.c Fri May 23 16:56:24 2008
@@ -19,10 +19,6 @@
#include "getoptx.h"
-#ifdef _AIX
-#pragma alloca
-#endif
-
/* Note that on some systems, the header files above declare variables
for use with their native getopt facilities, and those variables have
the same names as we'd like to use. So we use things like optargx
@@ -94,20 +90,25 @@
exchange(char ** const argv) {
unsigned int const nonopts_size =
(last_nonopt - first_nonopt) * sizeof (char *);
- char **temp = (char **) alloca (nonopts_size);
+ char **temp = (char **) malloc (nonopts_size);
+
+ if (temp == NULL)
+ abort();
/* Interchange the two blocks of data in argv. */
- bcopy (&argv[first_nonopt], temp, nonopts_size);
- bcopy (&argv[last_nonopt], &argv[first_nonopt],
- (optindx - last_nonopt) * sizeof (char *));
- bcopy (temp, &argv[first_nonopt + optindx - last_nonopt],
- nonopts_size);
+ memcpy (temp, &argv[first_nonopt], nonopts_size);
+ memcpy (&argv[first_nonopt], &argv[last_nonopt],
+ (optindx - last_nonopt) * sizeof (char *));
+ memcpy (&argv[first_nonopt + optindx - last_nonopt], temp,
+ nonopts_size);
/* Update records for the slots the non-options now occupy. */
first_nonopt += (optindx - last_nonopt);
last_nonopt = optindx;
+
+ free(temp);
}
/* Scan elements of ARGV (whose length is ARGC) for option characters
@@ -243,13 +244,16 @@
char *s = nextchar;
int exact = 0;
int ambig = 0;
- struct optionx *pfound = 0;
+ struct optionx * pfound;
int indfound;
while (*s && *s != '=') s++;
+ indfound = 0; /* quite compiler warning */
+
/* Test all options for either exact match or abbreviated matches. */
- for (p = _getopt_long_options, option_index = 0; p->name;
+ for (p = _getopt_long_options, option_index = 0, pfound = NULL;
+ p->name;
p++, option_index++)
if (!strncmp (p->name, nextchar, s - nextchar))
{
@@ -261,7 +265,7 @@
exact = 1;
break;
}
- else if (pfound == 0)
+ else if (!pfound)
{
/* First nonexact match found. */
pfound = p;
@@ -280,7 +284,7 @@
return '?';
}
- if (pfound != 0)
+ if (pfound)
{
option_index = indfound;
optindx++;
@@ -314,7 +318,7 @@
*(pfound->flag) = pfound->val;
return 0;
}
- if (argv[optindx][0] == '+' || index (optstring, *nextchar) == 0)
+ if (argv[optindx][0] == '+' || strchr (optstring, *nextchar) == 0)
{
if (opterrx != 0)
fprintf (stderr, "%s: unrecognized option `%c%s'\n",
@@ -328,7 +332,7 @@
{
char c = *nextchar++;
- char *temp = index (optstring, c);
+ char *temp = strchr (optstring, c);
/* Increment `optindx' when we start to process its last character. */
if (*nextchar == 0)
Added: freeswitch/trunk/libs/xmlrpc-c/lib/util/include/assertx.hpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/util/include/assertx.hpp Fri May 23 16:56:24 2008
@@ -0,0 +1,27 @@
+#ifndef ASSERTX_HPP_INCLUDED
+#define ASSERTX_HPP_INCLUDED
+
+#include <cassert>
+
+/* The compiler often warns you if you give a function formal parameter a
+ name, but don't use it. But because assert() disappears when doing an
+ optimized build, the compiler doesn't recognize your reference to the
+ parameter in the assert() argument. To avoid the bogus warning in
+ this case, we have ASSERT_ONLY_ARG(), which declares a name for a
+ formal parameter for purposes of assert() only. In cases where an
+ assert() would disappear, ASSERT_ONLY_ARG() disappears too.
+
+ E.g.
+
+ void foo(int const ASSERT_ONLY_ARG(arg1)) {
+
+ assert(arg1 > 0);
+ }
+*/
+#ifdef NDEBUG
+ #define ASSERT_ONLY_ARG(x)
+#else
+ #define ASSERT_ONLY_ARG(x) x
+#endif
+
+#endif
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/util/include/bool.h
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/util/include/bool.h (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/util/include/bool.h Fri May 23 16:56:24 2008
@@ -1,18 +1,18 @@
-#ifndef BOOL_H_INCLUDED
-#define BOOL_H_INCLUDED
+/* This takes the place of C99 stdbool.h, which at least some Windows
+ compilers don't have. (October 2005).
-#ifndef TRUE
-#define TRUE (1)
-#endif
-#ifndef FALSE
-#define FALSE (0)
-#endif
+ One must not also include <stdbool.h>, because it might cause a name
+ collision.
+*/
#ifndef __cplusplus
-#ifndef HAVE_BOOL
-#define HAVE_BOOL
-typedef int bool;
+/* At least the GNU compiler defines __bool_true_false_are_defined */
+#ifndef __bool_true_false_are_defined
+#define __bool_true_false_are_defined
+typedef enum {
+ false = 0,
+ true = 1
+} bool;
#endif
#endif
-#endif
Added: freeswitch/trunk/libs/xmlrpc-c/lib/util/include/c_util.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/util/include/c_util.h Fri May 23 16:56:24 2008
@@ -0,0 +1,19 @@
+#ifndef C_UTIL_H_INCLUDED
+#define C_UTIL_H_INCLUDED
+
+/* C language stuff. Doesn't involve any libraries that aren't part of
+ the compiler.
+*/
+
+#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
+
+/* GNU_PRINTF_ATTR lets the GNU compiler check printf-type
+ calls to be sure the arguments match the format string, thus preventing
+ runtime segmentation faults and incorrect messages.
+*/
+#ifdef __GNUC__
+#define GNU_PRINTF_ATTR(a,b) __attribute__ ((format (printf, a, b)))
+#else
+#define GNU_PRINTF_ATTR(a,b)
+#endif
+#endif
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/util/include/casprintf.h
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/util/include/casprintf.h (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/util/include/casprintf.h Fri May 23 16:56:24 2008
@@ -3,16 +3,14 @@
#include <stdarg.h>
-/* GNU_PRINTF_ATTR lets the GNU compiler check printf-type
- calls to be sure the arguments match the format string, thus preventing
- runtime segmentation faults and incorrect messages.
-*/
-#ifdef __GNUC__
-#define GNU_PRINTF_ATTR(a,b) __attribute__ ((format (printf, a, b)))
-#else
-#define GNU_PRINTF_ATTR(a,b)
+#include "c_util.h"
+
+#ifdef __cplusplus
+extern "C" {
#endif
+extern const char * const strsol;
+
void
cvasprintf(const char ** const retvalP,
const char * const fmt,
@@ -24,4 +22,8 @@
void
strfree(const char * const string);
+#ifdef __cplusplus
+}
+#endif
+
#endif
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/util/include/cmdline_parser.h
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/util/include/cmdline_parser.h (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/util/include/cmdline_parser.h Fri May 23 16:56:24 2008
@@ -1,6 +1,14 @@
#ifndef CMDLINE_PARSER_H
#define CMDLINE_PARSER_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+#if 0
+} /* to fake out automatic code indenters */
+#endif
+
+#include "int.h"
/*
@@ -10,17 +18,24 @@
*/
-enum optiontype {OPTTYPE_FLAG, OPTTYPE_INT, OPTTYPE_UINT, OPTTYPE_STRING};
+enum optiontype {
+ OPTTYPE_FLAG,
+ OPTTYPE_INT,
+ OPTTYPE_UINT,
+ OPTTYPE_STRING,
+ OPTTYPE_BINUINT,
+ OPTTYPE_FLOAT
+};
struct cmdlineParserCtl;
typedef struct cmdlineParserCtl * cmdlineParser;
void
-cmd_processOptions(cmdlineParser const cpP,
- int const argc,
- const char ** const argv,
- const char ** const errorP);
+cmd_processOptions(cmdlineParser const cpP,
+ int const argc,
+ const char ** const argv,
+ const char ** const errorP);
cmdlineParser
cmd_createOptionParser(void);
@@ -37,18 +52,26 @@
cmd_optionIsPresent(cmdlineParser const cpP,
const char * const name);
-unsigned int
-cmd_getOptionValueUint(cmdlineParser const cpP,
- const char * const name);
-
int
cmd_getOptionValueInt(cmdlineParser const cpP,
const char * const name);
+unsigned int
+cmd_getOptionValueUint(cmdlineParser const cpP,
+ const char * const name);
+
const char *
cmd_getOptionValueString(cmdlineParser const cpP,
const char * const name);
+uint64_t
+cmd_getOptionValueBinUint(cmdlineParser const cpP,
+ const char * const name);
+
+double
+cmd_getOptionValueFloat(cmdlineParser const cpP,
+ const char * const name);
+
unsigned int
cmd_argumentCount(cmdlineParser const cpP);
@@ -56,4 +79,8 @@
cmd_getArgument(cmdlineParser const cpP,
unsigned int const argNumber);
+#ifdef __cplusplus
+}
+#endif
+
#endif
Added: freeswitch/trunk/libs/xmlrpc-c/lib/util/include/cmdline_parser.hpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/util/include/cmdline_parser.hpp Fri May 23 16:56:24 2008
@@ -0,0 +1,59 @@
+#ifndef CMDLINE_PARSER_HPP_INCLUDED
+#define CMDLINE_PARSER_HPP_INCLUDED
+
+#include <string>
+
+struct cmdlineParserCtl;
+
+class CmdlineParser {
+public:
+ CmdlineParser();
+
+ ~CmdlineParser();
+
+ enum optType {FLAG, INT, UINT, STRING, BINUINT, FLOAT};
+
+ void
+ defineOption(std::string const optionName,
+ optType const optionType);
+
+ void
+ processOptions(int const argc,
+ const char ** const argv);
+
+ bool
+ optionIsPresent(std::string const optionName) const;
+
+ int
+ getOptionValueInt(std::string const optionName) const;
+
+ unsigned int
+ getOptionValueUint(std::string const optionName) const;
+
+ std::string
+ getOptionValueString(std::string const optionName) const;
+
+ unsigned long long
+ getOptionValueBinUint(std::string const optionName) const;
+
+ double
+ getOptionValueFloat(std::string const optionName) const;
+
+ unsigned int
+ argumentCount() const;
+
+ std::string
+ getArgument(unsigned int const argNumber) const;
+
+private:
+ struct cmdlineParserCtl * cp;
+
+ // Make sure no one can copy this object, because if there are two
+ // copies, there will be two attempts to destroy *cp.
+ CmdlineParser(CmdlineParser const&) {};
+
+ CmdlineParser&
+ operator=(CmdlineParser const&) {return *this;}
+};
+
+#endif
Added: freeswitch/trunk/libs/xmlrpc-c/lib/util/include/girmath.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/util/include/girmath.h Fri May 23 16:56:24 2008
@@ -0,0 +1,8 @@
+#ifndef __GIRMATH_H
+#define __GIRMATH_H
+
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+
+#endif
+
Added: freeswitch/trunk/libs/xmlrpc-c/lib/util/include/girstring.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/util/include/girstring.h Fri May 23 16:56:24 2008
@@ -0,0 +1,51 @@
+#ifndef GIRSTRING_H_INCLUDED
+#define GIRSTRING_H_INCLUDED
+
+#include <string.h>
+
+#include "xmlrpc_config.h"
+#include "bool.h"
+
+bool
+stripcaseeq(const char * const comparand,
+ const char * const comparator);
+
+static __inline__ bool
+streq(const char * const comparator,
+ const char * const comparand) {
+
+ return (strcmp(comparand, comparator) == 0);
+}
+
+static __inline__ bool
+memeq(const void * const comparator,
+ const void * const comparand,
+ size_t const size) {
+
+ return (memcmp(comparator, comparand, size) == 0);
+}
+
+#define MEMEQ(a,b,c) (memcmp(a, b, c) == 0)
+
+#define MEMSSET(a,b) (memset(a, b, sizeof(*a)))
+
+#define MEMSCPY(a,b) (memcpy(a, b, sizeof(*a)))
+
+#define MEMSZERO(a) (MEMSSET(a, 0))
+
+static __inline__ const char *
+sdup(const char * const input) {
+ return (const char *) strdup(input);
+}
+
+/* Copy string pointed by B to array A with size checking. */
+#define STRSCPY(A,B) \
+ (strncpy((A), (B), sizeof(A)), *((A)+sizeof(A)-1) = '\0')
+#define STRSCMP(A,B) \
+ (strncmp((A), (B), sizeof(A)))
+
+/* Concatenate string B onto string in array A with size checking */
+#define STRSCAT(A,B) \
+ (strncat((A), (B), sizeof(A)-strlen(A)), *((A)+sizeof(A)-1) = '\0')
+
+#endif
Added: freeswitch/trunk/libs/xmlrpc-c/lib/util/include/int.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/util/include/int.h Fri May 23 16:56:24 2008
@@ -0,0 +1,53 @@
+/* This takes the place of C99 inttypes.h, which at least some Windows
+ compilers don't have. (October 2007).
+*/
+
+/* PRId64 is the printf-style format specifier for a long long type, as in
+ long long mynumber = 5;
+ printf("My number is %" PRId64 ".\n", mynumber);
+
+ The LL/ULL macro is for 64 bit integer literals, like this:
+
+ long long mask= ULL(1) << 33;
+*/
+
+#ifdef _MSC_VER
+# define PRId64 "I64d"
+# define PRIu64 "I64u"
+
+#ifndef int16_t
+typedef short int16_t;
+#endif
+#ifndef uint16_t
+typedef unsigned short uint16_t;
+#endif
+#ifndef int32_t
+typedef int int32_t;
+#endif
+#ifndef uint32_t
+typedef unsigned int uint32_t;
+#endif
+#ifndef int64_t
+typedef __int64 int64_t;
+#endif
+#ifndef uint64_t
+typedef unsigned __int64 uint64_t;
+#endif
+#ifndef uint
+typedef unsigned int uint;
+#endif
+#ifndef uint8_t
+typedef unsigned char uint8_t;
+#endif
+
+/* Older Microsoft compilers don't know the standard ll/ull suffixes */
+#define LL(x) x ## i64
+#define ULL(x) x ## u64
+
+#else
+ /* Not Microsoft compiler */
+ #include <inttypes.h>
+ #define LL(x) x ## ll
+ #define ULL(x) x ## ull
+#endif
+
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/util/include/mallocvar.h
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/util/include/mallocvar.h (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/util/include/mallocvar.h Fri May 23 16:56:24 2008
@@ -50,14 +50,28 @@
reallocProduct(void ** const blockP,
unsigned int const factor1,
unsigned int const factor2) {
+
+ void * const oldBlockP = *blockP;
+
+ void * newBlockP;
if (UINT_MAX / factor2 < factor1)
- *blockP = NULL;
+ newBlockP = NULL;
else
- *blockP = realloc(*blockP, factor1 * factor2);
+ newBlockP = realloc(oldBlockP, factor1 * factor2);
+
+ if (newBlockP)
+ *blockP = newBlockP;
+ else {
+ free(oldBlockP);
+ *blockP = NULL;
+ }
}
+/* IMPLEMENTATION NOTE: There are huge strict aliasing pitfalls here
+ if you cast pointers, e.g. (void **)
+*/
#define MALLOCARRAY(arrayName, nElements) do { \
void * array; \
@@ -65,8 +79,11 @@
arrayName = array; \
} while (0)
-#define REALLOCARRAY(arrayName, nElements) \
- reallocProduct((void **)&arrayName, nElements, sizeof(arrayName[0]))
+#define REALLOCARRAY(arrayName, nElements) do { \
+ void * array = arrayName; \
+ reallocProduct(&array, nElements, sizeof(arrayName[0])); \
+ arrayName = array; \
+} while (0)
#define MALLOCARRAY_NOFAIL(arrayName, nElements) \
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/util/include/pthreadx.h
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/util/include/pthreadx.h (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/util/include/pthreadx.h Fri May 23 16:56:24 2008
@@ -30,39 +30,51 @@
# define _REENTRANT
# include <pthread.h>
#elif defined (WIN32)
+#include <windows.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
typedef HANDLE pthread_t;
typedef CRITICAL_SECTION pthread_mutex_t;
#define PTHREAD_MUTEX_INITIALIZER NULL
- //usage: pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+ /* usage: pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; */
typedef
struct {
- int attrs; //currently unused. placeholder.
+ int attrs; /* currently unused. placeholder. */
} pthread_attr_t;
typedef
struct {
- int attrs; //currently unused. placeholder.
+ int attrs; /* currently unused. placeholder. */
} pthread_mutexattr_t;
-//typedef void * (*pthread_func)(void *);
-typedef unsigned ( __stdcall *pthread_func )( void * );
-
-extern int pthread_create(pthread_t *new_thread_ID,
- const pthread_attr_t *attr,
- pthread_func start_func, void *arg);
+/* We make pthread_func identical to a Windows thread start function
+ so we can use Windows thread functions to implement these pthread
+ functions directly.
+*/
+typedef unsigned (WINAPI pthread_func)(void *);
+
+extern int pthread_create(pthread_t * const new_thread_ID,
+ const pthread_attr_t * const attr,
+ pthread_func * start_func,
+ void * const arg);
extern int pthread_cancel(pthread_t target_thread);
extern int pthread_join(pthread_t target_thread, void **status);
extern int pthread_detach(pthread_t target_thread);
-extern int pthread_mutex_init(pthread_mutex_t *mp,
- const pthread_mutexattr_t *attr);
-extern int pthread_mutex_lock(pthread_mutex_t *mp);
-extern int pthread_mutex_unlock(pthread_mutex_t *mp);
-extern int pthread_mutex_destroy(pthread_mutex_t *mp);
+extern int pthread_mutex_init(pthread_mutex_t * const mp,
+ const pthread_mutexattr_t * const attr);
+extern int pthread_mutex_lock(pthread_mutex_t * const mp);
+extern int pthread_mutex_unlock(pthread_mutex_t * const mp);
+extern int pthread_mutex_destroy(pthread_mutex_t * const mp);
+#ifdef __cplusplus
+}
+#endif
#endif /* WIN32 */
#endif
Added: freeswitch/trunk/libs/xmlrpc-c/lib/util/include/stdargx.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/util/include/stdargx.h Fri May 23 16:56:24 2008
@@ -0,0 +1,67 @@
+#ifndef STDARGX_H_INCLUDED
+#define STDARGX_H_INCLUDED
+
+#include "xmlrpc_config.h"
+#include <stdarg.h>
+#include <string.h>
+
+/*----------------------------------------------------------------------------
+ We need a special version of va_list in order to pass around the
+ variable argument heap by reference, thus allowing a subroutine to
+ advance the heap's pointer.
+
+ On some systems (e.g. Gcc for PPC or AMD64), va_list is an array.
+ That invites the scourge of array-to-pointer degeneration if you try
+ to take its address. Burying it inside a struct as we do with out
+ va_listx type makes it immune.
+
+ Example of what would happen if we used va_list instead of va_listx,
+ on a system where va_list is an array:
+
+ void sub2(va_list * argsP) [
+ ...
+ }
+
+ void sub1(va_list args) {
+ sub2(&args);
+ }
+
+ This doesn't work. '&args' is the same thing as 'args', so is
+ va_list, not va_list *. The compiler will even warn you about the
+ pointer type mismatch.
+
+ To use va_listx:
+
+ void sub1_va(char * format, va_list args) {
+ va_listx argsx;
+ init_va_listx(&argsx, args);
+ sub2(format, &argsx);
+ }
+
+-----------------------------------------------------------------------------*/
+
+
+typedef struct {
+/*----------------------------------------------------------------------------
+ Same thing as va_list, but in a form that works everywhere. See above.
+-----------------------------------------------------------------------------*/
+ va_list v;
+} va_listx;
+
+
+
+static __inline__ void
+init_va_listx(va_listx * const argsxP,
+ va_list const args) {
+#if VA_LIST_IS_ARRAY
+ /* 'args' is NOT a va_list. It is a pointer to the first element of a
+ 'va_list', which is the same address as a pointer to the va_list
+ itself.
+ */
+ memcpy(&argsxP->v, args, sizeof(argsxP->v));
+#else
+ argsxP->v = args;
+#endif
+}
+
+#endif
Added: freeswitch/trunk/libs/xmlrpc-c/lib/util/include/string_parser.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/util/include/string_parser.h Fri May 23 16:56:24 2008
@@ -0,0 +1,31 @@
+#ifndef STRING_PARSER_H_INCLUDED
+#define STRING_PARSER_H_INCLUDED
+
+#include "int.h"
+
+void
+interpretUll(const char * const string,
+ uint64_t * const ullP,
+ const char ** const errorP);
+
+void
+interpretLl(const char * const string,
+ int64_t * const llP,
+ const char ** const errorP);
+
+void
+interpretUint(const char * const string,
+ unsigned int * const uintP,
+ const char ** const errorP);
+
+void
+interpretInt(const char * const string,
+ int * const uintP,
+ const char ** const errorP);
+
+void
+interpretBinUint(const char * const string,
+ uint64_t * const valueP,
+ const char ** const errorP);
+
+#endif
Added: freeswitch/trunk/libs/xmlrpc-c/lib/util/include/unistdx.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/util/include/unistdx.h Fri May 23 16:56:24 2008
@@ -0,0 +1,14 @@
+#ifndef UNISTDX_H_INCLUDED
+#define UNISTDX_H_INCLUDED
+
+/* Xmlrpc-c code #includes "unistdx.h" instead of <unistd.h> because
+ <unistd.h> does not exist on WIN32.
+*/
+
+#ifndef WIN32
+# include <unistd.h>
+#else
+
+#endif /* WIN32 */
+
+#endif
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/util/pthreadx_win32.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/util/pthreadx_win32.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/util/pthreadx_win32.c Fri May 23 16:56:24 2008
@@ -25,7 +25,7 @@
#include "xmlrpc_config.h"
-#if WIN32
+#ifdef WIN32
#include "pthreadx.h"
@@ -34,15 +34,17 @@
#undef PACKAGE
#undef VERSION
-int pthread_create(pthread_t *new_thread_ID,
- const pthread_attr_t * attr,
- pthread_func start_func, void *arg)
-{
+int
+pthread_create(pthread_t * const new_thread_ID,
+ const pthread_attr_t * const attr,
+ pthread_func * func,
+ void * const arg) {
+
HANDLE hThread;
DWORD dwThreadID;
hThread = (HANDLE) _beginthreadex (
- NULL, 0, start_func, (LPVOID)arg, CREATE_SUSPENDED, &dwThreadID);
+ NULL, 0, func, (LPVOID)arg, CREATE_SUSPENDED, &dwThreadID);
SetThreadPriority (hThread, THREAD_PRIORITY_NORMAL);
ResumeThread (hThread);
@@ -52,48 +54,68 @@
return hThread ? 0 : -1;
}
+
+
/* Just kill it. */
-int pthread_cancel(pthread_t target_thread)
-{
- CloseHandle (target_thread);
+int
+pthread_cancel(pthread_t const target_thread) {
+
+ CloseHandle(target_thread);
return 0;
}
+
+
/* Waits for the thread to exit before continuing. */
-int pthread_join(pthread_t target_thread, void **status)
-{
+int
+pthread_join(pthread_t const target_thread,
+ void ** const statusP) {
+
DWORD dwResult = WaitForSingleObject(target_thread, INFINITE);
- (*status) = (void *)dwResult;
+ *statusP = (void *)dwResult;
return 0;
}
-/* Stubbed. Do nothing. */
-int pthread_detach(pthread_t target_thread)
-{
+
+
+int
+pthread_detach(pthread_t const target_thread) {
return 0;
}
-int pthread_mutex_init(pthread_mutex_t *mp,
- const pthread_mutexattr_t * attr)
-{
+
+
+int
+pthread_mutex_init(pthread_mutex_t * const mp,
+ const pthread_mutexattr_t * const attr) {
+
InitializeCriticalSection(mp);
return 0;
}
-int pthread_mutex_lock(pthread_mutex_t *mp)
-{
+
+
+int
+pthread_mutex_lock(pthread_mutex_t * const mp) {
+
EnterCriticalSection(mp);
return 0;
}
-int pthread_mutex_unlock(pthread_mutex_t *mp)
-{
+
+
+int
+pthread_mutex_unlock(pthread_mutex_t * const mp) {
+
LeaveCriticalSection(mp);
return 0;
}
-int pthread_mutex_destroy(pthread_mutex_t *mp)
-{
+
+
+int
+pthread_mutex_destroy(pthread_mutex_t * const mp) {
+
DeleteCriticalSection(mp);
return 0;
}
Added: freeswitch/trunk/libs/xmlrpc-c/lib/util/string_parser.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/util/string_parser.c Fri May 23 16:56:24 2008
@@ -0,0 +1,226 @@
+#include <sys/types.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <limits.h>
+
+#include "int.h"
+#include "girstring.h"
+#include "casprintf.h"
+
+#include "string_parser.h"
+
+static const char *
+strippedSubstring(const char * const string) {
+
+ const char * p;
+
+ for (p = &string[0]; isspace(*p); ++p);
+
+ return p;
+}
+
+
+
+void
+interpretUll(const char * const string,
+ uint64_t * const ullP,
+ const char ** const errorP) {
+
+ /* strtoull() has the same disappointing weaknesses of strtoul().
+ See interpretUint().
+ */
+
+ const char * const strippedString = strippedSubstring(string);
+
+ if (strippedString[0] == '\0')
+ casprintf(errorP, "Null (or all whitespace) string.");
+ else if (!isdigit(strippedString[0]))
+ casprintf(errorP, "First non-blank character is '%c', not a digit.",
+ strippedString[0]);
+ else {
+ /* strtoull() does a bizarre thing where if the number is out
+ of range, it returns a clamped value but tells you about it
+ by setting errno = ERANGE. If it is not out of range,
+ strtoull() leaves errno alone.
+ */
+ char * tail;
+
+ errno = 0; /* So we can tell if strtoull() overflowed */
+
+ *ullP = strtoull(strippedString, &tail, 10);
+
+ if (tail[0] != '\0')
+ casprintf(errorP, "Non-digit stuff in string: %s", tail);
+ else if (errno == ERANGE)
+ casprintf(errorP, "Number too large");
+ else
+ *errorP = NULL;
+ }
+}
+
+
+
+void
+interpretLl(const char * const string,
+ int64_t * const llP,
+ const char ** const errorP) {
+
+ if (string[0] == '\0')
+ casprintf(errorP, "Null string.");
+ else {
+ /* strtoll() does a bizarre thing where if the number is out
+ of range, it returns a clamped value but tells you about it
+ by setting errno = ERANGE. If it is not out of range,
+ strtoll() leaves errno alone.
+ */
+ char * tail;
+
+ errno = 0; /* So we can tell if strtoll() overflowed */
+
+ *llP = strtoll(string, &tail, 10);
+
+ if (tail[0] != '\0')
+ casprintf(errorP, "Non-digit stuff in string: %s", tail);
+ else if (errno == ERANGE)
+ casprintf(errorP, "Number too large");
+ else
+ *errorP = NULL;
+ }
+}
+
+
+
+void
+interpretUint(const char * const string,
+ uint * const uintP,
+ const char ** const errorP) {
+
+ /* strtoul() does a lousy job of dealing with invalid numbers. A null
+ string is just zero; a negative number is a large positive one; a
+ positive (cf unsigned) number is accepted. strtoul is inconsistent
+ in its treatment of the tail; if there is no valid number at all,
+ it returns the entire string as the tail, including leading white
+ space and sign, which are not themselves invalid.
+ */
+
+ const char * const strippedString = strippedSubstring(string);
+
+ if (strippedString[0] == '\0')
+ casprintf(errorP, "Null (or all whitespace) string.");
+ else if (!isdigit(strippedString[0]))
+ casprintf(errorP, "First non-blank character is '%c', not a digit.",
+ strippedString[0]);
+ else {
+ /* strtoul() does a bizarre thing where if the number is out
+ of range, it returns a clamped value but tells you about it
+ by setting errno = ERANGE. If it is not out of range,
+ strtoul() leaves errno alone.
+ */
+ char * tail;
+ unsigned long ulongValue;
+
+ errno = 0; /* So we can tell if strtoul() overflowed */
+
+ ulongValue = strtoul(strippedString, &tail, 10);
+
+ if (tail[0] != '\0')
+ casprintf(errorP, "Non-digit stuff in string: %s", tail);
+ else if (errno == ERANGE)
+ casprintf(errorP, "Number too large");
+ else if (ulongValue > UINT_MAX)
+ casprintf(errorP, "Number too large");
+ else {
+ *uintP = ulongValue;
+ *errorP = NULL;
+ }
+ }
+}
+
+
+
+void
+interpretInt(const char * const string,
+ int * const intP,
+ const char ** const errorP) {
+
+ if (string[0] == '\0')
+ casprintf(errorP, "Null string.");
+ else {
+ /* strtol() does a bizarre thing where if the number is out
+ of range, it returns a clamped value but tells you about it
+ by setting errno = ERANGE. If it is not out of range,
+ strtol() leaves errno alone.
+ */
+ char * tail;
+ long longValue;
+
+ errno = 0; /* So we can tell if strtol() overflowed */
+
+ longValue = strtol(string, &tail, 10);
+
+ if (tail[0] != '\0')
+ casprintf(errorP, "Non-digit stuff in string: %s", tail);
+ else if (errno == ERANGE)
+ casprintf(errorP, "Number too large");
+ else if (longValue > INT_MAX)
+ casprintf(errorP, "Number too large");
+ else if (longValue < INT_MIN)
+ casprintf(errorP, "Number too negative");
+ else {
+ *intP = longValue;
+ *errorP = NULL;
+ }
+ }
+}
+
+
+
+void
+interpretBinUint(const char * const string,
+ uint64_t * const valueP,
+ const char ** const errorP) {
+
+ char * tailptr;
+ long const mantissa_long = strtol(string, &tailptr, 10);
+
+ if (errno == ERANGE)
+ casprintf(errorP,
+ "Numeric value out of range for computation: '%s'. "
+ "Try a smaller number with a K, M, G, etc. suffix.",
+ string);
+ else {
+ int64_t const mantissa = mantissa_long;
+
+ int64_t argNumber;
+
+ *errorP = NULL; /* initial assumption */
+
+ if (*tailptr == '\0')
+ /* There's no suffix. A pure number */
+ argNumber = mantissa * 1;
+ else if (stripcaseeq(tailptr, "K"))
+ argNumber = mantissa * 1024;
+ else if (stripcaseeq(tailptr, "M"))
+ argNumber = mantissa * 1024 * 1024;
+ else if (stripcaseeq(tailptr, "G"))
+ argNumber = mantissa * 1024 * 1024 * 1024;
+ else if (stripcaseeq(tailptr, "T"))
+ argNumber = mantissa * 1024 * 1024 * 1024 * 1024;
+ else if (stripcaseeq(tailptr, "P"))
+ argNumber = mantissa * 1024 * 1024 * 1024 * 1024 * 1024;
+ else {
+ argNumber = 0; /* quiet compiler warning */
+ casprintf(errorP, "Garbage suffix '%s' on number", tailptr);
+ }
+ if (!*errorP) {
+ if (argNumber < 0)
+ casprintf(errorP, "Unsigned numeric value is "
+ "negative: %" PRId64, argNumber);
+ else
+ *valueP = (uint64_t) argNumber;
+ }
+ }
+}
Added: freeswitch/trunk/libs/xmlrpc-c/lib/util/stripcaseeq.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/util/stripcaseeq.c Fri May 23 16:56:24 2008
@@ -0,0 +1,69 @@
+#define _GNU_SOURCE
+#include <ctype.h>
+
+#include "bool.h"
+#include "girstring.h"
+
+
+
+bool
+stripcaseeq(const char * const comparand,
+ const char * const comparator) {
+/*----------------------------------------------------------------------------
+ Compare two strings, ignoring leading and trailing blanks and case.
+
+ Return true if the strings are identical, false otherwise.
+-----------------------------------------------------------------------------*/
+ const char *p, *q, *px, *qx;
+ bool equal;
+
+ /* Make p and q point to the first non-blank character in each string.
+ If there are no non-blank characters, make them point to the terminating
+ NULL.
+ */
+
+ p = &comparand[0];
+ while (*p == ' ')
+ ++p;
+ q = &comparator[0];
+ while (*q == ' ')
+ ++q;
+
+ /* Make px and qx point to the last non-blank character in each string.
+ If there are no nonblank characters (which implies the string is
+ null), make them point to the terminating NULL.
+ */
+
+ if (*p == '\0')
+ px = p;
+ else {
+ px = p + strlen(p) - 1;
+ while (*px == ' ')
+ --px;
+ }
+
+ if (*q == '\0')
+ qx = q;
+ else {
+ qx = q + strlen(q) - 1;
+ while (*qx == ' ')
+ --qx;
+ }
+
+ equal = true; /* initial assumption */
+
+ /* If the stripped strings aren't the same length,
+ we know they aren't equal
+ */
+ if (px - p != qx - q)
+ equal = false;
+
+
+ while (p <= px) {
+ if (toupper(*p) != toupper(*q))
+ equal = false;
+ ++p; ++q;
+ }
+ return equal;
+}
+
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/wininet_transport/Makefile
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/wininet_transport/Makefile (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/wininet_transport/Makefile Fri May 23 16:56:24 2008
@@ -1,18 +1,34 @@
-ifeq ($(SRCDIR)x,x)
-SRCDIR = $(CURDIR)/../..
+ifeq ($(SRCDIR),)
+ updir = $(shell echo $(dir $(1)) | sed 's/.$$//')
+ LIBDIR := $(call updir,$(CURDIR))
+ SRCDIR := $(call updir,$(LIBDIR))
+ BLDDIR := $(SRCDIR)
endif
+SUBDIR := lib/wininet_transport
-include $(SRCDIR)/Makefile.config
-
-CFLAGS = $(CFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD)
-LDFLAGS = -lpthread $(LADD)
-
-INCLUDES = -I$(SRCDIR) -I$(SRCDIR)/src
+include $(BLDDIR)/config.mk
default: all
.PHONY: all
-all: xmlrpc_wininet_transport.lo
+all: xmlrpc_wininet_transport.o xmlrpc_wininet_transport.osh
+
+# Rules for the above dependencies are in common.mk,
+# courtesy of TARGET_MODS.
+
+TARGET_MODS = xmlrpc_wininet_transport
+
+OMIT_WININET_TRANSPORT_RULE=Y
+
+include $(SRCDIR)/common.mk
+
+CFLAGS = $(CFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD)
+
+INCLUDES = \
+ -I$(BLDDIR) \
+ -I$(BLDDIR)/include \
+ -I$(SRCDIR)/include \
+ -I$(SRCDIR)/lib/util/include \
.PHONY: clean
clean: clean-common
@@ -32,9 +48,8 @@
.PHONY: dep
dep: dep-common
-include $(SRCDIR)/Makefile.common
-
include Makefile.depend
-xmlrpc_wininet_transport.lo:%.lo:%.c
- $(LIBTOOL) --mode=compile $(CC) -c $(INCLUDES) $(CFLAGS) $<
+# Need this dependency for those who don't use Makefile.depend.
+# Without it, version.h doesn't get created.
+xmlrpc_wininet_transport.o xmlrpc_wininet_transport.osh: version.h
Modified: freeswitch/trunk/libs/xmlrpc-c/lib/wininet_transport/xmlrpc_wininet_transport.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/wininet_transport/xmlrpc_wininet_transport.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/wininet_transport/xmlrpc_wininet_transport.c Fri May 23 16:56:24 2008
@@ -4,56 +4,48 @@
WinInet-based client transport for Xmlrpc-c. Copyright information at
the bottom of this file.
- Changelog (changes by Steven A. Bone - sbone at pobox.com unless otherwise noted):
- 05.01.01 - Significant refactoring of the transport layer due to internal
- changes of the xmlrpc-c transports. Modeled after the CURL
- based transport changes by Bryan Henderson.
- 05.02.03 - Fixed Authorization header - thanks yamer.
- 05.03.20 - Supports xmlrpc_xportparms, xmlrpc_wininet_xportparms added
- *potential breaking change* - now by default we fail on invalid
- SSL certs, use the xmlrpc_wininet_xportparms option to enable old
- behavior.
-
=============================================================================*/
#include "xmlrpc_config.h"
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stddef.h>
+#include <windows.h>
+#include <wininet.h>
+
#include "bool.h"
#include "mallocvar.h"
#include "linklist.h"
#include "casprintf.h"
+#include "pthreadx.h"
+
#include "xmlrpc-c/base.h"
#include "xmlrpc-c/base_int.h"
#include "xmlrpc-c/client.h"
#include "xmlrpc-c/client_int.h"
-#include "pthreadx.h"
-
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <stddef.h>
+#include "xmlrpc-c/transport.h"
-#if defined (WIN32)
-# include <wininet.h>
-#endif /*WIN32*/
-
-#if defined (WIN32) && defined(_DEBUG)
-# include <crtdbg.h>
-# define new DEBUG_NEW
-# define malloc(size) _malloc_dbg( size, _NORMAL_BLOCK, __FILE__, __LINE__)
-# undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
-#endif /*WIN32 && _DEBUG*/
+#if defined(_DEBUG)
+# include <crtdbg.h>
+# define new DEBUG_NEW
+# define malloc(size) _malloc_dbg( size, _NORMAL_BLOCK, __FILE__, __LINE__)
+# undef THIS_FILE
+ static char THIS_FILE[] = __FILE__;
+#endif
static HINTERNET hSyncInternetSession = NULL;
/* Declare WinInet status callback. */
-void CALLBACK statusCallback (HINTERNET hInternet,
- unsigned long dwContext,
- unsigned long dwInternetStatus,
- void * lpvStatusInformation,
- unsigned long dwStatusInformationLength);
+void CALLBACK
+statusCallback(HINTERNET const hInternet,
+ unsigned long const dwContext,
+ unsigned long const dwInternetStatus,
+ void * const lpvStatusInformation,
+ unsigned long const dwStatusInformationLength);
struct xmlrpc_client_transport {
@@ -65,24 +57,24 @@
*/
int allowInvalidSSLCerts;
/* Flag to specify if we ignore invalid SSL Certificates. If this
- is set to zero, calling a XMLRPC server with an invalid SSL
- certificate will fail. This is the default behavior of the other
- transports, but invalid certificates were allowed in pre 1.2
- wininet xmlrpc-c transports.
+ is set to zero, calling a XMLRPC server with an invalid SSL
+ certificate will fail. This is the default behavior of the other
+ transports, but invalid certificates were allowed in pre 1.2
+ wininet xmlrpc-c transports.
*/
};
typedef struct {
unsigned long http_status;
- HINTERNET hHttpRequest;
- HINTERNET hURL;
- INTERNET_PORT nPort;
- char szHostName[255];
- char szUrlPath[255];
- BOOL bUseSSL;
- char *headerList;
- BYTE *pSendData;
- xmlrpc_mem_block *pResponseData;
+ HINTERNET hHttpRequest;
+ HINTERNET hURL;
+ INTERNET_PORT nPort;
+ char szHostName[255];
+ char szUrlPath[255];
+ BOOL bUseSSL;
+ char * headerList;
+ BYTE * pSendData;
+ xmlrpc_mem_block * pResponseData;
} winInetTransaction;
typedef struct {
@@ -100,112 +92,117 @@
*/
struct xmlrpc_call_info * callInfoP;
/* User's identifier for this RPC */
- struct xmlrpc_client_transport * clientTransportP;
+ struct xmlrpc_client_transport * clientTransportP;
} rpc;
+
+
static void
-createWinInetHeaderList( xmlrpc_env * const envP,
- const xmlrpc_server_info * const serverP,
- char ** const headerListP) {
+createWinInetHeaderList(xmlrpc_env * const envP,
+ const xmlrpc_server_info * const serverP,
+ char ** const headerListP) {
+
+ const char * const szContentType = "Content-Type: text/xml\r\n";
- char *szHeaderList = NULL;
- char *szContentType = "Content-Type: text/xml\r\n";
+ char * szHeaderList;
/* Send an authorization header if we need one. */
- if (serverP->_http_basic_auth) {
+ if (serverP->allowedAuth.basic) {
/* Make the header with content type and authorization */
/* NOTE: A newline is required between each added header */
- szHeaderList = malloc(strlen(szContentType) + 17 + strlen(serverP->_http_basic_auth) + 1 );
+ szHeaderList = malloc(strlen(szContentType) + 17 +
+ strlen(serverP->basicAuthHdrValue) + 1);
if (szHeaderList == NULL)
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR,
- "Couldn't allocate memory for authorization header");
+ xmlrpc_faultf(envP,
+ "Couldn't allocate memory for authorization header");
else {
- memcpy(szHeaderList,szContentType, strlen(szContentType));
- memcpy(szHeaderList + strlen(szContentType),"\r\nAuthorization: ", 17);
- memcpy(szHeaderList + strlen(szContentType) + 17, serverP->_http_basic_auth,
- strlen(serverP->_http_basic_auth) + 1);
+ memcpy(szHeaderList, szContentType, strlen(szContentType));
+ memcpy(szHeaderList + strlen(szContentType),"\r\nAuthorization: ",
+ 17);
+ memcpy(szHeaderList + strlen(szContentType) + 17,
+ serverP->basicAuthHdrValue,
+ strlen(serverP->basicAuthHdrValue) + 1);
}
- }
- else
- {
- /* Just the content type header is needed */
- szHeaderList = malloc(strlen(szContentType) + 1);
+ } else {
+ /* Just the content type header is needed */
+ szHeaderList = malloc(strlen(szContentType) + 1);
if (szHeaderList == NULL)
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR, "Couldn't allocate memory for standard header");
+ xmlrpc_faultf(envP,
+ "Couldn't allocate memory for standard header");
else
- memcpy(szHeaderList,szContentType, strlen(szContentType)+1);
- }
-
+ memcpy(szHeaderList, szContentType, strlen(szContentType) + 1);
+ }
*headerListP = szHeaderList;
}
+
+
static void
-createWinInetTransaction(xmlrpc_env * const envP,
- const xmlrpc_server_info * const serverP,
- xmlrpc_mem_block * const callXmlP,
- xmlrpc_mem_block * const responseXmlP,
- winInetTransaction ** const winInetTransactionPP) {
+createWinInetTransaction(xmlrpc_env * const envP,
+ const xmlrpc_server_info * const serverP,
+ xmlrpc_mem_block * const callXmlP,
+ xmlrpc_mem_block * const responseXmlP,
+ winInetTransaction ** const winInetTranPP) {
winInetTransaction * winInetTransactionP;
MALLOCVAR(winInetTransactionP);
if (winInetTransactionP == NULL)
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR,
- "No memory to create WinInet transaction.");
+ xmlrpc_faultf(envP, "No memory to create WinInet transaction.");
else {
- char szExtraInfo[255];
- char szScheme[100];
- URL_COMPONENTS uc;
-
- /* Init to defaults */
- winInetTransactionP->http_status = 0;
- winInetTransactionP->hHttpRequest = NULL;
- winInetTransactionP->hURL = NULL;
- winInetTransactionP->headerList=NULL;
- winInetTransactionP->pSendData=NULL;
- winInetTransactionP->pResponseData=responseXmlP;
-
- /* Parse the URL and store results into the winInetTransaction struct */
- memset (&uc, 0, sizeof (uc));
- uc.dwStructSize = sizeof (uc);
- uc.lpszScheme = szScheme;
- uc.dwSchemeLength = 100;
- uc.lpszHostName = winInetTransactionP->szHostName;
- uc.dwHostNameLength = 255;
- uc.lpszUrlPath = winInetTransactionP->szUrlPath;
- uc.dwUrlPathLength = 255;
- uc.lpszExtraInfo = szExtraInfo;
- uc.dwExtraInfoLength = 255;
- if (InternetCrackUrl (serverP->_server_url, strlen (serverP->_server_url), ICU_ESCAPE, &uc) == FALSE)
- {
- xmlrpc_env_set_fault_formatted( envP, XMLRPC_INTERNAL_ERROR,
- "Unable to parse the server URL.");
- }
- else
- {
- winInetTransactionP->nPort = (uc.nPort) ? uc.nPort : INTERNET_DEFAULT_HTTP_PORT;
- if (_strnicmp (uc.lpszScheme, "https", 5) == 0)
- winInetTransactionP->bUseSSL=TRUE;
- else
- winInetTransactionP->bUseSSL=FALSE;
- createWinInetHeaderList(envP, serverP, &winInetTransactionP->headerList);
-
- XMLRPC_MEMBLOCK_APPEND(char, envP, callXmlP, "\0", 1);
- if (!envP->fault_occurred) {
- winInetTransactionP->pSendData = XMLRPC_MEMBLOCK_CONTENTS(char, callXmlP);
- }
- }
-
-
- if (envP->fault_occurred)
+ char szExtraInfo[255];
+ char szScheme[100];
+ URL_COMPONENTS uc;
+ BOOL succeeded;
+
+ /* Init to defaults */
+ winInetTransactionP->http_status = 0;
+ winInetTransactionP->hHttpRequest = NULL;
+ winInetTransactionP->hURL = NULL;
+ winInetTransactionP->headerList = NULL;
+ winInetTransactionP->pSendData = NULL;
+ winInetTransactionP->pResponseData = responseXmlP;
+
+ /* Parse the URL and store results into the winInetTransaction */
+
+ memset(&uc, 0, sizeof(uc));
+ uc.dwStructSize = sizeof (uc);
+ uc.lpszScheme = szScheme;
+ uc.dwSchemeLength = 100;
+ uc.lpszHostName = winInetTransactionP->szHostName;
+ uc.dwHostNameLength = 255;
+ uc.lpszUrlPath = winInetTransactionP->szUrlPath;
+ uc.dwUrlPathLength = 255;
+ uc.lpszExtraInfo = szExtraInfo;
+ uc.dwExtraInfoLength = 255;
+ succeeded = InternetCrackUrl(serverP->serverUrl,
+ strlen(serverP->serverUrl),
+ ICU_ESCAPE, &uc);
+ if (!succeeded)
+ xmlrpc_faultf(envP, "Unable to parse the server URL.");
+ else {
+ winInetTransactionP->nPort =
+ uc.nPort ? uc.nPort : INTERNET_DEFAULT_HTTP_PORT;
+ if (_strnicmp(uc.lpszScheme, "https", 5) == 0)
+ winInetTransactionP->bUseSSL=TRUE;
+ else
+ winInetTransactionP->bUseSSL=FALSE;
+ createWinInetHeaderList(envP, serverP,
+ &winInetTransactionP->headerList);
+
+ XMLRPC_MEMBLOCK_APPEND(char, envP, callXmlP, "\0", 1);
+ if (!envP->fault_occurred) {
+ winInetTransactionP->pSendData =
+ XMLRPC_MEMBLOCK_CONTENTS(char, callXmlP);
+ }
+ }
+
+ if (envP->fault_occurred)
free(winInetTransactionP);
}
- *winInetTransactionPP = winInetTransactionP;
+ *winInetTranPP = winInetTransactionP;
}
@@ -213,338 +210,373 @@
static void
destroyWinInetTransaction(winInetTransaction * const winInetTransactionP) {
- XMLRPC_ASSERT_PTR_OK(winInetTransactionP);
+ XMLRPC_ASSERT_PTR_OK(winInetTransactionP);
+
+ if (winInetTransactionP->hHttpRequest)
+ InternetCloseHandle(winInetTransactionP->hHttpRequest);
- if (winInetTransactionP->hHttpRequest)
- InternetCloseHandle (winInetTransactionP->hHttpRequest);
+ if (winInetTransactionP->hURL)
+ InternetCloseHandle(winInetTransactionP->hURL);
- if (winInetTransactionP->hURL)
- InternetCloseHandle (winInetTransactionP->hURL);
+ if (winInetTransactionP->headerList)
+ free(winInetTransactionP->headerList);
- if (winInetTransactionP->headerList)
- free(winInetTransactionP->headerList);
-
- free(winInetTransactionP);
-}
-
-static void get_wininet_response ( xmlrpc_env * const envP,
- winInetTransaction * const winInetTransactionP)
-{
- INTERNET_BUFFERS inetBuffer;
- LPTSTR pMsg = NULL;
- PVOID pMsgMem = NULL;
- unsigned long dwFlags;
- unsigned long dwErr = 0;
- unsigned long nExpected = 0;
- unsigned long dwLen = sizeof (unsigned long);
- void * body = NULL;
- BOOL bOK = FALSE;
-
- inetBuffer.dwStructSize = sizeof (INTERNET_BUFFERS);
- inetBuffer.Next = NULL;
- inetBuffer.lpcszHeader = NULL;
- inetBuffer.dwHeadersTotal = inetBuffer.dwHeadersLength = 0;
- inetBuffer.dwOffsetHigh = inetBuffer.dwOffsetLow = 0;
- inetBuffer.dwBufferLength = 0;
-
- bOK = HttpQueryInfo (winInetTransactionP->hHttpRequest,
- HTTP_QUERY_CONTENT_LENGTH|HTTP_QUERY_FLAG_NUMBER,
- &inetBuffer.dwBufferTotal, &dwLen, NULL);
- if (!bOK)
- {
- dwErr = GetLastError ();
- FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM,
- NULL,
- dwErr,
- MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR) &pMsgMem,
- 1024,NULL);
-
- pMsg = (pMsgMem) ? (LPTSTR)(pMsgMem) : "Sync HttpQueryInfo failed.";
- XMLRPC_FAIL (envP, XMLRPC_NETWORK_ERROR, pMsg);
- }
+ free(winInetTransactionP);
+}
+
+
+
+static void
+get_wininet_response(xmlrpc_env * const envP,
+ winInetTransaction * const winInetTransactionP) {
+
+ unsigned long dwLen;
+ INTERNET_BUFFERS inetBuffer;
+ unsigned long dwFlags;
+ unsigned long dwErr;
+ unsigned long nExpected;
+ void * body;
+ BOOL bOK;
+ PVOID pMsgMem;
+
+ pMsgMem = NULL; /* initial value */
+ dwErr = 0; /* initial value */
+ body = NULL; /* initial value */
+ dwLen = sizeof(unsigned long); /* initial value */
+
+ inetBuffer.dwStructSize = sizeof (INTERNET_BUFFERS);
+ inetBuffer.Next = NULL;
+ inetBuffer.lpcszHeader = NULL;
+ inetBuffer.dwHeadersTotal = 0;
+ inetBuffer.dwHeadersLength = 0;
+ inetBuffer.dwOffsetHigh = 0;
+ inetBuffer.dwOffsetLow = 0;
+ inetBuffer.dwBufferLength = 0;
+
+ /* Note that while Content-Length is optional in HTTP 1.1, it is
+ required by XML-RPC. Following fails if server didn't send it.
+ */
+
+ bOK = HttpQueryInfo(winInetTransactionP->hHttpRequest,
+ HTTP_QUERY_CONTENT_LENGTH|HTTP_QUERY_FLAG_NUMBER,
+ &inetBuffer.dwBufferTotal, &dwLen, NULL);
+ if (!bOK) {
+ LPTSTR pMsg;
+ dwErr = GetLastError ();
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ dwErr,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR) &pMsgMem,
+ 1024,NULL);
+
+ pMsg = pMsgMem ? (LPTSTR)pMsgMem : "Sync HttpQueryInfo failed.";
+ XMLRPC_FAIL(envP, XMLRPC_NETWORK_ERROR, pMsg);
+ }
if (inetBuffer.dwBufferTotal == 0)
- XMLRPC_FAIL (envP, XMLRPC_NETWORK_ERROR, "WinInet returned no data");
+ XMLRPC_FAIL(envP, XMLRPC_NETWORK_ERROR, "WinInet returned no data");
- body = inetBuffer.lpvBuffer = calloc (inetBuffer.dwBufferTotal, sizeof (TCHAR));
- dwFlags = IRF_SYNC;
- inetBuffer.dwBufferLength = nExpected = inetBuffer.dwBufferTotal;
- InternetQueryDataAvailable (winInetTransactionP->hHttpRequest, &inetBuffer.dwBufferLength, 0, 0);
-
- /* Read Response from InternetFile */
- do
- {
- if (inetBuffer.dwBufferLength != 0)
- bOK = InternetReadFileEx (winInetTransactionP->hHttpRequest, &inetBuffer, dwFlags, 1);
-
- if (!bOK)
- dwErr = GetLastError ();
-
- if (dwErr)
- {
- if (dwErr == WSAEWOULDBLOCK || dwErr == ERROR_IO_PENDING)
- {
- /* Non-block socket operation wait 10 msecs */
- SleepEx (10, TRUE);
- /* Reset dwErr to zero for next pass */
- dwErr = 0;
- }
- else
- {
- FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM,
- NULL,
- dwErr,
- MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR) &pMsgMem,
- 1024,NULL);
- pMsg = (pMsgMem) ? (LPTSTR)(pMsgMem) : "ASync InternetReadFileEx failed.";
- XMLRPC_FAIL (envP, XMLRPC_NETWORK_ERROR, pMsg);
- }
- }
-
- if (inetBuffer.dwBufferLength)
- {
- TCHAR * bufptr = inetBuffer.lpvBuffer;
- bufptr += inetBuffer.dwBufferLength;
- inetBuffer.lpvBuffer = bufptr;
- nExpected -= inetBuffer.dwBufferLength;
- /* Adjust inetBuffer.dwBufferLength when it is greater than the */
- /* expected end of file */
- if (inetBuffer.dwBufferLength > nExpected)
- inetBuffer.dwBufferLength = nExpected;
-
- }
- else
- inetBuffer.dwBufferLength = nExpected;
- dwErr = 0;
- } while (nExpected != 0);
+ inetBuffer.lpvBuffer = calloc(inetBuffer.dwBufferTotal, sizeof(TCHAR));
+ body = inetBuffer.lpvBuffer;
+ dwFlags = IRF_SYNC;
+ nExpected = inetBuffer.dwBufferTotal;
+ inetBuffer.dwBufferLength = nExpected;
+ InternetQueryDataAvailable(winInetTransactionP->hHttpRequest,
+ &inetBuffer.dwBufferLength, 0, 0);
+
+ /* Read Response from InternetFile */
+ do {
+ if (inetBuffer.dwBufferLength != 0)
+ bOK = InternetReadFileEx(winInetTransactionP->hHttpRequest,
+ &inetBuffer, dwFlags, 1);
+
+ if (!bOK)
+ dwErr = GetLastError();
+
+ if (dwErr) {
+ if (dwErr == WSAEWOULDBLOCK || dwErr == ERROR_IO_PENDING) {
+ /* Non-block socket operation wait 10 msecs */
+ SleepEx(10, TRUE);
+ /* Reset dwErr to zero for next pass */
+ dwErr = 0;
+ } else {
+ LPTSTR pMsg;
+ FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ dwErr,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR) &pMsgMem,
+ 1024,NULL);
+ pMsg = pMsgMem ?
+ (LPTSTR)pMsgMem : "ASync InternetReadFileEx failed.";
+ XMLRPC_FAIL(envP, XMLRPC_NETWORK_ERROR, pMsg);
+ }
+ }
+
+ if (inetBuffer.dwBufferLength) {
+ TCHAR * const oldBufptr = inetBuffer.lpvBuffer;
+ inetBuffer.lpvBuffer = oldBufptr + inetBuffer.dwBufferLength;
+ nExpected -= inetBuffer.dwBufferLength;
+ /* Adjust inetBuffer.dwBufferLength when it is greater than the */
+ /* expected end of file */
+ if (inetBuffer.dwBufferLength > nExpected)
+ inetBuffer.dwBufferLength = nExpected;
+
+ } else
+ inetBuffer.dwBufferLength = nExpected;
+ dwErr = 0;
+ } while (nExpected != 0);
/* Add to the response buffer. */
- xmlrpc_mem_block_append(envP, winInetTransactionP->pResponseData, body, inetBuffer.dwBufferTotal);
- XMLRPC_FAIL_IF_FAULT (envP);
+ xmlrpc_mem_block_append(envP, winInetTransactionP->pResponseData, body,
+ inetBuffer.dwBufferTotal);
+ XMLRPC_FAIL_IF_FAULT(envP);
cleanup:
- /* Since the XMLRPC_FAIL calls goto cleanup, we must handle */
- /* the free'ing of the memory here. */
- if (pMsgMem != NULL)
- {
- LocalFree( pMsgMem );
- }
+ /* Since the XMLRPC_FAIL calls goto cleanup, we must handle */
+ /* the free'ing of the memory here. */
+ if (pMsgMem != NULL)
+ LocalFree(pMsgMem);
- if (body)
- free (body);
+ if (body)
+ free(body);
}
+
static void
-performWinInetTransaction(xmlrpc_env * const envP,
- winInetTransaction * const winInetTransactionP,
- struct xmlrpc_client_transport * const clientTransportP) {
- LPTSTR pMsg = NULL;
- LPVOID pMsgMem = NULL;
-
- unsigned long lastErr;
- unsigned long reqFlags = INTERNET_FLAG_NO_UI;
- char * acceptTypes[] = {"text/xml", NULL};
- unsigned long queryLen = sizeof (unsigned long);
-
- winInetTransactionP->hURL = InternetConnect (hSyncInternetSession,
- winInetTransactionP->szHostName, winInetTransactionP->nPort,
- NULL, NULL, INTERNET_SERVICE_HTTP, 0, 1);
-
- /* Start our request running. */
- if (winInetTransactionP->bUseSSL == TRUE)
- reqFlags |= INTERNET_FLAG_SECURE |INTERNET_FLAG_IGNORE_CERT_CN_INVALID;
-
- winInetTransactionP->hHttpRequest = HttpOpenRequest (winInetTransactionP->hURL, "POST",
- winInetTransactionP->szUrlPath, "HTTP/1.1", NULL, (const char **)&acceptTypes,
- reqFlags, 1);
-
- XMLRPC_FAIL_IF_NULL(winInetTransactionP->hHttpRequest,envP, XMLRPC_INTERNAL_ERROR,
- "Unable to open the requested URL.");
-
- if ( HttpAddRequestHeaders (winInetTransactionP->hHttpRequest, winInetTransactionP->headerList,
- strlen (winInetTransactionP->headerList), HTTP_ADDREQ_FLAG_ADD|HTTP_ADDREQ_FLAG_REPLACE ) ==FALSE)
- {
- XMLRPC_FAIL (envP, XMLRPC_INTERNAL_ERROR, "Could not set Content-Type.");
- }
-
-#ifdef DEBUG
- /* Provide the user with transport status information */
- InternetSetStatusCallback (winInetTransactionP->hHttpRequest, statusCallback);
-#endif
+performWinInetTransaction(
+ xmlrpc_env * const envP,
+ winInetTransaction * const winInetTransactionP,
+ struct xmlrpc_client_transport * const clientTransportP) {
+
+ const char * const acceptTypes[] = {"text/xml", NULL};
+
+ unsigned long queryLen;
+ LPVOID pMsgMem;
+ BOOL succeeded;
+
+ unsigned long lastErr;
+ unsigned long reqFlags;
+
+ pMsgMem = NULL; /* initial value */
+
+ reqFlags = INTERNET_FLAG_NO_UI; /* initial value */
+
+ winInetTransactionP->hURL =
+ InternetConnect(hSyncInternetSession,
+ winInetTransactionP->szHostName,
+ winInetTransactionP->nPort,
+ NULL, NULL, INTERNET_SERVICE_HTTP, 0, 1);
+
+ /* Start our request running. */
+ if (winInetTransactionP->bUseSSL == TRUE)
+ reqFlags |=
+ INTERNET_FLAG_SECURE | INTERNET_FLAG_IGNORE_CERT_CN_INVALID;
+
+ winInetTransactionP->hHttpRequest =
+ HttpOpenRequest(winInetTransactionP->hURL, "POST",
+ winInetTransactionP->szUrlPath, "HTTP/1.1", NULL,
+ (const char **)&acceptTypes,
+ reqFlags, 1);
+
+ XMLRPC_FAIL_IF_NULL(winInetTransactionP->hHttpRequest, envP,
+ XMLRPC_INTERNAL_ERROR,
+ "Unable to open the requested URL.");
+
+ succeeded =
+ HttpAddRequestHeaders(winInetTransactionP->hHttpRequest,
+ winInetTransactionP->headerList,
+ strlen (winInetTransactionP->headerList),
+ HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE);
+
+ if (!succeeded)
+ XMLRPC_FAIL(envP, XMLRPC_INTERNAL_ERROR,
+ "Could not set Content-Type.");
Again:
- /* Send the requested XML remote procedure command */
- if (HttpSendRequest (winInetTransactionP->hHttpRequest, NULL, 0,
- winInetTransactionP->pSendData,
- strlen(winInetTransactionP->pSendData))==FALSE)
- {
- lastErr = GetLastError ();
-
- FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- lastErr,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR) &pMsgMem,
- 0, NULL);
-
-
- if (pMsgMem == NULL)
- {
- switch (lastErr)
- {
- case ERROR_INTERNET_CANNOT_CONNECT:
- pMsg = "Sync HttpSendRequest failed: Connection refused.";
- break;
- case ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED:
- pMsg = "Sync HttpSendRequest failed: Client authorization certificate needed.";
- break;
-
- /* The following conditions are recommendations that microsoft */
- /* provides in their knowledge base. */
-
- /* HOWTO: Handle Invalid Certificate Authority Error with WinInet (Q182888) */
- case ERROR_INTERNET_INVALID_CA:
- if (clientTransportP->allowInvalidSSLCerts){
- OutputDebugString ("Sync HttpSendRequest failed: "
- "The function is unfamiliar with the certificate "
- "authority that generated the server's certificate. ");
- reqFlags = SECURITY_FLAG_IGNORE_UNKNOWN_CA;
-
- InternetSetOption (winInetTransactionP->hHttpRequest, INTERNET_OPTION_SECURITY_FLAGS,
- &reqFlags, sizeof (reqFlags));
-
- goto Again;
- }
- else{
- pMsg = "Invalid or unknown/untrusted SSL Certificate Authority.";
- }
- break;
-
- /* HOWTO: Make SSL Requests Using WinInet (Q168151) */
- case ERROR_INTERNET_SEC_CERT_CN_INVALID:
- if (clientTransportP->allowInvalidSSLCerts){
- OutputDebugString ("Sync HttpSendRequest failed: "
- "The SSL certificate common name (host name field) is incorrect\r\n "
- "for example, if you entered www.server.com and the common name "
- "on the certificate says www.different.com. ");
-
- reqFlags = INTERNET_FLAG_IGNORE_CERT_CN_INVALID;
-
- InternetSetOption (winInetTransactionP->hHttpRequest, INTERNET_OPTION_SECURITY_FLAGS,
- &reqFlags, sizeof (reqFlags));
-
- goto Again;
- }
- else{
- pMsg = "The SSL certificate common name (host name field) is incorrect.";
- }
- break;
-
- case ERROR_INTERNET_SEC_CERT_DATE_INVALID:
- if (clientTransportP->allowInvalidSSLCerts){
- OutputDebugString ("Sync HttpSendRequest failed: "
- "The SSL certificate date that was received from the server is "
- "bad. The certificate is expired. ");
-
- reqFlags = INTERNET_FLAG_IGNORE_CERT_DATE_INVALID;
-
- InternetSetOption (winInetTransactionP->hHttpRequest, INTERNET_OPTION_SECURITY_FLAGS,
- &reqFlags, sizeof (reqFlags));
-
- goto Again;
- }
- else{
- pMsg = "The SSL certificate date that was received from the server is invalid.";
- }
- break;
-
- default:
- pMsg = (LPTSTR)pMsgMem = LocalAlloc (LPTR, MAX_PATH);
- sprintf (pMsg, "Sync HttpSendRequest failed: GetLastError (%d)", lastErr);
- break;
-
- }
- }
- else
- {
- pMsg = (LPTSTR)(pMsgMem);
-
- }
- XMLRPC_FAIL (envP, XMLRPC_NETWORK_ERROR, pMsg);
-
- }
-
- if( HttpQueryInfo (winInetTransactionP->hHttpRequest,
- HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_STATUS_CODE,
- &winInetTransactionP->http_status, &queryLen, NULL) == FALSE)
- {
- lastErr = GetLastError ();
- FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM,
- NULL,
- lastErr,
- MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR) &pMsgMem,
- 1024,NULL);
+ /* Send the requested XML remote procedure command */
+ succeeded = HttpSendRequest(winInetTransactionP->hHttpRequest, NULL, 0,
+ winInetTransactionP->pSendData,
+ strlen(winInetTransactionP->pSendData));
+ if (!succeeded) {
+ LPTSTR pMsg;
+
+ lastErr = GetLastError();
+
+ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ lastErr,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR) &pMsgMem,
+ 0, NULL);
+
+ if (pMsgMem == NULL) {
+ switch (lastErr) {
+ case ERROR_INTERNET_CANNOT_CONNECT:
+ pMsg = "Sync HttpSendRequest failed: Connection refused.";
+ break;
+ case ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED:
+ pMsg = "Sync HttpSendRequest failed: "
+ "Client authorization certificate needed.";
+ break;
+
+ /* The following conditions are recommendations that microsoft */
+ /* provides in their knowledge base. */
+
+ /* HOWTO: Handle Invalid Certificate Authority Error with
+ WinInet (Q182888)
+ */
+ case ERROR_INTERNET_INVALID_CA:
+ if (clientTransportP->allowInvalidSSLCerts){
+ OutputDebugString(
+ "Sync HttpSendRequest failed: "
+ "The function is unfamiliar with the certificate "
+ "authority that generated the server's certificate. ");
+ reqFlags = SECURITY_FLAG_IGNORE_UNKNOWN_CA;
+
+ InternetSetOption(winInetTransactionP->hHttpRequest,
+ INTERNET_OPTION_SECURITY_FLAGS,
+ &reqFlags, sizeof(reqFlags));
+
+ goto Again;
+ } else
+ pMsg = "Invalid or unknown/untrusted "
+ "SSL Certificate Authority.";
+ break;
+
+ /* HOWTO: Make SSL Requests Using WinInet (Q168151) */
+ case ERROR_INTERNET_SEC_CERT_CN_INVALID:
+ if (clientTransportP->allowInvalidSSLCerts) {
+ OutputDebugString(
+ "Sync HttpSendRequest failed: "
+ "The SSL certificate common name (host name field) "
+ "is incorrect\r\n "
+ "for example, if you entered www.server.com "
+ "and the common name "
+ "on the certificate says www.different.com. ");
+
+ reqFlags = INTERNET_FLAG_IGNORE_CERT_CN_INVALID;
+
+ InternetSetOption(winInetTransactionP->hHttpRequest,
+ INTERNET_OPTION_SECURITY_FLAGS,
+ &reqFlags, sizeof(reqFlags));
+
+ goto Again;
+ } else
+ pMsg = "The SSL certificate common name "
+ "(host name field) is incorrect.";
+ break;
+
+ case ERROR_INTERNET_SEC_CERT_DATE_INVALID:
+ if (clientTransportP->allowInvalidSSLCerts) {
+ OutputDebugString(
+ "Sync HttpSendRequest failed: "
+ "The SSL certificate date that was received "
+ "from the server is "
+ "bad. The certificate is expired. ");
+
+ reqFlags = INTERNET_FLAG_IGNORE_CERT_DATE_INVALID;
+
+ InternetSetOption(winInetTransactionP->hHttpRequest,
+ INTERNET_OPTION_SECURITY_FLAGS,
+ &reqFlags, sizeof(reqFlags));
+
+ goto Again;
+ } else
+ pMsg = "The SSL certificate date that was received "
+ "from the server is invalid.";
+ break;
+
+ default:
+ pMsg = (LPTSTR)pMsgMem = LocalAlloc(LPTR, MAX_PATH);
+ sprintf(pMsg, "Sync HttpSendRequest failed: "
+ "GetLastError (%d)", lastErr);
+ break;
- pMsg = (pMsgMem) ? (LPTSTR)(pMsgMem) : "Sync HttpQueryInfo failed.";
- XMLRPC_FAIL (envP, XMLRPC_NETWORK_ERROR, pMsg);
+ }
+ } else
+ pMsg = (LPTSTR)pMsgMem;
+
+ XMLRPC_FAIL(envP, XMLRPC_NETWORK_ERROR, pMsg);
+ }
+
+ queryLen = sizeof(unsigned long); /* initial value */
- }
+ succeeded = HttpQueryInfo(winInetTransactionP->hHttpRequest,
+ HTTP_QUERY_FLAG_NUMBER | HTTP_QUERY_STATUS_CODE,
+ &winInetTransactionP->http_status,
+ &queryLen, NULL);
+ if (!succeeded) {
+ LPTSTR pMsg;
+
+ lastErr = GetLastError();
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ lastErr,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR) &pMsgMem,
+ 1024, NULL);
+
+ pMsg = pMsgMem ? (LPTSTR)pMsgMem : "Sync HttpQueryInfo failed.";
+ XMLRPC_FAIL(envP, XMLRPC_NETWORK_ERROR, pMsg);
+ }
/* Make sure we got a "200 OK" message from the remote server. */
- if(winInetTransactionP->http_status!=200)
- {
- unsigned long msgLen = 1024;
- char errMsg [1024];
- *errMsg = 0;
- HttpQueryInfo (winInetTransactionP->hHttpRequest, HTTP_QUERY_STATUS_TEXT, errMsg, &msgLen, NULL);
-
- /* Set our fault. We break this into multiple lines because it */
- /* will generally contain line breaks to begin with. */
- xmlrpc_env_set_fault_formatted (envP, XMLRPC_NETWORK_ERROR,
- "HTTP error #%d occurred\n %s", winInetTransactionP->http_status, errMsg);
- goto cleanup;
-
- }
- /* Read the response. */
- get_wininet_response (envP, winInetTransactionP);
- XMLRPC_FAIL_IF_FAULT (envP);
+ if (winInetTransactionP->http_status != 200) {
+ unsigned long msgLen;
+ char errMsg[1024];
+ errMsg[0] = '\0';
+ msgLen = 1024; /* initial value */
- cleanup:
- /* Since the XMLRPC_FAIL calls goto cleanup, we must handle */
- /* the free'ing of the memory here. */
- if (pMsgMem != NULL)
- {
- LocalFree( pMsgMem );
- }
+ HttpQueryInfo(winInetTransactionP->hHttpRequest,
+ HTTP_QUERY_STATUS_TEXT, errMsg, &msgLen, NULL);
+ xmlrpc_env_set_fault_formatted(
+ envP, XMLRPC_NETWORK_ERROR,
+ "HTTP error #%d occurred\n %s",
+ winInetTransactionP->http_status, errMsg);
+ goto cleanup;
+ }
+ /* Read the response. */
+ get_wininet_response(envP, winInetTransactionP);
+ XMLRPC_FAIL_IF_FAULT(envP);
+
+ cleanup:
+ /* Since the XMLRPC_FAIL calls goto cleanup, we must handle */
+ /* the free'ing of the memory here. */
+ if (pMsgMem)
+ LocalFree(pMsgMem);
}
+
+
static unsigned __stdcall
-doAsyncRpc(void * arg) {
+doAsyncRpc(void * const arg) {
rpc * const rpcP = arg;
xmlrpc_env env;
xmlrpc_env_init(&env);
- performWinInetTransaction(&env, rpcP->winInetTransactionP, rpcP->clientTransportP );
+ performWinInetTransaction(&env, rpcP->winInetTransactionP,
+ rpcP->clientTransportP );
rpcP->complete(rpcP->callInfoP, rpcP->responseXmlP, env);
xmlrpc_env_clean(&env);
+
return 0;
}
+
static void
-createRpcThread(xmlrpc_env * const envP,
- rpc * const rpcP,
- pthread_t * const threadP) {
+createRpcThread(xmlrpc_env * const envP,
+ rpc * const rpcP,
+ pthread_t * const threadP) {
int rc;
@@ -553,54 +585,49 @@
case 0:
break;
case EAGAIN:
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR,
- "pthread_create() failed: System Resources exceeded.");
+ xmlrpc_faultf(envP, "pthread_create() failed: "
+ "System Resources exceeded.");
break;
case EINVAL:
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR,
- "pthread_create() failed: Param Error for attr.");
+ xmlrpc_faultf(envP, "pthread_create() failed: "
+ "Param Error for attr.");
break;
case ENOMEM:
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR,
- "pthread_create() failed: No memory for new thread.");
+ xmlrpc_faultf(envP, "pthread_create() failed: "
+ "No memory for new thread.");
break;
default:
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR,
- "pthread_create() failed: Unrecognized error code %d.", rc);
+ xmlrpc_faultf(envP, "pthread_create() failed: "
+ "Unrecognized error code %d.", rc);
break;
}
}
+
+
static void
-rpcCreate(xmlrpc_env * const envP,
+rpcCreate(xmlrpc_env * const envP,
struct xmlrpc_client_transport * const clientTransportP,
- const xmlrpc_server_info * const serverP,
- xmlrpc_mem_block * const callXmlP,
- xmlrpc_mem_block * const responseXmlP,
- xmlrpc_transport_asynch_complete complete,
- struct xmlrpc_call_info * const callInfoP,
- rpc ** const rpcPP) {
+ const xmlrpc_server_info * const serverP,
+ xmlrpc_mem_block * const callXmlP,
+ xmlrpc_mem_block * const responseXmlP,
+ xmlrpc_transport_asynch_complete complete,
+ struct xmlrpc_call_info * const callInfoP,
+ rpc ** const rpcPP) {
rpc * rpcP;
MALLOCVAR(rpcP);
if (rpcP == NULL)
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR,
- "Couldn't allocate memory for rpc object");
+ xmlrpc_faultf(envP, "Couldn't allocate memory for rpc object");
else {
- rpcP->callInfoP = callInfoP;
- rpcP->complete = complete;
+ rpcP->callInfoP = callInfoP;
+ rpcP->complete = complete;
rpcP->responseXmlP = responseXmlP;
rpcP->threadExists = FALSE;
- createWinInetTransaction(envP, serverP,
- callXmlP, responseXmlP,
- &rpcP->winInetTransactionP);
+ createWinInetTransaction(envP, serverP, callXmlP, responseXmlP,
+ &rpcP->winInetTransactionP);
if (!envP->fault_occurred) {
if (complete) {
createRpcThread(envP, rpcP, &rpcP->thread);
@@ -622,6 +649,8 @@
*rpcPP = rpcP;
}
+
+
static void
rpcDestroy(rpc * const rpcP) {
@@ -635,6 +664,8 @@
free(rpcP);
}
+
+
static void *
finishRpc(struct list_head * const headerP,
void * const context ATTR_UNUSED) {
@@ -642,7 +673,7 @@
rpc * const rpcP = headerP->itemP;
if (rpcP->threadExists) {
- void *status;
+ void * status;
int result;
result = pthread_join(rpcP->thread, &status);
@@ -659,148 +690,154 @@
/* Used for debugging purposes to track the status of
-** your request. */
-void CALLBACK statusCallback (HINTERNET hInternet,
- unsigned long dwContext,
- unsigned long dwInternetStatus,
- void * lpvStatusInformation,
- unsigned long dwStatusInformationLength)
-{
- switch (dwInternetStatus)
- {
- case INTERNET_STATUS_RESOLVING_NAME:
- OutputDebugString("INTERNET_STATUS_RESOLVING_NAME\r\n");
- break;
-
- case INTERNET_STATUS_NAME_RESOLVED:
- OutputDebugString("INTERNET_STATUS_NAME_RESOLVED\r\n");
- break;
-
- case INTERNET_STATUS_HANDLE_CREATED:
- OutputDebugString("INTERNET_STATUS_HANDLE_CREATED\r\n");
- break;
-
- case INTERNET_STATUS_CONNECTING_TO_SERVER:
- OutputDebugString("INTERNET_STATUS_CONNECTING_TO_SERVER\r\n");
- break;
-
- case INTERNET_STATUS_REQUEST_SENT:
- OutputDebugString("INTERNET_STATUS_REQUEST_SENT\r\n");
- break;
-
- case INTERNET_STATUS_SENDING_REQUEST:
- OutputDebugString("INTERNET_STATUS_SENDING_REQUEST\r\n");
- break;
-
- case INTERNET_STATUS_CONNECTED_TO_SERVER:
- OutputDebugString("INTERNET_STATUS_CONNECTED_TO_SERVER\r\n");
- break;
-
- case INTERNET_STATUS_RECEIVING_RESPONSE:
- OutputDebugString("INTERNET_STATUS_RECEIVING_RESPONSE\r\n");
- break;
-
- case INTERNET_STATUS_RESPONSE_RECEIVED:
- OutputDebugString("INTERNET_STATUS_RESPONSE_RECEIVED\r\n");
- break;
-
- case INTERNET_STATUS_CLOSING_CONNECTION:
- OutputDebugString("INTERNET_STATUS_CLOSING_CONNECTION\r\n");
- break;
-
- case INTERNET_STATUS_CONNECTION_CLOSED:
- OutputDebugString("INTERNET_STATUS_CONNECTION_CLOSED\r\n");
- break;
-
- case INTERNET_STATUS_HANDLE_CLOSING:
- OutputDebugString("INTERNET_STATUS_HANDLE_CLOSING\r\n");
- break;
-
- case INTERNET_STATUS_CTL_RESPONSE_RECEIVED:
- OutputDebugString("INTERNET_STATUS_CTL_RESPONSE_RECEIVED\r\n");
- break;
-
- case INTERNET_STATUS_REDIRECT:
- OutputDebugString("INTERNET_STATUS_REDIRECT\r\n");
- break;
-
- case INTERNET_STATUS_REQUEST_COMPLETE:
- /* This indicates the data is ready. */
- OutputDebugString("INTERNET_STATUS_REQUEST_COMPLETE\r\n");
- break;
-
- default:
- OutputDebugString("statusCallback, default case!\r\n");
- break;
+ your request.
+*/
+void CALLBACK
+statusCallback (HINTERNET const hInternet,
+ unsigned long const dwContext,
+ unsigned long const dwInternetStatus,
+ void * const lpvStatusInformation,
+ unsigned long const dwStatusInformationLength) {
+
+ switch (dwInternetStatus) {
+ case INTERNET_STATUS_RESOLVING_NAME:
+ OutputDebugString("INTERNET_STATUS_RESOLVING_NAME\r\n");
+ break;
+
+ case INTERNET_STATUS_NAME_RESOLVED:
+ OutputDebugString("INTERNET_STATUS_NAME_RESOLVED\r\n");
+ break;
+
+ case INTERNET_STATUS_HANDLE_CREATED:
+ OutputDebugString("INTERNET_STATUS_HANDLE_CREATED\r\n");
+ break;
+
+ case INTERNET_STATUS_CONNECTING_TO_SERVER:
+ OutputDebugString("INTERNET_STATUS_CONNECTING_TO_SERVER\r\n");
+ break;
+
+ case INTERNET_STATUS_REQUEST_SENT:
+ OutputDebugString("INTERNET_STATUS_REQUEST_SENT\r\n");
+ break;
+
+ case INTERNET_STATUS_SENDING_REQUEST:
+ OutputDebugString("INTERNET_STATUS_SENDING_REQUEST\r\n");
+ break;
+
+ case INTERNET_STATUS_CONNECTED_TO_SERVER:
+ OutputDebugString("INTERNET_STATUS_CONNECTED_TO_SERVER\r\n");
+ break;
+
+ case INTERNET_STATUS_RECEIVING_RESPONSE:
+ OutputDebugString("INTERNET_STATUS_RECEIVING_RESPONSE\r\n");
+ break;
+
+ case INTERNET_STATUS_RESPONSE_RECEIVED:
+ OutputDebugString("INTERNET_STATUS_RESPONSE_RECEIVED\r\n");
+ break;
+
+ case INTERNET_STATUS_CLOSING_CONNECTION:
+ OutputDebugString("INTERNET_STATUS_CLOSING_CONNECTION\r\n");
+ break;
+
+ case INTERNET_STATUS_CONNECTION_CLOSED:
+ OutputDebugString("INTERNET_STATUS_CONNECTION_CLOSED\r\n");
+ break;
+
+ case INTERNET_STATUS_HANDLE_CLOSING:
+ OutputDebugString("INTERNET_STATUS_HANDLE_CLOSING\r\n");
+ break;
+
+ case INTERNET_STATUS_CTL_RESPONSE_RECEIVED:
+ OutputDebugString("INTERNET_STATUS_CTL_RESPONSE_RECEIVED\r\n");
+ break;
+
+ case INTERNET_STATUS_REDIRECT:
+ OutputDebugString("INTERNET_STATUS_REDIRECT\r\n");
+ break;
+
+ case INTERNET_STATUS_REQUEST_COMPLETE:
+ /* This indicates the data is ready. */
+ OutputDebugString("INTERNET_STATUS_REQUEST_COMPLETE\r\n");
+ break;
+
+ default:
+ OutputDebugString("statusCallback, default case!\r\n");
+ break;
}
}
+
+
static void
-create(xmlrpc_env * const envP,
- int const flags ATTR_UNUSED,
- const char * const appname ATTR_UNUSED,
- const char * const appversion ATTR_UNUSED,
- const struct xmlrpc_xportparms * const transportparmsP,
- size_t const parm_size,
+create(xmlrpc_env * const envP,
+ int const flags ATTR_UNUSED,
+ const char * const appname ATTR_UNUSED,
+ const char * const appversion ATTR_UNUSED,
+ const void * const transportparmsP,
+ size_t const parm_size,
struct xmlrpc_client_transport ** const handlePP) {
/*----------------------------------------------------------------------------
This does the 'create' operation for a WinInet client transport.
-----------------------------------------------------------------------------*/
- struct xmlrpc_client_transport * transportP;
+ const struct xmlrpc_wininet_xportparms * const wininetXportParmsP =
+ transportparmsP;
- struct xmlrpc_wininet_xportparms * const wininetXportParmsP =
- (struct xmlrpc_wininet_xportparms *) transportparmsP;
+ struct xmlrpc_client_transport * transportP;
MALLOCVAR(transportP);
if (transportP == NULL)
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR,
- "Unable to allocate transport descriptor.");
+ xmlrpc_faultf(envP, "Unable to allocate transport descriptor.");
else {
pthread_mutex_init(&transportP->listLock, NULL);
list_make_empty(&transportP->rpcList);
- if (hSyncInternetSession == NULL)
- hSyncInternetSession = InternetOpen ("xmlrpc-c wininet transport",
- INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
-
- if (!wininetXportParmsP || parm_size < XMLRPC_WXPSIZE(allowInvalidSSLCerts))
- transportP->allowInvalidSSLCerts = 0;
- else
- transportP->allowInvalidSSLCerts = wininetXportParmsP->allowInvalidSSLCerts;
+ if (hSyncInternetSession == NULL)
+ hSyncInternetSession =
+ InternetOpen("xmlrpc-c wininet transport",
+ INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
+
+ if (!wininetXportParmsP ||
+ parm_size < XMLRPC_WXPSIZE(allowInvalidSSLCerts))
+ transportP->allowInvalidSSLCerts = 0;
+ else
+ transportP->allowInvalidSSLCerts =
+ wininetXportParmsP->allowInvalidSSLCerts;
*handlePP = transportP;
}
}
+
static void
destroy(struct xmlrpc_client_transport * const clientTransportP) {
/*----------------------------------------------------------------------------
This does the 'destroy' operation for a WinInet client transport.
-----------------------------------------------------------------------------*/
- XMLRPC_ASSERT(clientTransportP != NULL);
+ XMLRPC_ASSERT(clientTransportP != NULL);
XMLRPC_ASSERT(list_is_empty(&clientTransportP->rpcList));
- if (hSyncInternetSession)
- InternetCloseHandle(hSyncInternetSession);
- hSyncInternetSession = NULL;
+ if (hSyncInternetSession)
+ InternetCloseHandle(hSyncInternetSession);
+ hSyncInternetSession = NULL;
- pthread_mutex_destroy(&clientTransportP->listLock);
+ pthread_mutex_destroy(&clientTransportP->listLock);
- free(clientTransportP);
+ free(clientTransportP);
}
+
static void
-sendRequest(xmlrpc_env * const envP,
+sendRequest(xmlrpc_env * const envP,
struct xmlrpc_client_transport * const clientTransportP,
- const xmlrpc_server_info * const serverP,
- xmlrpc_mem_block * const callXmlP,
- xmlrpc_transport_asynch_complete complete,
- struct xmlrpc_call_info * const callInfoP) {
+ const xmlrpc_server_info * const serverP,
+ xmlrpc_mem_block * const callXmlP,
+ xmlrpc_transport_asynch_complete complete,
+ struct xmlrpc_call_info * const callInfoP) {
/*----------------------------------------------------------------------------
Initiate an XML-RPC rpc asynchronously. Don't wait for it to go to
the server.
@@ -827,10 +864,12 @@
*/
}
+
+
static void
finishAsynch(struct xmlrpc_client_transport * const clientTransportP,
- xmlrpc_timeoutType const timeoutType ATTR_UNUSED,
- xmlrpc_timeout const timeout ATTR_UNUSED) {
+ xmlrpc_timeoutType const timeoutType ATTR_UNUSED,
+ xmlrpc_timeout const timeout ATTR_UNUSED) {
/*----------------------------------------------------------------------------
Wait for the threads of all outstanding RPCs to exit and destroy those
RPCs.
@@ -849,14 +888,14 @@
}
+
static void
-call(xmlrpc_env * const envP,
+call(xmlrpc_env * const envP,
struct xmlrpc_client_transport * const clientTransportP,
- const xmlrpc_server_info * const serverP,
- xmlrpc_mem_block * const callXmlP,
- xmlrpc_mem_block ** const responsePP) {
+ const xmlrpc_server_info * const serverP,
+ xmlrpc_mem_block * const callXmlP,
+ xmlrpc_mem_block ** const responsePP) {
-
xmlrpc_mem_block * responseXmlP;
rpc * rpcP;
@@ -870,7 +909,8 @@
rpcCreate(envP, clientTransportP, serverP, callXmlP, responseXmlP,
NULL, NULL, &rpcP);
if (!envP->fault_occurred) {
- performWinInetTransaction(envP, rpcP->winInetTransactionP, clientTransportP);
+ performWinInetTransaction(envP, rpcP->winInetTransactionP,
+ clientTransportP);
*responsePP = responseXmlP;
@@ -882,14 +922,20 @@
}
+
struct xmlrpc_client_transport_ops xmlrpc_wininet_transport_ops = {
+ NULL,
+ NULL,
&create,
&destroy,
&sendRequest,
&call,
&finishAsynch,
+ NULL,
};
+
+
/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
Added: freeswitch/trunk/libs/xmlrpc-c/missing
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/missing Fri May 23 16:56:24 2008
@@ -0,0 +1,190 @@
+#! /bin/sh
+# Common stub for a few missing GNU programs while installing.
+# Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+# Franc,ois Pinard <pinard at iro.umontreal.ca>, 1996.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+if test $# -eq 0; then
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+fi
+
+case "$1" in
+
+ -h|--h|--he|--hel|--help)
+ echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+error status if there is no known handling for PROGRAM.
+
+Options:
+ -h, --help display this help and exit
+ -v, --version output version information and exit
+
+Supported PROGRAM values:
+ aclocal touch file \`aclocal.m4'
+ autoconf touch file \`configure'
+ autoheader touch file \`config.h.in'
+ automake touch all \`Makefile.in' files
+ bison create \`y.tab.[ch]', if possible, from existing .[ch]
+ flex create \`lex.yy.c', if possible, from existing .c
+ lex create \`lex.yy.c', if possible, from existing .c
+ makeinfo touch the output file
+ yacc create \`y.tab.[ch]', if possible, from existing .[ch]"
+ ;;
+
+ -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+ echo "missing - GNU libit 0.0"
+ ;;
+
+ -*)
+ echo 1>&2 "$0: Unknown \`$1' option"
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+ ;;
+
+ aclocal)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`acinclude.m4' or \`configure.in'. You might want
+ to install the \`Automake' and \`Perl' packages. Grab them from
+ any GNU archive site."
+ touch aclocal.m4
+ ;;
+
+ autoconf)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`configure.in'. You might want to install the
+ \`Autoconf' and \`GNU m4' packages. Grab them from any GNU
+ archive site."
+ touch configure
+ ;;
+
+ autoheader)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`acconfig.h' or \`configure.in'. You might want
+ to install the \`Autoconf' and \`GNU m4' packages. Grab them
+ from any GNU archive site."
+ files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' configure.in`
+ test -z "$files" && files="config.h"
+ touch_files=
+ for f in $files; do
+ case "$f" in
+ *:*) touch_files="$touch_files "`echo "$f" |
+ sed -e 's/^[^:]*://' -e 's/:.*//'`;;
+ *) touch_files="$touch_files $f.in";;
+ esac
+ done
+ touch $touch_files
+ ;;
+
+ automake)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`Makefile.am', \`acinclude.m4' or \`configure.in'.
+ You might want to install the \`Automake' and \`Perl' packages.
+ Grab them from any GNU archive site."
+ find . -type f -name Makefile.am -print |
+ sed 's/\.am$/.in/' |
+ while read f; do touch "$f"; done
+ ;;
+
+ bison|yacc)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified a \`.y' file. You may need the \`Bison' package
+ in order for those modifications to take effect. You can get
+ \`Bison' from any GNU archive site."
+ rm -f y.tab.c y.tab.h
+ if [ $# -ne 1 ]; then
+ eval LASTARG="\${$#}"
+ case "$LASTARG" in
+ *.y)
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
+ if [ -f "$SRCFILE" ]; then
+ cp "$SRCFILE" y.tab.c
+ fi
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
+ if [ -f "$SRCFILE" ]; then
+ cp "$SRCFILE" y.tab.h
+ fi
+ ;;
+ esac
+ fi
+ if [ ! -f y.tab.h ]; then
+ echo >y.tab.h
+ fi
+ if [ ! -f y.tab.c ]; then
+ echo 'main() { return 0; }' >y.tab.c
+ fi
+ ;;
+
+ lex|flex)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified a \`.l' file. You may need the \`Flex' package
+ in order for those modifications to take effect. You can get
+ \`Flex' from any GNU archive site."
+ rm -f lex.yy.c
+ if [ $# -ne 1 ]; then
+ eval LASTARG="\${$#}"
+ case "$LASTARG" in
+ *.l)
+ SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
+ if [ -f "$SRCFILE" ]; then
+ cp "$SRCFILE" lex.yy.c
+ fi
+ ;;
+ esac
+ fi
+ if [ ! -f lex.yy.c ]; then
+ echo 'main() { return 0; }' >lex.yy.c
+ fi
+ ;;
+
+ makeinfo)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified a \`.texi' or \`.texinfo' file, or any other file
+ indirectly affecting the aspect of the manual. The spurious
+ call might also be the consequence of using a buggy \`make' (AIX,
+ DU, IRIX). You might want to install the \`Texinfo' package or
+ the \`GNU make' package. Grab either from any GNU archive site."
+ file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
+ if test -z "$file"; then
+ file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
+ file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file`
+ fi
+ touch $file
+ ;;
+
+ *)
+ echo 1>&2 "\
+WARNING: \`$1' is needed, and you do not seem to have it handy on your
+ system. You might have modified some files without having the
+ proper tools for further handling them. Check the \`README' file,
+ it often tells you about the needed prerequirements for installing
+ this package. You may also peek at any GNU archive site, in case
+ some other package would contain this missing \`$1' program."
+ exit 1
+ ;;
+esac
+
+exit 0
Modified: freeswitch/trunk/libs/xmlrpc-c/mkinstalldirs
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/mkinstalldirs (original)
+++ freeswitch/trunk/libs/xmlrpc-c/mkinstalldirs Fri May 23 16:56:24 2008
@@ -4,7 +4,7 @@
# Created: 1993-05-16
# Public domain
-# $Id: mkinstalldirs,v 1.1 2004/10/16 21:41:08 giraffedata Exp $
+# $Id: mkinstalldirs,v 1.13 1999/01/05 03:18:55 bje Exp $
errstatus=0
Modified: freeswitch/trunk/libs/xmlrpc-c/src/Makefile
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/src/Makefile (original)
+++ freeswitch/trunk/libs/xmlrpc-c/src/Makefile Fri May 23 16:56:24 2008
@@ -1,147 +1,296 @@
-ifeq ($(SRCDIR)x,x)
-SRCDIR = $(CURDIR)/..
+ifeq ($(SRCDIR),)
+ updir = $(shell echo $(dir $(1)) | sed 's/.$$//')
+ SRCDIR := $(call updir,$(CURDIR))
+ BLDDIR := $(SRCDIR)
endif
-SUBDIR = src
-BUILDDIR = $(SRCDIR)
-VPATH = .:$(SRCDIR)
+SUBDIR := src
-include $(BUILDDIR)/Makefile.config
+include $(BLDDIR)/config.mk
default: all
SUBDIRS =
-CPPCLEAN =
ifeq ($(ENABLE_CPLUSPLUS),yes)
SUBDIRS += cpp
- CPPCLEAN += cpp/clean
endif
-WININET_TRANSPORT_DIR = $(SRCDIR)/lib/wininet_transport
-CURL_TRANSPORT_DIR = $(SRCDIR)/lib/curl_transport
-LIBWWW_TRANSPORT_DIR = $(SRCDIR)/lib/libwww_transport
+TARGET_LIBRARY_NAMES := libxmlrpc libxmlrpc_server
-CASPRINTF_OBJ = $(BUILDDIR)/lib/util/casprintf.lo
+# We cannot build libxmlrpc_server_abyss if we can't also build Abyss,
+# because we need libxmlrpc_abyss in order to build the proper runtime
+# dependencies into libxmlrpc_server_abyss.
-TRANSPORT_OBJS =
-ifeq ($(MUST_BUILD_WININET_CLIENT),yes)
- TRANSPORT_OBJS += $(WININET_TRANSPORT_DIR)/xmlrpc_wininet_transport.lo
-endif
-ifeq ($(MUST_BUILD_CURL_CLIENT),yes)
- TRANSPORT_OBJS += $(CURL_TRANSPORT_DIR)/xmlrpc_curl_transport.lo
-endif
-ifeq ($(MUST_BUILD_LIBWWW_CLIENT),yes)
- TRANSPORT_OBJS += $(LIBWWW_TRANSPORT_DIR)/xmlrpc_libwww_transport.lo
+ifeq ($(ENABLE_ABYSS_SERVER),yes)
+ TARGET_LIBRARY_NAMES += libxmlrpc_server_abyss
endif
-ifeq ($(ENABLE_LIBXML2_BACKEND),yes)
- LIBXML_INCLUDES = $(LIBXML2_CFLAGS)
- LIBXML = $(LIBXML2_LIBS)
-else
- LIBXML_INCLUDES = -I$(SRCDIR)/lib/expat/xmlparse
- LIBXML = $(BUILDDIR)/lib/expat/xmlparse/libxmlrpc_xmlparse.la \
- $(BUILDDIR)/lib/expat/xmltok/libxmlrpc_xmltok.la
+ifeq ($(MUST_BUILD_CLIENT),yes)
+ TARGET_LIBRARY_NAMES += libxmlrpc_client
endif
-ABYSS_INCLUDES = -I$(SRCDIR)/lib/abyss/src
-
-LIBXMLRPC_CLIENT_OBJS = xmlrpc_client.lo
-LIBXMLRPC_SERVER_OBJS = xmlrpc_registry.lo
-LIBXMLRPC_SERVER_ABYSS_OBJS = xmlrpc_server_abyss.lo
-
-ifeq ($(ENABLE_LIBXML2_BACKEND),yes)
- XMLRPC_XML_PARSER = xmlrpc_libxml2.lo
-else
- XMLRPC_XML_PARSER = xmlrpc_expat.lo
+ifeq ($(ENABLE_CGI_SERVER),yes)
+ TARGET_LIBRARY_NAMES += libxmlrpc_server_cgi
endif
-LIBXMLRPC_OBJS = xmlrpc_support.lo xmlrpc_data.lo xmlrpc_builddecomp.lo \
- xmlrpc_datetime.lo xmlrpc_array.lo xmlrpc_struct.lo \
- $(XMLRPC_XML_PARSER) xmlrpc_parse.lo \
- xmlrpc_serialize.lo xmlrpc_base64.lo \
- xmlrpc_utf8.lo xmlrpc_authcookie.lo xmlrpc_strutil.lo
+STATIC_LIBRARIES_TO_INSTALL = $(TARGET_STATIC_LIBRARIES)
-LIB_OBJS = $(LIBXMLRPC_CLIENT_OBJS) $(LIBXMLRPC_SERVER_OBJS)
+SHARED_LIBS_TO_BUILD := $(TARGET_LIBRARY_NAMES)
+SHARED_LIBS_TO_INSTALL := $(TARGET_LIBRARY_NAMES)
-TRANSPORT_INCLUDES = \
- -I$(WININET_TRANSPORT_DIR) \
- -I$(CURL_TRANSPORT_DIR) \
- -I$(LIBWWW_TRANSPORT_DIR) \
-
-INCLUDES = -I$(BUILDDIR) -I$(SRCDIR) \
- -I$(SRCDIR)/include -I$(SRCDIR)/lib/util/include \
- -I$(SRCDIR)/lib/abyss/src \
- $(TRANSPORT_INCLUDES) \
- $(LIBXML_INCLUDES) \
+# TRANSPORT_MODS is the list of modules that have to go into the client
+# library to provide the client XML transport functions.
-TARGET_LTLIBRARIES = libxmlrpc.la libxmlrpc_server.la \
- libxmlrpc_server_abyss.la
+# TRANSPORT_LIBDEP is linker -l options to declare what libraries contain
+# things to which the transport objects refer. (like LIBxxx_LIBDEP --
+# see below)
-ifeq ($(MUST_BUILD_CLIENT),yes)
- TARGET_LTLIBRARIES += libxmlrpc_client.la
+TRANSPORT_MODS =
+TRANSPORT_LIBDEP =
+ifeq ($(MUST_BUILD_WININET_CLIENT),yes)
+ TRANSPORT_MODS += $(BLDDIR)/lib/wininet_transport/xmlrpc_wininet_transport
+ TRANSPORT_LIBDEP += $(shell wininet-config --libs)
endif
-
-ifeq ($(ENABLE_CGI_SERVER),yes)
- TARGET_LTLIBRARIES += libxmlrpc_server_cgi.la
+ifeq ($(MUST_BUILD_CURL_CLIENT),yes)
+ TRANSPORT_MODS += $(BLDDIR)/lib/curl_transport/xmlrpc_curl_transport
+ TRANSPORT_LIBDEP += $(shell curl-config --libs)
+endif
+ifeq ($(MUST_BUILD_LIBWWW_CLIENT),yes)
+ TRANSPORT_MODS += $(BLDDIR)/lib/libwww_transport/xmlrpc_libwww_transport
+ TRANSPORT_LIBDEP += $(shell libwww-config --libs)
endif
-all: $(TARGET_LTLIBRARIES) $(SUBDIRS:%=%/all)
-
-LDFLAGS = $(LADD)
+ifeq ($(ENABLE_LIBXML2_BACKEND),yes)
+ XMLRPC_XML_PARSER = xmlrpc_libxml2
+ XML_PARSER_LIBDEP = $(shell xml2-config --libs)
+ XML_PARSER_LIBDEP_DEP =
+else
+ XMLRPC_XML_PARSER = xmlrpc_expat
+ XML_PARSER_LIBDEP = -L$(BLDDIR)/lib/expat/xmlparse -lxmlrpc_xmlparse
+ XML_PARSER_LIBDEP_DEP = $(LIBXMLRPC_XMLPARSE)
+endif
-LIBLDFLAGS = $(LDFLAGS_VERSINFO) -rpath $(LIBINST_DIR) $(LADD)
+# LIBxxx_OBJS is the list of object files that make up library libxxx.
-libxmlrpc.la: $(LIBXMLRPC_OBJS)
- $(LIBTOOL) --mode=link $(CCLD) -o $@ $(LIBLDFLAGS) $^
+LIBXMLRPC_MODS = \
+ double \
+ parse_value \
+ resource \
+ trace \
+ version \
+ xmlrpc_data \
+ xmlrpc_datetime \
+ xmlrpc_string \
+ xmlrpc_array \
+ xmlrpc_struct \
+ xmlrpc_build \
+ xmlrpc_decompose \
+ $(XMLRPC_XML_PARSER) \
+ xmlrpc_parse \
+ xmlrpc_serialize \
+ xmlrpc_base64 \
+ xmlrpc_authcookie \
+
+LIBXMLRPC_CLIENT_MODS = xmlrpc_client xmlrpc_client_global xmlrpc_server_info
+
+LIBXMLRPC_SERVER_MODS = registry method system_method
+
+LIBXMLRPC_SERVER_ABYSS_MODS = xmlrpc_server_abyss
+
+LIBXMLRPC_SERVER_CGI_MODS = xmlrpc_server_cgi
+
+TARGET_MODS = \
+ $(LIBXMLRPC_MODS) \
+ $(LIBXMLRPC_SERVER_MODS) \
+ $(LIBXMLRPC_SERVER_ABYSS_MODS) \
+ $(LIBXMLRPC_SERVER_CGI_MODS) \
+ $(LIBXMLRPC_CLIENT_MODS) \
+
+OMIT_XMLRPC_LIB_RULE=Y
+MAJ=3
+ # Major number of shared libraries in this directory
+
+include $(SRCDIR)/common.mk
+
+# This 'common.mk' dependency makes sure the symlinks get built before
+# this make file is used for anything.
+
+$(SRCDIR)/common.mk: srcdir blddir
+
+# TARGET_STATIC_LIBRARIES, etc. are set by common.mk, based on
+# TARGET_LIBRARY_NAMES.
+
+
+all: \
+ $(TARGET_STATIC_LIBRARIES) \
+ $(TARGET_SHARED_LIBRARIES) \
+ $(TARGET_SHARED_LE_LIBS) \
+ $(SUBDIRS:%=%/all) \
+
+# Extra dependencies to make parallel make work in spite of all the submakes
+# (See top level make file for details)
+ifeq ($MUST_BUILD_CLIENT),yes)
+cpp/all: $(BLDDIR)/transport_config.h
+endif
-libxmlrpc_client.la: xmlrpc_client.lo $(TRANSPORT_OBJS) $(CASPRINTF_OBJ)
- $(LIBTOOL) --mode=link $(CCLD) -o $@ $(LIBLDFLAGS) $^
+#-----------------------------------------------------------------------------
+# RULES TO LINK LIBRARIES
+#-----------------------------------------------------------------------------
+
+# Rules for these are in common.mk, courtesy of TARGET_LIBRARY_NAMES:
+
+# shlibfn generates e.g. libxmlrpc.so.3.1
+# shliblefn generates e.g. libxmlrpc.so
+
+LIBXMLRPC = $(call shlibfn, libxmlrpc)
+
+$(LIBXMLRPC): $(LIBXMLRPC_MODS:%=%.osh) \
+ $(LIBXMLRPC_UTIL) \
+ $(XML_PARSER_LIBDEP_DEP)
+$(LIBXMLRPC): LIBOBJECTS = $(LIBXMLRPC_MODS:%=%.osh)
+$(LIBXMLRPC): LIBDEP = \
+ -L$(LIBXMLRPC_UTIL_DIR) -lxmlrpc_util \
+ $(XML_PARSER_LIBDEP)
+
+LIBXMLRPC_SERVER = $(call shlibfn, libxmlrpc_server)
+
+$(LIBXMLRPC_SERVER): \
+ $(LIBXMLRPC_SERVER_MODS:%=%.osh) \
+ $(LIBXMLRPC_UTIL) \
+ $(call shliblefn, libxmlrpc)
+$(LIBXMLRPC_SERVER): LIBOBJECTS = $(LIBXMLRPC_SERVER_MODS:%=%.osh)
+$(LIBXMLRPC_SERVER): LIBDEP = \
+ -L$(LIBXMLRPC_UTIL_DIR) -lxmlrpc_util -L. -lxmlrpc
+
+LIBXMLRPC_SERVER_ABYSS = $(call shlibfn, libxmlrpc_server_abyss)
+
+$(LIBXMLRPC_SERVER_ABYSS): \
+ $(LIBXMLRPC_SERVER_ABYSS_MODS:%=%.osh) \
+ $(LIBXMLRPC_UTIL) \
+ $(LIBXMLRPC_ABYSS) \
+ $(call shliblefn, libxmlrpc_server) \
+ $(call shliblefn, libxmlrpc)
+$(LIBXMLRPC_SERVER_ABYSS): LIBOBJECTS = $(LIBXMLRPC_SERVER_ABYSS_MODS:%=%.osh)
+$(LIBXMLRPC_SERVER_ABYSS): LIBDEP = \
+ -L$(LIBXMLRPC_UTIL_DIR) -lxmlrpc_util \
+ -L. -lxmlrpc_server \
+ -L$(LIBXMLRPC_ABYSS_DIR) -lxmlrpc_abyss \
+ -lxmlrpc
+
+LIBXMLRPC_SERVER_CGI = $(call shlibfn, libxmlrpc_server_cgi)
+
+$(LIBXMLRPC_SERVER_CGI): \
+ $(LIBXMLRPC_SERVER_CGI_MODS:%=%.osh) \
+ $(LIBXMRPC_UTIL) \
+ $(call shliblefn, libxmlrpc_server) \
+ $(call shliblefn, libxmlrpc)
+$(LIBXMLRPC_SERVER_CGI): LIBOBJECTS = $(LIBXMLRPC_SERVER_CGI_MODS:%=%.osh)
+$(LIBXMLRPC_SERVER_CGI): LIBDEP = \
+ -L$(LIBXMLRPC_UTIL_DIR) -lxmlrpc_util -L. -lxmlrpc_server -lxmlrpc
+
+LIBXMLRPC_CLIENT = $(call shlibfn, libxmlrpc_client)
+
+$(LIBXMLRPC_CLIENT): \
+ $(LIBXMLRPC_CLIENT_MODS:%=%.osh) \
+ $(TRANSPORT_MODS:%=%.osh) \
+ $(LIBXMLRPC_UTIL) \
+ $(call shliblefn, libxmlrpc)
+$(LIBXMLRPC_CLIENT): LIBOBJECTS = \
+ $(LIBXMLRPC_CLIENT_MODS:%=%.osh) \
+ $(TRANSPORT_MODS:%=%.osh)
+$(LIBXMLRPC_CLIENT): LIBDEP = \
+ -L$(LIBXMLRPC_UTIL_DIR) -lxmlrpc_util \
+ -L. -lxmlrpc \
+ $(TRANSPORT_LIBDEP)
+
+
+libxmlrpc.a: $(LIBXMLRPC_MODS:%=%.o)
+libxmlrpc.a: LIBOBJECTS = $(LIBXMLRPC_MODS:%=%.o)
+
+libxmlrpc_server.a: $(LIBXMLRPC_SERVER_MODS:%=%.o)
+libxmlrpc_server.a: LIBOBJECTS = $(LIBXMLRPC_SERVER_MODS:%=%.o)
+
+libxmlrpc_server_abyss.a: $(LIBXMLRPC_SERVER_ABYSS_MODS:%=%.o)
+libxmlrpc_server_abyss.a: LIBOBJECTS=$(LIBXMLRPC_SERVER_ABYSS_MODS:%=%.o)
+
+libxmlrpc_server_cgi.a: $(LIBXMLRPC_SERVER_CGI_MODS:%=%.o)
+libxmlrpc_server_cgi.a: LIBOBJECTS=$(LIBXMLRPC_SERVER_CGI_MODS:%=%.o)
+
+libxmlrpc_client.a: $(LIBXMLRPC_CLIENT_MODS:%=%.o) $(TRANSPORT_MODS:%=%.o)
+libxmlrpc_client.a: LIBOBJECTS = \
+ $(LIBXMLRPC_CLIENT_MODS:%=%.o) \
+ $(TRANSPORT_MODS:%=%.o)
+
+
+#-----------------------------------------------------------------------------
+# RULES TO COMPILE OBJECT MODULES FOR LIBRARIES
+#-----------------------------------------------------------------------------
+
+# Rules for these are in common.mk, courtesy of TARGET_MODS:
+
+BASIC_INCLUDES = \
+ -I$(BLDDIR) \
+ -I$(BLDDIR)/include \
+ -I$(SRCDIR)/include \
+ -I$(SRCDIR)/lib/util/include \
-libxmlrpc_server.la: xmlrpc_registry.lo
- $(LIBTOOL) --mode=link $(CCLD) -o $@ $(LIBLDFLAGS) $^
+TRANSPORT_INCLUDES = \
+ -I$($SRCDIR)/lib/wininet_transport \
+ -I$(SRCDIR)/lib/curl_transport \
+ -I$(SRCDIR)/lib/libwww_transport \
-libxmlrpc_server_abyss.la: xmlrpc_server_abyss.lo
- $(LIBTOOL) --mode=link $(CCLD) -o $@ $(LIBLDFLAGS) $^
+ifeq ($(ENABLE_LIBXML2_BACKEND),yes)
+ LIBXML_INCLUDES = $(shell xml2-config --cflags)
+else
+ LIBXML_INCLUDES = -I$(SRCDIR)/lib/expat/xmlparse
+endif
-libxmlrpc_server_cgi.la: xmlrpc_server_cgi.lo
- $(LIBTOOL) --mode=link $(CCLD) -o $@ $(LIBLDFLAGS) $^
+$(LIBXMLRPC_MODS:%=%.o) \
+$(LIBXMLRPC_MODS:%=%.osh): \
+ INCLUDES = $(BASIC_INCLUDES) $(LIBXML_INCLUDES)
+
+$(LIBXMLRPC_CLIENT_MODS:%=%.o) \
+$(LIBXMLRPC_CLIENT_MODS:%=%.osh): \
+ INCLUDES = $(BASIC_INCLUDES) $(TRANSPORT_INCLUDES)
+
+$(LIBXMLRPC_SERVER_MODS:%=%.o) \
+$(LIBXMLRPC_SERVER_MODS:%=%.osh): \
+ INCLUDES = $(BASIC_INCLUDES)
+
+$(LIBXMLRPC_SERVER_ABYSS_MODS:%=%.o) \
+$(LIBXMLRPC_SERVER_ABYSS_MODS:%=%.osh): \
+ INCLUDES = $(BASIC_INCLUDES) -I$(SRCDIR)/lib/abyss/src
+
+$(LIBXMLRPC_SERVER_CGI_MODS:%=%.o) \
+$(LIBXMLRPC_SERVER_CGI_MODS:%=%.osh): \
+ INCLUDES = $(BASIC_INCLUDES)
CFLAGS = $(CFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD)
-$(LIB_OBJS):%.lo:%.c
- $(LIBTOOL) --mode=compile $(CC) -c $(INCLUDES) $(CFLAGS) $<
-
-$(LIBXMLRPC_OBJS):%.lo:%.c
- $(LIBTOOL) --mode=compile $(CC) -c $(INCLUDES) $(LIBXML_INCLUDES) \
- $(CFLAGS) $<
-
-$(LIBXMLRPC_SERVER_ABYSS_OBJS):%.lo:%.c
- $(LIBTOOL) --mode=compile $(CC) -c $(INCLUDES) $(ABYSS_INCLUDES) \
- $(CFLAGS) $<
-
-xmlrpc_server_cgi.lo:%.lo:%.c
- $(LIBTOOL) --mode=compile $(CC) -c $(INCLUDES) \
- $(CFLAGS) $<
-
-LTLIBRARIES_TO_INSTALL = $(TARGET_LTLIBRARIES)
check:
- $(MAKE) -C test check
+ $(MAKE) -C test runtests
+ $(MAKE) -C cpp check
.PHONY: install
install: install-common $(SUBDIRS:%=%/install)
.PHONY: clean clean-local distclean
-clean: clean-common clean-local
-clean-local: $(CPPCLEAN)
+clean: clean-common clean-local $(SUBDIRS:%=%/clean)
+clean-local:
+ $(MAKE) -C test clean
-distclean: clean distclean-common
+distclean: clean-common clean-local distclean-common $(SUBDIRS:%=%/distclean)
.PHONY: dep
-dep: $(SUBDIRS:%=%/dep) $(BUILDDIR)/transport_config.h dep-common
+dep: $(SUBDIRS:%=%/dep) $(BLDDIR)/transport_config.h dep-common
-include $(SRCDIR)/Makefile.common
+dep-common:
+ INCLUDES = $(BASIC_INCLUDES) $(TRANSPORT_INCLUDES) $(LIBXML_INCLUDES)
-xmlrpc_client.lo: $(BUILDDIR)/transport_config.h
+xmlrpc_client.o xmlrpc_client.osh: $(BLDDIR)/transport_config.h
+xmlrpc_client.o xmlrpc_client.osh: $(BLDDIR)/version.h
+registry.o registry.osh: $(BLDDIR)/version.h
+version.o version.osh: $(BLDDIR)/version.h
include Makefile.depend
Modified: freeswitch/trunk/libs/xmlrpc-c/src/cpp/Makefile
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/src/cpp/Makefile (original)
+++ freeswitch/trunk/libs/xmlrpc-c/src/cpp/Makefile Fri May 23 16:56:24 2008
@@ -1,177 +1,245 @@
-ifeq ($(SRCDIR)x,x)
-SRCDIR = $(CURDIR)/../..
+ifeq ($(SRCDIR),)
+ updir = $(shell echo $(dir $(1)) | sed 's/.$$//')
+ srcDIR := $(call updir,$(CURDIR))
+ SRCDIR := $(call updir,$(srcDIR))
+ BLDDIR := $(SRCDIR)
endif
-SUBDIR = src/cpp
-BUILDDIR = $(SRCDIR)
-VPATH = .:$(SRCDIR)
+SUBDIR := src/cpp
-include $(BUILDDIR)/Makefile.config
+include $(BLDDIR)/config.mk
default: all
-WININET_TRANSPORT_DIR = $(SRCDIR)/lib/wininet_transport
-CURL_TRANSPORT_DIR = $(SRCDIR)/lib/curl_transport
-LIBWWW_TRANSPORT_DIR = $(SRCDIR)/lib/libwww_transport
+# libxmlrpc_cpp is the legacy C++ wrapper library. The others are the
+# more elaborate replacements.
+
+TARGET_LIB_NAMES_PP := \
+ libxmlrpc_cpp \
+ libxmlrpc++ \
+ libxmlrpc_server++ \
+ libxmlrpc_server_abyss++ \
+ libxmlrpc_server_pstream++ \
+ libxmlrpc_packetsocket \
+
+ifeq ($(MUST_BUILD_CLIENT),yes)
+ TARGET_LIB_NAMES_PP += libxmlrpc_client++
+endif
+
+STATIC_LIBRARIES_TO_INSTALL = $(TARGET_STATIC_LIBRARIES)
+
+SHARED_LIBS_TO_BUILD := $(TARGET_LIB_NAMES_PP)
+SHARED_LIBS_TO_INSTALL := $(TARGET_LIB_NAMES_PP)
+
+# INCLUDES and DEP_SOURCES are used by dep-common target
+INCLUDES = $(BASIC_INCLUDES) $(CLIENT_INCLUDES) $(LIBXML_INCLUDES) \
+ $(SERVER_INCLUDES) $(SERVER_ABYSS_INCLUDES) $(TRANSPORT_INCLUDES)
+DEP_SOURCES = *.cpp
+
+WININET_TRANSPORT_DIR = srcdir/lib/wininet_transport
+CURL_TRANSPORT_DIR = srcdir/lib/curl_transport
+LIBWWW_TRANSPORT_DIR = srcdir/lib/libwww_transport
ifeq ($(ENABLE_LIBXML2_BACKEND),yes)
LIBXML_INCLUDES = $(LIBXML2_CFLAGS)
- LIBXML = $(LIBXML2_LIBS)
else
- LIBXML_INCLUDES = -I$(SRCDIR)/lib/expat/xmlparse
- LIBXML = $(BUILDDIR)/lib/expat/xmlparse/libxmlrpc_xmlparse.la \
- $(BUILDDIR)/lib/expat/xmltok/libxmlrpc_xmltok.la
+ LIBXML_INCLUDES = -Isrcdir/lib/expat/xmlparse
endif
-ifeq ($(ENABLE_LIBXML2),yes)
- XMLRPC_XML_PARSER = xmlrpc_libxml2.lo
-else
- XMLRPC_XML_PARSER = xmlrpc_expat.lo
-endif
+LIBXMLRPCPP_MODS = \
+ base64 env_wrap fault girerr girmem outcome param_list value xml
+LIBXMLRPC_SERVERPP_MODS = registry
+LIBXMLRPC_SERVER_ABYSSPP_MODS = server_abyss
+LIBXMLRPC_SERVER_PSTREAMPP_MODS = server_pstream
+LIBXMLRPC_CLIENTPP_MODS = client client_simple curl libwww wininet pstream
+LIBXMLRPC_PACKETSOCKET_MODS = packetsocket
-LIBXMLRPC = $(BUILDDIR)/src/libxmlrpc.la
-LIBXMLRPC_SERVER = $(BUILDDIR)/src/libxmlrpc_server.la
-LIBXMLRPC_CLIENT = $(BUILDDIR)/src/libxmlrpc_client.la
-
-LIBXMLRPCPP_OBJS = girmem.o value.o fault.o outcome.o param_list.o xml.o
-LIBXMLRPC_SERVERPP_OBJS = registry.o
-LIBXMLRPC_SERVER_ABYSSPP_OBJS = server_abyss.o
-LIBXMLRPC_CLIENTPP_OBJS = client.o client_simple.o
-
-$(LIBXMLRPC_CLIENTPP_OBJS): $(BUILDDIR)/transport_config.h
-
-TRANSPORT_OBJS =
-ifeq ($(MUST_BUILD_WININET_CLIENT),yes)
- TRANSPORT_OBJS += $(WININET_TRANSPORT_DIR)/xmlrpc_wininet_transport.lo
-endif
-ifeq ($(MUST_BUILD_CURL_CLIENT),yes)
- TRANSPORT_OBJS += $(CURL_TRANSPORT_DIR)/xmlrpc_curl_transport.lo
-endif
-ifeq ($(MUST_BUILD_LIBWWW_CLIENT),yes)
- TRANSPORT_OBJS += $(LIBWWW_TRANSPORT_DIR)/xmlrpc_libwww_transport.lo
-endif
+TARGET_MODS_PP = \
+ XmlRpcCpp \
+ $(LIBXMLRPCPP_MODS) \
+ $(LIBXMLRPC_SERVERPP_MODS) \
+ $(LIBXMLRPC_SERVER_ABYSSPP_MODS) \
+ $(LIBXMLRPC_SERVER_PSTREAMPP_MODS) \
+ $(LIBXMLRPC_CLIENTPP_MODS) \
+ $(LIBXMLRPC_PACKETSOCKET_MODS) \
+
+OMIT_CPP_LIB_RULES = Y
+MAJ=4
+ # Major number of shared libraries in this directory
+
+include $(SRCDIR)/common.mk
+
+
+# This 'common.mk' dependency makes sure the symlinks get built before
+# this make file is used for anything.
+
+$(SRCDIR)/common.mk: srcdir blddir
TRANSPORT_INCLUDES = \
-I$(WININET_TRANSPORT_DIR) \
-I$(CURL_TRANSPORT_DIR) \
-I$(LIBWWW_TRANSPORT_DIR) \
-BASIC_INCLUDES = -I$(SRCDIR)/include -I$(BUILDDIR) -I$(SRCDIR) \
- -I$(SRCDIR)/lib/util/include
+BASIC_INCLUDES = \
+ -Iblddir/include \
+ -Isrcdir/include \
+ -Iblddir \
+ -Isrcdir/lib/util/include
-# We always statically-link our C++ code because it's tiny, and C++ is
-# no good at shared libraries, anyway. It's actually getting bigger,
-# but since I'm determined not to expand the use of libtool (because
-# it obfuscates the build process), I haven't figured out yet how to
-# get the shared libraries to build for all the platforms.
-# libxmlrpc_cpp.a is the legacy C++ wrapper library. The others are the
-# more elaborate replacements.
+# TARGET_STATIC_LIBARIES, etc. are set by common.mk, based on
+# TARGET_LIB_NAMES_PP.
-TARGET_LIBRARIES = \
- libxmlrpc_cpp.a \
- libxmlrpc++.a \
- libxmlrpc_server++.a \
- libxmlrpc_server_abyss++.a \
- libxmlrpc_client++.a \
+all: \
+ $(TARGET_STATIC_LIBRARIES) \
+ $(TARGET_SHARED_LIBS_PP) \
+ $(TARGET_SHARED_LE_LIBS)
-TARGET_PROGS = cpptest
-all: $(TARGET_LIBRARIES)
+#-----------------------------------------------------------------------------
+# RULES TO LINK LIBRARIES
+#-----------------------------------------------------------------------------
-ifeq ($(MUST_BUILD_CURL_CLIENT),yes)
- LDFLAGS += $(shell curl-config --libs) -lpthread
-endif
-ifeq ($(MUST_BUILD_LIBWWW_CLIENT),yes)
- LDFLAGS += $(shell libwww-config --libs)
-endif
+# Rules for these are in common.mk, courtesy of TARGET_LIB_NAMES_PP:
-LDFLAGS += $(LADD)
+# shlibfn generates e.g. libxmlrpc.so.3.1
+# shliblefn generates e.g. libxmlrpc.so
-cpptest:%:%.o libxmlrpc_server_abyss++.a libxmlrpc_server++.a \
- libxmlrpc_client++.a libxmlrpc++.a libxmlrpc_cpp.a \
- $(LIBXMLRPC) $(LIBXMLRPC_SERVER) $(LIBXMLRPC_CLIENT) $(LIBXML)
- $(LIBTOOL) --mode=link $(CXXLD) -o $@ $(LDFLAGS) $^
+LIBXMLRPC_CPP = $(call shlibfn, libxmlrpc_cpp)
-LIBLDFLAGS = $(LADD)
+$(LIBXMLRPC_CPP): XmlRpcCpp.osh
+$(LIBXMLRPC_CPP): LIBOBJECTS = XmlRpcCpp.osh
+
+LIBXMLRPCPP = $(call shlibfn, libxmlrpc++)
+
+$(LIBXMLRPCPP): $(LIBXMLRPCPP_MODS:%=%.osh) \
+ $(LIBXMLRPC)
+$(LIBXMLRPCPP): LIBOBJECTS = $(LIBXMLRPCPP_MODS:%=%.osh)
+$(LIBXMLRPCPP): LIBDEP = -Lblddir/src -lxmlrpc
+
+LIBXMLRPC_SERVERPP = $(call shlibfn, libxmlrpc_server++)
+
+$(LIBXMLRPC_SERVERPP): $(LIBXMLRPC_SERVERPP_MODS:%=%.osh) \
+ $(LIBXMLRPC_SERVER) \
+ $(LIBXMLRPC)
+$(LIBXMLRPC_SERVERPP): LIBOBJECTS = $(LIBXMLRPC_SERVERPP_MODS:%=%.osh)
+$(LIBXMLRPC_SERVERPP): LIBDEP = -Lblddir/src -lxmlrpc_server -lxmlrpc
+
+LIBXMLRPC_SERVER_ABYSSPP = $(call shlibfn, libxmlrpc_server_abyss++)
+
+$(LIBXMLRPC_SERVER_ABYSSPP): $(LIBXMLRPC_SERVER_ABYSSPP_MODS:%=%.osh) \
+ $(LIBXMLRPC_ABYSS) \
+ $(LIBXMLRPC)
+$(LIBXMLRPC_SERVER_ABYSSPP): LIBOBJECTS = $(LIBXMLRPC_SERVER_ABYSSPP_MODS:%=%.osh)
+$(LIBXMLRPC_SERVER_ABYSSPP): LIBDEP = \
+ -L$(LIBXMLRPC_ABYSS_DIR) -lxmlrpc_abyss -Lblddir/src -lxmlrpc
+
+LIBXMLRPC_SERVER_PSTREAMPP = $(call shlibfn, libxmlrpc_server_pstream++)
+
+$(LIBXMLRPC_SERVER_PSTREAMPP): $(LIBXMLRPC_SERVER_PSTREAMPP_MODS:%=%.osh) \
+ $(LIBXMLRPC_SERVER) \
+ $(LIBXMLRPC_PACKETSOCKET)
+$(LIBXMLRPC_SERVER_PSTREAMPP): LIBOBJECTS = $(LIBXMLRPC_SERVER_PSTREAMPP_MODS:%=%.osh)
+$(LIBXMLRPC_SERVER_PSTREAMPP): LIBDEP = \
+ -Lblddir/src -lxmlrpc_server -L. -lxmlrpc_packetsocket
+
+LIBXMLRPC_CLIENTPP = $(call shlibfn, libxmlrpc_client++)
+
+$(LIBXMLRPC_CLIENTPP): $(LIBXMLRPC_CLIENTPP_MODS:%=%.osh) \
+ $(LIBXMLRPCPP) \
+ $(LIBXMLRPC_CLIENT)
+$(LIBXMLRPC_CLIENTPP): LIBOBJECTS = $(LIBXMLRPC_CLIENTPP_MODS:%=%.osh)
+$(LIBXMLRPC_CLIENTPP): LIBDEP = \
+ -L. -lxmlrpc++ -Lblddir/src -lxmlrpc_client
+
+LIBXMLRPC_PACKETSOCKET = $(call shlibfn, libxmlrpc_packetsocket)
+
+$(LIBXMLRPC_PACKETSOCKET): $(LIBXMLRPC_PACKETSOCKET_MODS:%=%.osh)
+$(LIBXMLRPC_PACKETSOCKET): LIBOBJECTS = $(LIBXMLRPC_PACKETSOCKET_MODS:%=%.osh)
libxmlrpc_cpp.a: XmlRpcCpp.o
- -rm -f $@
- $(AR) cru $@ $^
- $(RANLIB) $@
-
-libxmlrpc++.a: $(LIBXMLRPCPP_OBJS)
- -rm -f $@
- $(AR) cru $@ $^
- $(RANLIB) $@
-
-libxmlrpc_server++.a: $(LIBXMLRPC_SERVERPP_OBJS)
- -rm -f $@
- $(AR) cru $@ $^
- $(RANLIB) $@
-
-libxmlrpc_server_abyss++.a: $(LIBXMLRPC_SERVER_ABYSSPP_OBJS)
- -rm -f $@
- $(AR) cru $@ $^
- $(RANLIB) $@
-
-libxmlrpc_client++.a: $(LIBXMLRPC_CLIENTPP_OBJS)
- -rm -f $@
- $(AR) cru $@ $^
- $(RANLIB) $@
+libxmlrpc_cpp.a: LIBOBJECTS = XmlRpcCpp.o
-CXXFLAGS = $(CXXFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD)
+libxmlrpc++.a: $(LIBXMLRPCPP_MODS:%=%.o)
+libxmlrpc++.a: LIBOBJECTS = $(LIBXMLRPCPP_MODS:%=%.o)
-cpptest.o:%.o:%.cpp
- $(CXX) -c $(BASIC_INCLUDES) $(CXXFLAGS) $<
+libxmlrpc_server++.a: $(LIBXMLRPC_SERVERPP_MODS:%=%.o)
+libxmlrpc_server++.a: LIBOBJECTS = $(LIBXMLRPC_SERVERPP_MODS:%=%.o)
-XmlRpcCpp.o:%.o:%.cpp
- $(CXX) -c $(BASIC_INCLUDES) $(CXXFLAGS) $<
+libxmlrpc_server_abyss++.a: $(LIBXMLRPC_SERVER_ABYSSPP_MODS:%=%.o)
+libxmlrpc_server_abyss++.a: LIBOBJECTS=$(LIBXMLRPC_SERVER_ABYSSPP_MODS:%=%.o)
-$(LIBXMLRPCPP_OBJS):%.o:%.cpp
- $(CXX) -c $(BASIC_INCLUDES) $(CXXFLAGS) $<
+libxmlrpc_server_pstream++.a: $(LIBXMLRPC_SERVER_PSTREAMPP_MODS:%=%.o)
+libxmlrpc_server_pstream++.a: LIBOBJECTS=$(LIBXMLRPC_SERVER_PSTREAMPP_MODS:%=%.o)
-SERVER_INCLUDES = $(BASIC_INCLUDES) $(LIBXML_INCLUDES)
+libxmlrpc_client++.a: $(LIBXMLRPC_CLIENTPP_MODS:%=%.o)
+libxmlrpc_client++.a: LIBOBJECTS = $(LIBXMLRPC_CLIENTPP_MODS:%=%.o)
+
+libxmlrpc_packetsocket.a: $(LIBXMLRPC_PACKETSOCKET_MODS:%=%.o)
+libxmlrpc_packetsocket.a: LIBOBJECTS = $(LIBXMLRPC_PACKETSOCKET_MODS:%=%.o)
-$(LIBXMLRPC_SERVERPP_OBJS):%.o:%.cpp
- $(CXX) -c $(SERVER_INCLUDES) $(CXXFLAGS) $<
+#-----------------------------------------------------------------------------
+# RULES TO COMPILE OBJECT MODULES FOR LIBRARIES
+#-----------------------------------------------------------------------------
-SERVER_ABYSS_INCLUDES = $(SERVER_INCLUDES) -I$(SRCDIR)/lib/abyss/src
+# Rules for these are in common.mk, courtesy of TARGET_MODS_PP:
-$(LIBXMLRPC_SERVER_ABYSSPP_OBJS):%.o:%.cpp
- $(CXX) -c $(SERVER_ABYSS_INCLUDES) $(CXXFLAGS) $<
+XmlRpcCpp.o% XmlrpcCpp.osh: \
+ INCLUDES = $(BASIC_INCLUDES)
+
+$(LIBXMLRPCPP_MODS:%=%.o) \
+$(LIBXMLRPCPP_MODS:%=%.osh): \
+ INCLUDES = $(BASIC_INCLUDES)
+
+SERVER_INCLUDES = $(BASIC_INCLUDES) $(LIBXML_INCLUDES)
-CLIENT_INCLUDES = $(BASIC_INCLUDES) $(LIBXML_INCLUDES) $(TRANSPORT_INCLUDES)
+$(LIBXMLRPC_SERVERPP_MODS:%=%.o) \
+$(LIBXMLRPC_SERVERPP_MODS:%=%.osh): \
+ INCLUDES = $(SERVER_INCLUDES)
+
+$(LIBXMLRPC_SERVER_ABYSSPP_MODS:%=%.o) \
+$(LIBXMLRPC_SERVER_ABYSSPP_MODS:%=%.o): \
+ INCLUDES = $(SERVER_INCLUDES)
+
+$(LIBXMLRPC_SERVER_PSTREAMPP_MODS:%=%.o) \
+$(LIBXMLRPC_SERVER_PSTREAMPP_MODS:%=%.o): \
+ INCLUDES = $(SERVER_INCLUDES)
+
+$(LIBXMLRPC_CLIENTPP_MODS:%=%.o) \
+$(LIBXMLRPC_CLIENTPP_MODS:%=%.osh): \
+ INCLUDES = $(BASIC_INCLUDES) $(LIBXML_INCLUDES) $(TRANSPORT_INCLUDES)
+
+$(LIBXMLRPC_PACKETSOCKET_MODS:%=%.o) \
+$(LIBXMLRPC_PACKETSOCKET_MODS:%=%.osh): \
+ INCLUDES = $(BASIC_INCLUDES)
-$(LIBXMLRPC_CLIENTPP_OBJS):%.o:%.cpp
- $(CXX) -c $(CLIENT_INCLUDES) $(CXXFLAGS) $<
+CXXFLAGS = $(CXXFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD)
+TRANSPORT_CONFIG_USERS = client curl libwww wininet
+$(TRANSPORT_CONFIG_USERS:%=%.o) $(TRANSPORT_CONFIG_USERS:%=%.osh): \
+ $(BLDDIR)/transport_config.h
-LIBRARIES_TO_INSTALL = $(TARGET_LIBRARIES)
+#-----------------------------------------------------------------------------
+# MISCELLANEOUS RULES
+#-----------------------------------------------------------------------------
-check: cpptest
- for tst in $^; do \
- ./$$tst; \
- done;
+check:
+ $(MAKE) -C test runtests
.PHONY: install
install: install-common
-.PHONY: clean clean-local distclean
+.PHONY: clean clean-local distclean distclean-local
clean: clean-common clean-local
clean-local:
- rm -f $(TARGET_PROGS)
+ $(MAKE) -C test clean
-distclean: clean distclean-common
+distclean: clean distclean-local distclean-common
-# INCLUDES and DEP_SOURCES are used by dep-common target
-INCLUDES = $(BASIC_INCLUDES) $(CLIENT_INCLUDES) $(LIBXML_INCLUDES) \
- $(SERVER_INCLUDES) $(SERVER_ABYSS_INCLUDES) $(TRANSPORT_INCLUDES)
-DEP_SOURCES = *.cpp
+distclean-local:
+ $(MAKE) -C test distclean
.PHONY: dep
-dep: $(BUILDDIR)/transport_config.h dep-common
-
-include $(SRCDIR)/Makefile.common
+dep: dep-common $(BLDDIR)/transport_config.h
include Makefile.depend
Modified: freeswitch/trunk/libs/xmlrpc-c/src/cpp/XmlRpcCpp.cpp
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/src/cpp/XmlRpcCpp.cpp (original)
+++ freeswitch/trunk/libs/xmlrpc-c/src/cpp/XmlRpcCpp.cpp Fri May 23 16:56:24 2008
@@ -25,6 +25,8 @@
#include <string>
+#include <cstring>
+
#include "xmlrpc-c/oldcppwrapper.hpp"
using std::string;
@@ -36,23 +38,23 @@
XmlRpcFault::XmlRpcFault (const XmlRpcFault &fault) {
xmlrpc_env_init(&mFault);
xmlrpc_env_set_fault(&mFault,
- fault.mFault.fault_code,
- fault.mFault.fault_string);
+ fault.mFault.fault_code,
+ fault.mFault.fault_string);
}
XmlRpcFault::XmlRpcFault (const int faultCode, const string faultString) {
xmlrpc_env_init(&mFault);
xmlrpc_env_set_fault(&mFault, faultCode,
- const_cast<char*>(faultString.c_str()));
+ const_cast<char*>(faultString.c_str()));
}
XmlRpcFault::XmlRpcFault (const xmlrpc_env *env) {
if (!env->fault_string)
- throw XmlRpcFault(XMLRPC_INTERNAL_ERROR,
- "Tried to create empty fault");
+ throw XmlRpcFault(XMLRPC_INTERNAL_ERROR,
+ "Tried to create empty fault");
xmlrpc_env_init(&mFault);
xmlrpc_env_set_fault(&mFault, env->fault_code,
- const_cast<char*>(env->fault_string));
+ const_cast<char*>(env->fault_string));
}
XmlRpcFault::~XmlRpcFault (void) {
@@ -72,9 +74,9 @@
XmlRpcEnv::XmlRpcEnv (const XmlRpcEnv &env) {
xmlrpc_env_init(&mEnv);
if (env.hasFaultOccurred())
- xmlrpc_env_set_fault(&mEnv,
- env.mEnv.fault_code,
- env.mEnv.fault_string);
+ xmlrpc_env_set_fault(&mEnv,
+ env.mEnv.fault_code,
+ env.mEnv.fault_string);
}
XmlRpcFault XmlRpcEnv::getFault (void) const {
@@ -166,7 +168,7 @@
}
XmlRpcValue XmlRpcValue::makeBase64 (const unsigned char *const data,
- size_t len)
+ size_t len)
{
XmlRpcEnv env;
xmlrpc_value *value = xmlrpc_build_value(env, "6", data, len);
@@ -187,7 +189,7 @@
xmlrpc_bool result;
xmlrpc_parse_value(env, mValue, "b", &result);
env.throwIfFaultOccurred();
- return result;
+ return (result != 0);
}
double XmlRpcValue::getDouble (void) const {
@@ -233,7 +235,7 @@
}
void XmlRpcValue::getBase64 (const unsigned char *& out_data,
- size_t& out_len) const
+ size_t& out_len) const
{
XmlRpcEnv env;
xmlrpc_parse_value(env, mValue, "6", &out_data, &out_len);
@@ -271,10 +273,10 @@
XmlRpcEnv env;
const char *keystr = key.data();
size_t keylen = key.size();
- bool result = xmlrpc_struct_has_key_n(env, mValue,
- const_cast<char*>(keystr), keylen);
+ int result = xmlrpc_struct_has_key_n(env, mValue,
+ const_cast<char*>(keystr), keylen);
env.throwIfFaultOccurred();
- return result;
+ return (result != 0);
}
XmlRpcValue XmlRpcValue::structGetValue (const string& key) const {
@@ -282,8 +284,8 @@
const char *keystr = key.data();
size_t keylen = key.size();
xmlrpc_value *result =
- xmlrpc_struct_get_value_n(env, mValue,
- const_cast<char*>(keystr), keylen);
+ xmlrpc_struct_get_value_n(env, mValue,
+ const_cast<char*>(keystr), keylen);
env.throwIfFaultOccurred();
return XmlRpcValue(result);
}
@@ -294,13 +296,13 @@
const char *keystr = key.data();
size_t keylen = key.size();
xmlrpc_struct_set_value_n(env, mValue, (char*) keystr, keylen,
- value.borrowReference());
+ value.borrowReference());
env.throwIfFaultOccurred();
}
void XmlRpcValue::structGetKeyAndValue (const int index,
- string& out_key,
- XmlRpcValue& out_value) const
+ string& out_key,
+ XmlRpcValue& out_value) const
{
XmlRpcEnv env;
@@ -313,81 +315,81 @@
}
XmlRpcGenSrv& XmlRpcGenSrv::addMethod (const string& name,
- xmlrpc_method method,
- void *data)
+ xmlrpc_method method,
+ void *data)
{
XmlRpcEnv env;
- xmlrpc_registry_add_method (env, mRegistry, NULL,
- name.c_str (),
- method, data);
+ xmlrpc_registry_add_method (env, mRegistry, NULL,
+ name.c_str (),
+ method, data);
env.throwIfFaultOccurred ();
- return (*this);
+ return (*this);
}
XmlRpcGenSrv& XmlRpcGenSrv::addMethod (const string& name,
- xmlrpc_method method,
- void* data,
- const string& signature,
- const string& help)
+ xmlrpc_method method,
+ void* data,
+ const string& signature,
+ const string& help)
{
XmlRpcEnv env;
- xmlrpc_registry_add_method_w_doc (env, mRegistry, NULL,
- name.c_str (),
- method, data,
- signature.c_str (),
- help.c_str ());
+ xmlrpc_registry_add_method_w_doc (env, mRegistry, NULL,
+ name.c_str (),
+ method, data,
+ signature.c_str (),
+ help.c_str ());
env.throwIfFaultOccurred ();
- return (*this);
+ return (*this);
}
xmlrpc_mem_block* XmlRpcGenSrv::alloc (XmlRpcEnv& env, const string& body) const
{
- xmlrpc_mem_block* result = NULL;
- char* contents;
+ xmlrpc_mem_block* result = NULL;
+ char* contents;
- result = xmlrpc_mem_block_new (env, body.length ());
- env.throwIfFaultOccurred ();
+ result = xmlrpc_mem_block_new (env, body.length ());
+ env.throwIfFaultOccurred ();
- contents = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, result);
+ contents = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, result);
- memcpy (contents, body.c_str (), body.length ());
- return result;
+ memcpy (contents, body.c_str (), body.length ());
+ return result;
}
string XmlRpcGenSrv::handle (const string& body) const
{
- XmlRpcEnv env;
- string result;
- xmlrpc_mem_block* input = NULL, * output = NULL;
- char* input_data, * output_data;
- size_t input_size, output_size;
-
- if (body.length () > xmlrpc_limit_get (XMLRPC_XML_SIZE_LIMIT_ID))
- throw XmlRpcFault (XMLRPC_LIMIT_EXCEEDED_ERROR, "XML-RPC request too large");
-
- input = alloc (env, body);
- input_data = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, input);
- input_size = XMLRPC_TYPED_MEM_BLOCK_SIZE(char, input);
-
- output = xmlrpc_registry_process_call (env, mRegistry, NULL,
- input_data, input_size);
-
- if (output)
- {
- output_data = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, output);
- output_size = XMLRPC_TYPED_MEM_BLOCK_SIZE(char, output);
-
- result.assign (output_data, output_size);
- xmlrpc_mem_block_free (output);
- }
-
- xmlrpc_mem_block_free (input);
- if (!result.length ())
- throw XmlRpcFault (env);
+ XmlRpcEnv env;
+ string result;
+ xmlrpc_mem_block* input = NULL, * output = NULL;
+ char* input_data, * output_data;
+ size_t input_size, output_size;
+
+ if (body.length () > xmlrpc_limit_get (XMLRPC_XML_SIZE_LIMIT_ID))
+ throw XmlRpcFault (XMLRPC_LIMIT_EXCEEDED_ERROR, "XML-RPC request too large");
+
+ input = alloc (env, body);
+ input_data = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, input);
+ input_size = XMLRPC_TYPED_MEM_BLOCK_SIZE(char, input);
+
+ output = xmlrpc_registry_process_call (env, mRegistry, NULL,
+ input_data, input_size);
+
+ if (output)
+ {
+ output_data = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, output);
+ output_size = XMLRPC_TYPED_MEM_BLOCK_SIZE(char, output);
+
+ result.assign (output_data, output_size);
+ xmlrpc_mem_block_free (output);
+ }
+
+ xmlrpc_mem_block_free (input);
+ if (!result.length ())
+ throw XmlRpcFault (env);
- return result;
+ return result;
}
Added: freeswitch/trunk/libs/xmlrpc-c/src/cpp/base64.cpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/cpp/base64.cpp Fri May 23 16:56:24 2008
@@ -0,0 +1,234 @@
+#include <cassert>
+#include <string>
+#include <vector>
+#include <bitset>
+
+#include "xmlrpc-c/girerr.hpp"
+using girerr::error;
+using girerr::throwf;
+#include "xmlrpc-c/base64.hpp"
+
+using namespace std;
+using namespace xmlrpc_c;
+
+
+namespace {
+
+char const table_a2b_base64[] = {
+ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
+ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
+ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,
+ 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1, 0,-1,-1, /* Note PAD->0 */
+ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14,
+ 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1,
+ -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
+ 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1
+};
+
+char const base64Pad('=');
+size_t const base64MaxChunkSize(57);
+ // Max binary chunk size (76 character line)
+#define BASE64_LINE_SZ 128 /* Buffer size for a single line. */
+
+unsigned char const table_b2a_base64[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+} // namespace
+
+
+
+class bitBuffer {
+public:
+ bitBuffer() : bitsInBuffer(0) {};
+
+ void
+ shiftIn8Bits(unsigned char const newBits) {
+ // Shift in 8 bits to the right end of the buffer
+
+ this->buffer = (this->buffer << 8) | newBits;
+ this->bitsInBuffer += 8;
+
+ assert(this->bitsInBuffer <= 12);
+ }
+
+ void
+ shiftIn6Bits(unsigned char const newBits) {
+ // Shift in 6 bits to the right end of the buffer
+
+ this->buffer = (this->buffer << 6) | newBits;
+ this->bitsInBuffer += 6;
+
+ assert(this->bitsInBuffer <= 12);
+ }
+
+ void
+ shiftOut6Bits(unsigned char * const outputP) {
+ // Shift out 6 bits from the left end of the buffer
+
+ assert(bitsInBuffer >= 6);
+
+ *outputP = (this->buffer >> (this->bitsInBuffer - 6)) & 0x3f;
+ this->bitsInBuffer -= 6;
+ }
+
+ void
+ shiftOut8Bits(unsigned char * const outputP) {
+ // Shift out 8 bits from the left end of the buffer
+
+ assert(bitsInBuffer >= 8);
+
+ *outputP = (this->buffer >> (this->bitsInBuffer - 8)) & 0x3f;
+ this->bitsInBuffer -= 8;
+ }
+
+ void
+ shiftOutResidue(unsigned char * const outputP) {
+ // Shift out the residual 2 or 4 bits, padded on the right with 0
+ // to 6 bits.
+
+ while (this->bitsInBuffer < 6) {
+ this->buffer <<= 2;
+ this->bitsInBuffer += 2;
+ }
+
+ this->shiftOut6Bits(outputP);
+ }
+
+ void
+ discardResidue() {
+ assert(bitsInBuffer < 8);
+
+ this->bitsInBuffer = 0;
+ }
+
+ unsigned int
+ bitCount() {
+ return bitsInBuffer;
+ }
+
+private:
+ unsigned int buffer;
+ unsigned int bitsInBuffer;
+};
+
+
+namespace xmlrpc_c {
+
+
+static void
+encodeChunk(vector<unsigned char> const& bytes,
+ size_t const lineStart,
+ size_t const chunkSize,
+ string * const outputP) {
+
+ bitBuffer buffer;
+ // A buffer in which we accumulate bits (up to 12 bits)
+ // until we have enough (6) for a base64 character.
+
+ // I suppose this would be more efficient with an iterator on
+ // 'bytes' and/or *outputP. I'd have to find out how to use one.
+
+ for (size_t linePos = 0; linePos < chunkSize; ++linePos) {
+ // Shift the data into our buffer
+ buffer.shiftIn8Bits(bytes[lineStart + linePos]);
+
+ // Encode any complete 6 bit groups
+ while (buffer.bitCount() >= 6) {
+ unsigned char theseBits;
+ buffer.shiftOut6Bits(&theseBits);
+ outputP->append(1, table_b2a_base64[theseBits]);
+ }
+ }
+ if (buffer.bitCount() > 0) {
+ // Handle residual bits in the buffer
+ unsigned char theseBits;
+ buffer.shiftOutResidue(&theseBits);
+
+ outputP->append(1, table_b2a_base64[theseBits]);
+
+ // Pad to a multiple of 4 characters (24 bits)
+ assert(outputP->length() % 4 > 0);
+ outputP->append(4-outputP->length() % 4, base64Pad);
+ } else {
+ assert(outputP->length() % 4 == 0);
+ }
+}
+
+
+
+string
+base64FromBytes(vector<unsigned char> const& bytes,
+ newlineCtl const newlineCtl) {
+
+ string retval;
+
+ if (bytes.size() == 0) {
+ if (newlineCtl == NEWLINE_YES)
+ retval = "\r\n";
+ else
+ retval = "";
+ } else {
+ // It would be good to preallocate retval. Need to look up
+ // how to do that.
+ for (size_t chunkStart = 0;
+ chunkStart < bytes.size();
+ chunkStart += base64MaxChunkSize) {
+
+ size_t const chunkSize(
+ min(base64MaxChunkSize, bytes.size() - chunkStart));
+
+ encodeChunk(bytes, chunkStart, chunkSize, &retval);
+
+ if (newlineCtl == NEWLINE_YES)
+ // Append a courtesy crlf
+ retval += "\r\n";
+ }
+ }
+ return retval;
+}
+
+
+
+vector<unsigned char>
+bytesFromBase64(string const& base64) {
+
+ vector<unsigned char> retval;
+ bitBuffer buffer;
+ unsigned int npad;
+
+ npad = 0; // No pad characters seen yet
+
+ for (unsigned int cursor = 0; cursor < base64.length(); ++cursor) {
+ char const thisChar(base64[cursor] & 0x7f);
+
+ if (thisChar == '\r' || thisChar == '\n' || thisChar == ' ') {
+ // ignore this punctuation
+ } else {
+ if (thisChar == base64Pad) {
+ // This pad character is here to synchronize a chunk to
+ // a multiple of 24 bits (4 base64 characters; 3 bytes).
+ buffer.discardResidue();
+ } else {
+ unsigned int const tableIndex(thisChar);
+ if (table_a2b_base64[tableIndex] == -1)
+ throwf("Contains non-base64 character "
+ "with ASCII code 0x%02x", thisChar);
+
+ buffer.shiftIn6Bits(table_a2b_base64[tableIndex]);
+
+ if (buffer.bitCount() >= 8) {
+ unsigned char thisByte;
+ buffer.shiftOut8Bits(&thisByte);
+ retval.push_back(thisByte);
+ }
+ }
+ }
+ }
+
+ if (buffer.bitCount() > 0)
+ throwf("Not a multiple of 4 characters");
+
+ return retval;
+}
+
+} //namespace
Modified: freeswitch/trunk/libs/xmlrpc-c/src/cpp/client.cpp
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/src/cpp/client.cpp (original)
+++ freeswitch/trunk/libs/xmlrpc-c/src/cpp/client.cpp Fri May 23 16:56:24 2008
@@ -9,36 +9,25 @@
help from internal C utility libraries).
=============================================================================*/
+#include <stdlib.h>
#include <cassert>
#include <string>
+#include <vector>
#include "xmlrpc-c/girerr.hpp"
using girerr::error;
+using girerr::throwf;
#include "xmlrpc-c/girmem.hpp"
using girmem::autoObjectPtr;
using girmem::autoObject;
+#include "env_wrap.hpp"
#include "xmlrpc-c/base.h"
#include "xmlrpc-c/client.h"
#include "xmlrpc-c/transport.h"
-/* transport_config.h defines XMLRPC_DEFAULT_TRANSPORT,
- MUST_BUILD_WININET_CLIENT, MUST_BUILD_CURL_CLIENT,
- MUST_BUILD_LIBWWW_CLIENT
-*/
-#include "transport_config.h"
-
-#if MUST_BUILD_WININET_CLIENT
-#include "xmlrpc_wininet_transport.h"
-#endif
-#if MUST_BUILD_CURL_CLIENT
-#include "xmlrpc_curl_transport.h"
-#endif
-#if MUST_BUILD_LIBWWW_CLIENT
-#include "xmlrpc_libwww_transport.h"
-#endif
-
#include "xmlrpc-c/base.hpp"
#include "xmlrpc-c/xml.hpp"
#include "xmlrpc-c/client.hpp"
+#include "transport_config.h"
using namespace std;
using namespace xmlrpc_c;
@@ -46,23 +35,28 @@
namespace {
+void
+throwIfError(env_wrap const& env) {
+
+ if (env.env_c.fault_occurred)
+ throw(error(env.env_c.fault_string));
+}
+
+
+
class memblockStringWrapper {
public:
memblockStringWrapper(string const value) {
- xmlrpc_env env;
- xmlrpc_env_init(&env);
+ env_wrap env;
- this->memblockP = XMLRPC_MEMBLOCK_NEW(char, &env, 0);
+ this->memblockP = XMLRPC_MEMBLOCK_NEW(char, &env.env_c, 0);
+ throwIfError(env);
- if (env.fault_occurred)
- throw(error(env.fault_string));
-
- XMLRPC_MEMBLOCK_APPEND(char, &env, this->memblockP,
+ XMLRPC_MEMBLOCK_APPEND(char, &env.env_c, this->memblockP,
value.c_str(), value.size());
- if (env.fault_occurred)
- throw(error(env.fault_string));
+ throwIfError(env);
}
memblockStringWrapper(xmlrpc_mem_block * const memblockP) :
@@ -79,6 +73,30 @@
namespace xmlrpc_c {
+struct client_xml_impl {
+ /* We have both kinds of pointers to give the user flexibility -- we
+ have constructors that take both. But the simple pointer
+ 'transportP' is valid in both cases.
+ */
+ clientXmlTransport * transportP;
+ clientXmlTransportPtr transportPtr;
+ xmlrpc_dialect dialect;
+
+ client_xml_impl(clientXmlTransport * const transportP,
+ xmlrpc_dialect const dialect = xmlrpc_dialect_i8) :
+ transportP(transportP),
+ dialect(dialect) {}
+
+ client_xml_impl(clientXmlTransportPtr const transportPtr,
+ clientXmlTransport * const transportP,
+ xmlrpc_dialect const dialect = xmlrpc_dialect_i8) :
+ transportP(transportP),
+ transportPtr(transportPtr),
+ dialect(dialect) {}
+};
+
+
+
carriageParm::carriageParm() {}
@@ -87,6 +105,33 @@
+carriageParmPtr::carriageParmPtr() {
+ // Base class constructor will construct pointer that points to nothing
+}
+
+
+
+carriageParmPtr::carriageParmPtr(
+carriageParm * const carriageParmP) : autoObjectPtr(carriageParmP) {}
+
+
+
+carriageParm *
+carriageParmPtr::operator->() const {
+
+ autoObject * const p(this->objectP);
+ return dynamic_cast<carriageParm *>(p);
+}
+
+
+
+carriageParm *
+carriageParmPtr::get() const {
+ return dynamic_cast<carriageParm *>(objectP);
+}
+
+
+
carriageParm_http0::carriageParm_http0() :
c_serverInfoP(NULL) {}
@@ -99,6 +144,7 @@
}
+
carriageParm_http0::~carriageParm_http0() {
if (this->c_serverInfoP)
@@ -113,13 +159,158 @@
if (c_serverInfoP)
throw(error("object already instantiated"));
- xmlrpc_env env;
- xmlrpc_env_init(&env);
+ env_wrap env;
+
+ this->c_serverInfoP =
+ xmlrpc_server_info_new(&env.env_c, serverUrl.c_str());
+ throwIfError(env);
+}
+
+
+
+void
+carriageParm_http0::setUser(string const userid,
+ string const password) {
+
+ if (!this->c_serverInfoP)
+ throw(error("object not instantiated"));
+
+ env_wrap env;
+
+ xmlrpc_server_info_set_user(
+ &env.env_c, this->c_serverInfoP, userid.c_str(), password.c_str());
+
+ if (env.env_c.fault_occurred)
+ throw(error(env.env_c.fault_string));
+}
+
+
+
+void
+carriageParm_http0::allowAuthBasic() {
+
+ if (!this->c_serverInfoP)
+ throw(error("object not instantiated"));
+
+ env_wrap env;
+
+ xmlrpc_server_info_allow_auth_basic(&env.env_c, this->c_serverInfoP);
+
+ if (env.env_c.fault_occurred)
+ throw(error(env.env_c.fault_string));
+}
+
+
+
+void
+carriageParm_http0::disallowAuthBasic() {
+
+ if (!this->c_serverInfoP)
+ throw(error("object not instantiated"));
+
+ env_wrap env;
+
+ xmlrpc_server_info_disallow_auth_basic(&env.env_c, this->c_serverInfoP);
+
+ if (env.env_c.fault_occurred)
+ throw(error(env.env_c.fault_string));
+}
+
+
+
+void
+carriageParm_http0::allowAuthDigest() {
+
+ if (!this->c_serverInfoP)
+ throw(error("object not instantiated"));
+
+ env_wrap env;
+
+ xmlrpc_server_info_allow_auth_digest(&env.env_c, this->c_serverInfoP);
+
+ if (env.env_c.fault_occurred)
+ throw(error(env.env_c.fault_string));
+}
- this->c_serverInfoP = xmlrpc_server_info_new(&env, serverUrl.c_str());
- if (env.fault_occurred)
- throw(error(env.fault_string));
+
+void
+carriageParm_http0::disallowAuthDigest() {
+
+ if (!this->c_serverInfoP)
+ throw(error("object not instantiated"));
+
+ env_wrap env;
+
+ xmlrpc_server_info_disallow_auth_digest(&env.env_c, this->c_serverInfoP);
+
+ if (env.env_c.fault_occurred)
+ throw(error(env.env_c.fault_string));
+}
+
+
+
+void
+carriageParm_http0::allowAuthNegotiate() {
+
+ if (!this->c_serverInfoP)
+ throw(error("object not instantiated"));
+
+ env_wrap env;
+
+ xmlrpc_server_info_allow_auth_negotiate(&env.env_c, this->c_serverInfoP);
+
+ if (env.env_c.fault_occurred)
+ throw(error(env.env_c.fault_string));
+}
+
+
+
+void
+carriageParm_http0::disallowAuthNegotiate() {
+
+ if (!this->c_serverInfoP)
+ throw(error("object not instantiated"));
+
+ env_wrap env;
+
+ xmlrpc_server_info_disallow_auth_negotiate(
+ &env.env_c, this->c_serverInfoP);
+
+ if (env.env_c.fault_occurred)
+ throw(error(env.env_c.fault_string));
+}
+
+
+
+void
+carriageParm_http0::allowAuthNtlm() {
+
+ if (!this->c_serverInfoP)
+ throw(error("object not instantiated"));
+
+ env_wrap env;
+
+ xmlrpc_server_info_allow_auth_ntlm(&env.env_c, this->c_serverInfoP);
+
+ if (env.env_c.fault_occurred)
+ throw(error(env.env_c.fault_string));
+}
+
+
+
+void
+carriageParm_http0::disallowAuthNtlm() {
+
+ if (!this->c_serverInfoP)
+ throw(error("object not instantiated"));
+
+ env_wrap env;
+
+ xmlrpc_server_info_disallow_auth_ntlm(&env.env_c, this->c_serverInfoP);
+
+ if (env.env_c.fault_occurred)
+ throw(error(env.env_c.fault_string));
}
@@ -128,43 +319,35 @@
carriageParm_http0::setBasicAuth(string const username,
string const password) {
- if (!c_serverInfoP)
+ if (!this->c_serverInfoP)
throw(error("object not instantiated"));
- xmlrpc_env env;
- xmlrpc_env_init(&env);
+ env_wrap env;
xmlrpc_server_info_set_basic_auth(
- &env, this->c_serverInfoP, username.c_str(), password.c_str());
-
- if (env.fault_occurred)
- throw(error(env.fault_string));
+ &env.env_c, this->c_serverInfoP, username.c_str(), password.c_str());
+ throwIfError(env);
}
-carriageParm_curl0::carriageParm_curl0(
- string const serverUrl
- ) {
-
- this->instantiate(serverUrl);
+carriageParm_http0Ptr::carriageParm_http0Ptr() {
+ // Base class constructor will construct pointer that points to nothing
}
-carriageParm_libwww0::carriageParm_libwww0(
- string const serverUrl
- ) {
- this->instantiate(serverUrl);
-}
+carriageParm_http0Ptr::carriageParm_http0Ptr(
+ carriageParm_http0 * const carriageParmP) :
+ carriageParmPtr(carriageParmP) {}
-carriageParm_wininet0::carriageParm_wininet0(
- string const serverUrl
- ) {
+carriageParm_http0 *
+carriageParm_http0Ptr::operator->() const {
- this->instantiate(serverUrl);
+ autoObject * const p(this->objectP);
+ return dynamic_cast<carriageParm_http0 *>(p);
}
@@ -192,6 +375,11 @@
+xmlTransactionPtr::xmlTransactionPtr(xmlTransaction * xmlTransP) :
+ autoObjectPtr(xmlTransP) {}
+
+
+
xmlTransaction *
xmlTransactionPtr::operator->() const {
autoObject * const p(this->objectP);
@@ -200,6 +388,51 @@
+struct xmlTranCtl {
+/*----------------------------------------------------------------------------
+ This contains information needed to conduct a transaction. You
+ construct it as you start the transaction and destroy it after the
+ work is done. You need this only for an asynchronous one, because
+ where the user starts and finishes the RPC in the same
+ libxmlrpc_client call, you can just keep this information in
+ various stack variables, and it's faster and easier to understand
+ that way.
+
+ The C transport is designed to take a xmlrpc_call_info argument for
+ similar stuff needed by the the C client object. But it's really
+ opaque to the transport, so we just let xmlTranCtl masquerade as
+ xmlprc_call_info in our call to the C transport.
+-----------------------------------------------------------------------------*/
+ xmlTranCtl(xmlTransactionPtr const& xmlTranP,
+ string const& callXml) :
+
+ xmlTranP(xmlTranP) {
+
+ env_wrap env;
+
+ this->callXmlP = XMLRPC_MEMBLOCK_NEW(char, &env.env_c, 0);
+ throwIfError(env);
+
+ XMLRPC_MEMBLOCK_APPEND(char, &env.env_c, this->callXmlP,
+ callXml.c_str(), callXml.size());
+ throwIfError(env);
+ }
+
+ ~xmlTranCtl() {
+ XMLRPC_MEMBLOCK_FREE(char, this->callXmlP);
+ }
+
+ xmlTransactionPtr const xmlTranP;
+ // The transaction we're controlling. Most notable use of this is
+ // that this object we inform when the transaction is done. This
+ // is where the response XML and other transaction results go.
+
+ xmlrpc_mem_block * callXmlP;
+ // The XML of the call. This is what the transport transports.
+};
+
+
+
clientXmlTransport::~clientXmlTransport() {}
@@ -208,6 +441,9 @@
clientXmlTransport::start(carriageParm * const carriageParmP,
string const& callXml,
xmlTransactionPtr const& xmlTranP) {
+
+ // Note: derived class clientXmlTransport_http overrides this,
+ // so it doesn't normally get used.
string responseXml;
@@ -219,9 +455,14 @@
void
-clientXmlTransport::finishAsync(xmlrpc_c::timeout const timeout) {
- if (timeout.finite == timeout.finite)
- throw(error("This class does not have finishAsync()"));
+clientXmlTransport::finishAsync(xmlrpc_c::timeout) {
+
+ // Since our start() does the whole thing, there's nothing for
+ // us to do.
+
+ // A derived class that overrides start() with something properly
+ // asynchronous had better also override finishAsync() with something
+ // substantial.
}
@@ -232,17 +473,16 @@
xmlrpc_mem_block * const responseXmlMP,
xmlrpc_env const transportEnv) {
- xmlTransactionPtr * const xmlTranPP =
- reinterpret_cast<xmlTransactionPtr *>(callInfoP);
+ xmlTranCtl * const xmlTranCtlP = reinterpret_cast<xmlTranCtl *>(callInfoP);
try {
if (transportEnv.fault_occurred) {
- (*xmlTranPP)->finishErr(error(transportEnv.fault_string));
+ xmlTranCtlP->xmlTranP->finishErr(error(transportEnv.fault_string));
} else {
string const responseXml(
XMLRPC_MEMBLOCK_CONTENTS(char, responseXmlMP),
XMLRPC_MEMBLOCK_SIZE(char, responseXmlMP));
- (*xmlTranPP)->finish(responseXml);
+ xmlTranCtlP->xmlTranP->finish(responseXml);
}
} catch(error) {
/* We can't throw an error back to C code, and the async_complete
@@ -251,17 +491,52 @@
*/
assert(false);
}
- delete(xmlTranPP);
+ delete(xmlTranCtlP);
- /* Ordinarily, *xmlTranPP is the last reference to **xmlTranPP
- (The xmlTransaction), so it will get destroyed too. But
+ /* Ordinarily, *xmlTranCtlP is the last reference to
+ xmlTranCtlP->xmlTranP, so that will get destroyed too. But
->finish() could conceivably create a new reference to
- **xmlTranPP, and then it would keep living.
+ xmlTranCtlP->xmlTranP, and then it would keep living.
*/
}
+void
+clientXmlTransport::setInterrupt(int *) {
+
+ throwf("The client XML transport is not interruptible");
+}
+
+
+
+clientXmlTransportPtr::clientXmlTransportPtr() {
+ // Base class constructor will construct pointer that points to nothing
+}
+
+
+
+clientXmlTransportPtr::clientXmlTransportPtr(
+ clientXmlTransport * const transportP) : autoObjectPtr(transportP) {}
+
+
+
+clientXmlTransport *
+clientXmlTransportPtr::get() const {
+ return dynamic_cast<clientXmlTransport *>(objectP);
+}
+
+
+
+clientXmlTransport *
+clientXmlTransportPtr::operator->() const {
+
+ autoObject * const p(this->objectP);
+ return dynamic_cast<clientXmlTransport *>(p);
+}
+
+
+
clientXmlTransport_http::~clientXmlTransport_http() {}
@@ -272,9 +547,6 @@
string const& callXml,
string * const responseXmlP) {
- xmlrpc_env env;
- xmlrpc_env_init(&env);
-
carriageParm_http0 * const carriageParmHttpP =
dynamic_cast<carriageParm_http0 *>(carriageParmP);
@@ -286,14 +558,15 @@
xmlrpc_mem_block * responseXmlMP;
- this->c_transportOpsP->call(&env,
+ env_wrap env;
+
+ this->c_transportOpsP->call(&env.env_c,
this->c_transportP,
carriageParmHttpP->c_serverInfoP,
callXmlM.memblockP,
&responseXmlMP);
- if (env.fault_occurred)
- throw(error(env.fault_string));
+ throwIfError(env);
memblockStringWrapper responseHolder(responseXmlMP);
// Makes responseXmlMP get freed at end of scope
@@ -310,8 +583,7 @@
string const& callXml,
xmlTransactionPtr const& xmlTranP) {
- xmlrpc_env env;
- xmlrpc_env_init(&env);
+ env_wrap env;
carriageParm_http0 * const carriageParmHttpP =
dynamic_cast<carriageParm_http0 *>(carriageParmP);
@@ -320,27 +592,20 @@
throw(error("HTTP client XML transport called with carriage "
"parameter object not of type carriageParm_http"));
- memblockStringWrapper callXmlM(callXml);
-
- /* xmlTranP2 is the reference to the XML transaction that is held by
- the running transaction, in C code. It lives in dynamically allocated
- storage and xmlTranP2P points to it.
- */
- xmlTransactionPtr * const xmlTranP2P(new xmlTransactionPtr(xmlTranP));
+ xmlTranCtl * const tranCtlP(new xmlTranCtl(xmlTranP, callXml));
try {
this->c_transportOpsP->send_request(
- &env,
+ &env.env_c,
this->c_transportP,
carriageParmHttpP->c_serverInfoP,
- callXmlM.memblockP,
+ tranCtlP->callXmlP,
&this->asyncComplete,
- reinterpret_cast<xmlrpc_call_info *>(xmlTranP2P));
+ reinterpret_cast<xmlrpc_call_info *>(tranCtlP));
- if (env.fault_occurred)
- throw(error(env.fault_string));
+ throwIfError(env);
} catch (...) {
- delete xmlTranP2P;
+ delete tranCtlP;
throw;
}
}
@@ -360,219 +625,263 @@
+void
+clientXmlTransport_http::setInterrupt(int * const interruptP) {
+
+ if (this->c_transportOpsP->set_interrupt)
+ this->c_transportOpsP->set_interrupt(this->c_transportP, interruptP);
+}
+
+
+
+bool const haveCurl(
#if MUST_BUILD_CURL_CLIENT
+true
+#else
+false
+#endif
+);
+
+bool const haveLibwww(
+#if MUST_BUILD_LIBWWW_CLIENT
+true
+#else
+false
+#endif
+);
-clientXmlTransport_curl::clientXmlTransport_curl(
- string const networkInterface,
- bool const noSslVerifyPeer,
- bool const noSslVerifyHost,
- string const userAgent) {
+bool const haveWininet(
+#if MUST_BUILD_WININET_CLIENT
+true
+#else
+false
+#endif
+);
- struct xmlrpc_curl_xportparms transportParms;
- transportParms.network_interface =
- networkInterface.size() > 0 ? networkInterface.c_str() : NULL;
- transportParms.no_ssl_verifypeer = noSslVerifyPeer;
- transportParms.no_ssl_verifyhost = noSslVerifyHost;
- transportParms.user_agent =
- userAgent.size() > 0 ? userAgent.c_str() : NULL;
- this->c_transportOpsP = &xmlrpc_curl_transport_ops;
+vector<string>
+clientXmlTransport_http::availableTypes() {
- xmlrpc_env env;
- xmlrpc_env_init(&env);
+ vector<string> retval;
- xmlrpc_curl_transport_ops.create(
- &env, 0, "", "", (xmlrpc_xportparms *)&transportParms,
- XMLRPC_CXPSIZE(user_agent),
- &this->c_transportP);
+ if (haveCurl)
+ retval.push_back("curl");
- if (env.fault_occurred)
- throw(error(env.fault_string));
-}
-#else // MUST_BUILD_CURL_CLIENT
+ if (haveLibwww)
+ retval.push_back("libwww");
-clientXmlTransport_curl::clientXmlTransport_curl(string, bool, bool, string) {
+ if (haveWininet)
+ retval.push_back("wininet");
- throw("There is no Curl client XML transport in this XML-RPC client "
- "library");
+ return retval;
}
-#endif
-
-clientXmlTransport_curl::~clientXmlTransport_curl() {
+clientXmlTransportPtr
+clientXmlTransport_http::create() {
+/*----------------------------------------------------------------------------
+ Make an HTTP Client XML transport of any kind (Caller doesn't care).
+
+ Caller can find out what kind he got by trying dynamic casts.
- this->c_transportOpsP->destroy(this->c_transportP);
+ Caller can use a carriageParm_http0 with the transport.
+-----------------------------------------------------------------------------*/
+ if (haveCurl)
+ return clientXmlTransportPtr(new clientXmlTransport_curl());
+ else if (haveLibwww)
+ return clientXmlTransportPtr(new clientXmlTransport_libwww());
+ else if (haveWininet)
+ return clientXmlTransportPtr(new clientXmlTransport_wininet());
+ else
+ throwf("This XML-RPC client library contains no HTTP XML transports");
}
-#if MUST_BUILD_LIBWWW_CLIENT
+clientTransaction::clientTransaction() {}
-clientXmlTransport_libwww::clientXmlTransport_libwww(
- string const appname,
- string const appversion) {
- this->c_transportOpsP = &xmlrpc_libwww_transport_ops;
- xmlrpc_env env;
- xmlrpc_env_init(&env);
+clientTransactionPtr::clientTransactionPtr() {}
- xmlrpc_libwww_transport_ops.create(
- &env, 0, appname.c_str(), appversion.c_str(), NULL, 0,
- &this->c_transportP);
- if (env.fault_occurred)
- throw(error(env.fault_string));
-}
-#else // MUST_BUILD_LIBWWW_CLIENT
- clientXmlTransport_libwww::clientXmlTransport_libwww(string, string) {
+clientTransactionPtr::clientTransactionPtr(
+ clientTransaction * const transP) : autoObjectPtr(transP) {}
- throw(error("There is no Libwww client XML transport "
- "in this XML-RPC client library"));
-}
-#endif
+
+clientTransactionPtr::~clientTransactionPtr() {}
-clientXmlTransport_libwww::~clientXmlTransport_libwww() {
- this->c_transportOpsP->destroy(this->c_transportP);
+clientTransaction *
+clientTransactionPtr::operator->() const {
+ autoObject * const p(this->objectP);
+ return dynamic_cast<clientTransaction *>(p);
}
-#if MUST_BUILD_WININET_CLIENT
-
-clientXmlTransport_wininet::clientXmlTransport_wininet(
- bool const allowInvalidSslCerts
- ) {
+client::~client() {}
- struct xmlrpc_wininet_xportparms transportParms;
- transportParms.allowInvalidSSLCerts = allowInvalidSslCerts;
- this->c_transportOpsP = &xmlrpc_wininet_transport_ops;
+void
+client::start(carriageParm * const carriageParmP,
+ string const& methodName,
+ paramList const& paramList,
+ clientTransactionPtr const& tranP) {
+/*----------------------------------------------------------------------------
+ Start an RPC, wait for it to complete, and finish it.
- xmlrpc_env env;
- xmlrpc_env_init(&env);
+ Usually, a derived class overrides this with something that does
+ not wait for the RPC to complete, but rather arranges for something
+ to finish the RPC later when the RPC does complete.
+-----------------------------------------------------------------------------*/
+ rpcOutcome outcome;
- xmlrpc_wininet_transport_ops.create(
- &env, 0, "", "", &transportParms, XMLRPC_WXPSIZE(allowInvalidSSLCerts),
- &this->c_transportP);
+ this->call(carriageParmP, methodName, paramList, &outcome);
- if (env.fault_occurred)
- throw(error(env.fault_string));
+ tranP->finish(outcome);
}
-#else // MUST_BUILD_WININET_CLIENT
-clientXmlTransport_wininet::clientXmlTransport_wininet(bool const) {
- throw(error("There is no Wininet client XML transport "
- "in this XML-RPC client library"));
+void
+client::finishAsync(xmlrpc_c::timeout) {
+
+ // Since our start() does the whole thing, there's nothing for
+ // us to do.
+
+ // A derived class that overrides start() with something properly
+ // asynchronous had better also override finishAsync() with something
+ // substantial.
}
-#endif
-
-clientXmlTransport_wininet::~clientXmlTransport_wininet() {
+void
+client::setInterrupt(int *) {
- this->c_transportOpsP->destroy(this->c_transportP);
+ throwf("Clients of this type are not interruptible");
}
-clientTransaction::clientTransaction() {}
+clientPtr::clientPtr() {
+ // Base class constructor will construct pointer that points to nothing
+}
-clientTransactionPtr::clientTransactionPtr() {}
+clientPtr::clientPtr(
+ client * const clientP) : autoObjectPtr(clientP) {}
-clientTransactionPtr::~clientTransactionPtr() {}
+client *
+clientPtr::operator->() const {
+ autoObject * const p(this->objectP);
+ return dynamic_cast<client *>(p);
+}
-clientTransaction *
-clientTransactionPtr::operator->() const {
- autoObject * const p(this->objectP);
- return dynamic_cast<clientTransaction *>(p);
+
+client *
+clientPtr::get() const {
+ return dynamic_cast<client *>(objectP);
}
-client::~client() {}
+client_xml::client_xml(clientXmlTransport * const transportP) {
+ this->implP = new client_xml_impl(transportP);
+}
-void
-client::start(carriageParm * const carriageParmP,
- string const methodName,
- paramList const& paramList,
- clientTransactionPtr const& tranP) {
-/*----------------------------------------------------------------------------
- Start an RPC, wait for it to complete, and finish it.
- Usually, a derived class overrides this with something that does
- not wait for the RPC to complete, but rather arranges for something
- to finish the RPC later when the RPC does complete.
------------------------------------------------------------------------------*/
- rpcOutcome outcome;
- this->call(carriageParmP, methodName, paramList, &outcome);
+client_xml::client_xml(clientXmlTransportPtr const transportPtr) {
- tranP->finish(outcome);
+ this->implP = new client_xml_impl(transportPtr, transportPtr.get());
}
-client_xml::client_xml(clientXmlTransport * const transportP) :
- transportP(transportP) {}
-
+client_xml::client_xml(clientXmlTransport * const transportP,
+ xmlrpc_dialect const dialect) {
+
+ this->implP = new client_xml_impl(transportP, dialect);
+}
+
+
+
+client_xml::client_xml(clientXmlTransportPtr const transportPtr,
+ xmlrpc_dialect const dialect) {
+
+ this->implP = new client_xml_impl(transportPtr, transportPtr.get(),
+ dialect);
+}
+
+
+
+client_xml::~client_xml() {
+
+ delete(this->implP);
+}
+
void
client_xml::call(carriageParm * const carriageParmP,
- string const methodName,
+ string const& methodName,
paramList const& paramList,
rpcOutcome * const outcomeP) {
string callXml;
string responseXml;
- xml::generateCall(methodName, paramList, &callXml);
+ xml::generateCall(methodName, paramList, this->implP->dialect, &callXml);
xml::trace("XML-RPC CALL", callXml);
- this->transportP->call(carriageParmP, callXml, &responseXml);
-
+ try {
+ this->implP->transportP->call(carriageParmP, callXml, &responseXml);
+ } catch (error const& error) {
+ throwf("Unable to transport XML to server and "
+ "get XML response back. %s", error.what());
+ }
xml::trace("XML-RPC RESPONSE", responseXml);
-
- xml::parseResponse(responseXml, outcomeP);
+
+ try {
+ xml::parseResponse(responseXml, outcomeP);
+ } catch (error const& error) {
+ throwf("Response XML from server is not valid XML-RPC response. %s",
+ error.what());
+ }
}
void
client_xml::start(carriageParm * const carriageParmP,
- string const methodName,
+ string const& methodName,
paramList const& paramList,
clientTransactionPtr const& tranP) {
string callXml;
- xml::generateCall(methodName, paramList, &callXml);
+ xml::generateCall(methodName, paramList, this->implP->dialect, &callXml);
xml::trace("XML-RPC CALL", callXml);
xmlTransaction_clientPtr const xmlTranP(tranP);
- this->transportP->start(carriageParmP, callXml, xmlTranP);
+ this->implP->transportP->start(carriageParmP, callXml, xmlTranP);
}
@@ -580,11 +889,66 @@
void
client_xml::finishAsync(xmlrpc_c::timeout const timeout) {
- transportP->finishAsync(timeout);
+ this->implP->transportP->finishAsync(timeout);
}
+void
+client_xml::setInterrupt(int * const interruptP) {
+
+ this->implP->transportP->setInterrupt(interruptP);
+}
+
+
+
+serverAccessor::serverAccessor(clientPtr const clientP,
+ carriageParmPtr const carriageParmP) :
+
+ clientP(clientP), carriageParmP(carriageParmP) {};
+
+
+
+void
+serverAccessor::call(std::string const& methodName,
+ xmlrpc_c::paramList const& paramList,
+ xmlrpc_c::rpcOutcome * const outcomeP) const {
+
+ this->clientP->call(this->carriageParmP.get(),
+ methodName,
+ paramList,
+ outcomeP);
+}
+
+
+
+serverAccessorPtr::serverAccessorPtr() {
+ // Base class constructor will construct pointer that points to nothing
+}
+
+
+
+serverAccessorPtr::serverAccessorPtr(
+ serverAccessor * const serverAccessorParmP) :
+ autoObjectPtr(serverAccessorParmP) {}
+
+
+
+serverAccessor *
+serverAccessorPtr::operator->() const {
+
+ autoObject * const p(this->objectP);
+ return dynamic_cast<serverAccessor *>(p);
+}
+
+
+
+serverAccessor *
+serverAccessorPtr::get() const {
+ return dynamic_cast<serverAccessor *>(objectP);
+}
+
+
connection::connection(client * const clientP,
carriageParm * const carriageParmP) :
@@ -596,20 +960,43 @@
-rpc::rpc(string const methodName,
- xmlrpc_c::paramList const& paramList) {
+struct rpc_impl {
+ enum state {
+ STATE_UNFINISHED, // RPC is running or not started yet
+ STATE_ERROR, // We couldn't execute the RPC
+ STATE_FAILED, // RPC executed successfully, but failed per XML-RPC
+ STATE_SUCCEEDED // RPC is done, no exception
+ };
+ enum state state;
+ girerr::error * errorP; // Defined only in STATE_ERROR
+ rpcOutcome outcome;
+ // Defined only in STATE_FAILED and STATE_SUCCEEDED
+ string methodName;
+ xmlrpc_c::paramList paramList;
+
+ rpc_impl(string const& methodName,
+ xmlrpc_c::paramList const& paramList) :
+ state(STATE_UNFINISHED),
+ methodName(methodName),
+ paramList(paramList) {}
+};
+
+
+
+rpc::rpc(string const methodName,
+ paramList const& paramList) {
- this->state = STATE_UNFINISHED;
- this->methodName = methodName;
- this->paramList = paramList;
+ this->implP = new rpc_impl(methodName, paramList);
}
rpc::~rpc() {
+
+ if (this->implP->state == rpc_impl::STATE_ERROR)
+ delete(this->implP->errorP);
- if (this->state == STATE_ERROR)
- delete(this->errorP);
+ delete(this->implP);
}
@@ -618,16 +1005,17 @@
rpc::call(client * const clientP,
carriageParm * const carriageParmP) {
- if (this->state != STATE_UNFINISHED)
+ if (this->implP->state != rpc_impl::STATE_UNFINISHED)
throw(error("Attempt to execute an RPC that has already been "
"executed"));
clientP->call(carriageParmP,
- this->methodName,
- this->paramList,
- &this->outcome);
+ this->implP->methodName,
+ this->implP->paramList,
+ &this->implP->outcome);
- this->state = outcome.succeeded() ? STATE_SUCCEEDED : STATE_FAILED;
+ this->implP->state = this->implP->outcome.succeeded() ?
+ rpc_impl::STATE_SUCCEEDED : rpc_impl::STATE_FAILED;
}
@@ -645,13 +1033,13 @@
rpc::start(client * const clientP,
carriageParm * const carriageParmP) {
- if (this->state != STATE_UNFINISHED)
+ if (this->implP->state != rpc_impl::STATE_UNFINISHED)
throw(error("Attempt to execute an RPC that has already been "
"executed"));
clientP->start(carriageParmP,
- this->methodName,
- this->paramList,
+ this->implP->methodName,
+ this->implP->paramList,
rpcPtr(this));
}
@@ -668,9 +1056,11 @@
void
rpc::finish(rpcOutcome const& outcome) {
- this->state = outcome.succeeded() ? STATE_SUCCEEDED : STATE_FAILED;
+ this->implP->state =
+ outcome.succeeded() ?
+ rpc_impl::STATE_SUCCEEDED : rpc_impl::STATE_FAILED;
- this->outcome = outcome;
+ this->implP->outcome = outcome;
this->notifyComplete();
}
@@ -680,8 +1070,8 @@
void
rpc::finishErr(error const& error) {
- this->state = STATE_ERROR;
- this->errorP = new girerr::error(error);
+ this->implP->state = rpc_impl::STATE_ERROR;
+ this->implP->errorP = new girerr::error(error);
this->notifyComplete();
}
@@ -710,23 +1100,23 @@
value
rpc::getResult() const {
- switch (this->state) {
- case STATE_UNFINISHED:
+ switch (this->implP->state) {
+ case rpc_impl::STATE_UNFINISHED:
throw(error("Attempt to get result of RPC that is not finished."));
break;
- case STATE_ERROR:
- throw(*this->errorP);
+ case rpc_impl::STATE_ERROR:
+ throw(*this->implP->errorP);
break;
- case STATE_FAILED:
- throw(error("RPC failed. " +
- this->outcome.getFault().getDescription()));
+ case rpc_impl::STATE_FAILED:
+ throw(error("RPC response indicates failure. " +
+ this->implP->outcome.getFault().getDescription()));
break;
- case STATE_SUCCEEDED: {
+ case rpc_impl::STATE_SUCCEEDED: {
// All normal
}
}
- return this->outcome.getResult();
+ return this->implP->outcome.getResult();
}
@@ -735,36 +1125,36 @@
fault
rpc::getFault() const {
- switch (this->state) {
- case STATE_UNFINISHED:
+ switch (this->implP->state) {
+ case rpc_impl::STATE_UNFINISHED:
throw(error("Attempt to get fault from RPC that is not finished"));
break;
- case STATE_ERROR:
- throw(*this->errorP);
+ case rpc_impl::STATE_ERROR:
+ throw(*this->implP->errorP);
break;
- case STATE_SUCCEEDED:
+ case rpc_impl::STATE_SUCCEEDED:
throw(error("Attempt to get fault from an RPC that succeeded"));
break;
- case STATE_FAILED: {
+ case rpc_impl::STATE_FAILED: {
// All normal
}
}
- return this->outcome.getFault();
+ return this->implP->outcome.getFault();
}
bool
rpc::isFinished() const {
- return (this->state != STATE_UNFINISHED);
+ return (this->implP->state != rpc_impl::STATE_UNFINISHED);
}
bool
rpc::isSuccessful() const {
- return (this->state == STATE_SUCCEEDED);
+ return (this->implP->state == rpc_impl::STATE_SUCCEEDED);
}
@@ -773,17 +1163,13 @@
-rpcPtr::rpcPtr(rpc * const rpcP) {
- this->instantiate(rpcP);
-}
+rpcPtr::rpcPtr(rpc * const rpcP) : clientTransactionPtr(rpcP) {}
rpcPtr::rpcPtr(string const methodName,
- xmlrpc_c::paramList const& paramList) {
-
- this->instantiate(new rpc(methodName, paramList));
-}
+ xmlrpc_c::paramList const& paramList) :
+ clientTransactionPtr(new rpc(methodName, paramList)) {}
@@ -813,8 +1199,8 @@
xml::parseResponse(responseXml, &outcome);
this->tranP->finish(outcome);
- } catch (error const caughtError) {
- this->tranP->finishErr(caughtError);
+ } catch (error const& error) {
+ this->tranP->finishErr(error);
}
}
@@ -833,10 +1219,8 @@
xmlTransaction_clientPtr::xmlTransaction_clientPtr(
- clientTransactionPtr const& tranP) {
-
- this->instantiate(new xmlTransaction_client(tranP));
-}
+ clientTransactionPtr const& tranP) :
+ xmlTransactionPtr(new xmlTransaction_client(tranP)) {}
Modified: freeswitch/trunk/libs/xmlrpc-c/src/cpp/client_simple.cpp
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/src/cpp/client_simple.cpp (original)
+++ freeswitch/trunk/libs/xmlrpc-c/src/cpp/client_simple.cpp Fri May 23 16:56:24 2008
@@ -1,16 +1,13 @@
#include <string>
+#include <cstring>
#include "xmlrpc-c/girerr.hpp"
using girerr::error;
+#include "env_wrap.hpp"
#include "xmlrpc-c/base.h"
#include "xmlrpc-c/base.hpp"
#include "xmlrpc-c/client.hpp"
#include <xmlrpc-c/client.hpp>
-/* transport_config.h defines XMLRPC_DEFAULT_TRANSPORT,
- MUST_BUILD_WININET_CLIENT, MUST_BUILD_CURL_CLIENT,
- MUST_BUILD_LIBWWW_CLIENT
-*/
-#include "transport_config.h"
#include "xmlrpc-c/client_simple.hpp"
@@ -21,12 +18,21 @@
namespace {
+
+void
+throwIfError(env_wrap const& env) {
+
+ if (env.env_c.fault_occurred)
+ throw(error(env.env_c.fault_string));
+}
+
+
+class cValueWrapper {
/*----------------------------------------------------------------------------
Use an object of this class to set up to remove a reference to an
xmlrpc_value object (a C object with manual reference management)
at then end of a scope -- even if the scope ends with a throw.
-----------------------------------------------------------------------------*/
-class cValueWrapper {
xmlrpc_value * valueP;
public:
cValueWrapper(xmlrpc_value * valueP) : valueP(valueP) {}
@@ -39,25 +45,9 @@
clientSimple::clientSimple() {
- if (string(XMLRPC_DEFAULT_TRANSPORT) == string("curl"))
- this->transportP = new clientXmlTransport_curl;
- else if (string(XMLRPC_DEFAULT_TRANSPORT) == string("libwww"))
- this->transportP = new clientXmlTransport_libwww;
- else if (string(XMLRPC_DEFAULT_TRANSPORT) == string("wininet"))
- this->transportP = new clientXmlTransport_wininet;
- else
- throw(error("INTERNAL ERROR: "
- "Default client XML transport is not one we recognize"));
-
- this->clientP = new client_xml(transportP);
-}
-
-
-
-clientSimple::~clientSimple() {
+ clientXmlTransportPtr const transportP(clientXmlTransport_http::create());
- delete this->clientP;
- delete this->transportP;
+ this->clientP = clientPtr(new client_xml(transportP));
}
@@ -71,7 +61,7 @@
rpcPtr rpcPtr(methodName, paramList());
- rpcPtr->call(this->clientP, &carriageParm);
+ rpcPtr->call(this->clientP.get(), &carriageParm);
*resultP = rpcPtr->getResult();
}
@@ -84,8 +74,7 @@
xmlrpc_value ** const paramArrayPP,
va_list args) {
- xmlrpc_env env;
- xmlrpc_env_init(&env);
+ env_wrap env;
/* The format is a sequence of parameter specifications, such as
"iiii" for 4 integer parameters. We add parentheses to make it
@@ -94,11 +83,11 @@
string const arrayFormat("(" + string(format) + ")");
const char * tail;
- xmlrpc_build_value_va(&env, arrayFormat.c_str(),
+ xmlrpc_build_value_va(&env.env_c, arrayFormat.c_str(),
args, paramArrayPP, &tail);
- if (env.fault_occurred)
- throw(error(env.fault_string));
+ if (env.env_c.fault_occurred)
+ throw(error(env.env_c.fault_string));
if (strlen(tail) != 0) {
/* xmlrpc_build_value_va() parses off a single value specification
@@ -125,8 +114,7 @@
carriageParm_http0 carriageParm(serverUrl);
- xmlrpc_env env;
- xmlrpc_env_init(&env);
+ env_wrap env;
xmlrpc_value * paramArrayP;
va_list args;
@@ -134,28 +122,29 @@
makeParamArray(format, ¶mArrayP, args);
va_end(args);
- if (env.fault_occurred)
- throw(error(env.fault_string));
+ if (env.env_c.fault_occurred)
+ throw(error(env.env_c.fault_string));
else {
cValueWrapper paramArrayWrapper(paramArrayP); // ensure destruction
- unsigned int const paramCount = xmlrpc_array_size(&env, paramArrayP);
+ unsigned int const paramCount(
+ xmlrpc_array_size(&env.env_c, paramArrayP));
- if (env.fault_occurred)
- throw(error(env.fault_string));
+ if (env.env_c.fault_occurred)
+ throw(error(env.env_c.fault_string));
paramList paramList;
for (unsigned int i = 0; i < paramCount; ++i) {
xmlrpc_value * paramP;
- xmlrpc_array_read_item(&env, paramArrayP, i, ¶mP);
- if (env.fault_occurred)
- throw(error(env.fault_string));
+ xmlrpc_array_read_item(&env.env_c, paramArrayP, i, ¶mP);
+ if (env.env_c.fault_occurred)
+ throw(error(env.env_c.fault_string));
else {
cValueWrapper paramWrapper(paramP); // ensure destruction
paramList.add(value(paramP));
}
}
rpcPtr rpcPtr(methodName, paramList);
- rpcPtr->call(this->clientP, &carriageParm);
+ rpcPtr->call(this->clientP.get(), &carriageParm);
*resultP = rpcPtr->getResult();
}
}
@@ -172,7 +161,7 @@
rpcPtr rpcPtr(methodName, paramList);
- rpcPtr->call(this->clientP, &carriageParm);
+ rpcPtr->call(this->clientP.get(), &carriageParm);
*resultP = rpcPtr->getResult();
}
Added: freeswitch/trunk/libs/xmlrpc-c/src/cpp/curl.cpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/cpp/curl.cpp Fri May 23 16:56:24 2008
@@ -0,0 +1,287 @@
+/*=============================================================================
+ curl.cpp
+===============================================================================
+ This is the Curl XML transport of the C++ XML-RPC client library for
+ Xmlrpc-c.
+
+ Note that unlike most of Xmlprc-c's C++ API, this is _not_ based on the
+ C client library. This code is independent of the C client library, and
+ is based directly on the client XML transport libraries (with a little
+ help from internal C utility libraries).
+=============================================================================*/
+
+#include <stdlib.h>
+#include <cassert>
+#include <string>
+
+#include "xmlrpc-c/girerr.hpp"
+using girerr::error;
+using girerr::throwf;
+#include "xmlrpc-c/girmem.hpp"
+using girmem::autoObjectPtr;
+using girmem::autoObject;
+#include "env_wrap.hpp"
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/client.h"
+#include "xmlrpc-c/transport.h"
+#include "xmlrpc-c/base_int.h"
+
+/* transport_config.h defines MUST_BUILD_CURL_CLIENT */
+#include "transport_config.h"
+
+#include "xmlrpc-c/client_transport.hpp"
+
+
+using namespace std;
+using namespace xmlrpc_c;
+
+
+
+namespace {
+
+class globalConstant {
+public:
+ globalConstant();
+ ~globalConstant();
+};
+
+
+
+globalConstant::globalConstant() {
+
+ // Not thread safe
+
+ xmlrpc_transport_setup setupFn;
+
+#if MUST_BUILD_CURL_CLIENT
+ setupFn = xmlrpc_curl_transport_ops.setup_global_const;
+#else
+ setupFn = NULL;
+#endif
+ if (setupFn) {
+ env_wrap env;
+
+ setupFn(&env.env_c); // Not thread safe
+
+ if (env.env_c.fault_occurred)
+ throwf("Failed to do global initialization "
+ "of Curl transport code. %s", env.env_c.fault_string);
+ }
+}
+
+
+
+globalConstant::~globalConstant() {
+
+ // Not thread safe
+
+ xmlrpc_transport_teardown teardownFn;
+
+#if MUST_BUILD_CURL_CLIENT
+ teardownFn = xmlrpc_curl_transport_ops.teardown_global_const;
+#else
+ teardownFn = NULL;
+#endif
+ if (teardownFn)
+ teardownFn(); // not thread safe
+}
+
+globalConstant globalConst;
+ // This object is never accessed. Its whole purpose to to be born and
+ // to die, which it does automatically as part of C++ program
+ // program initialization and termination.
+
+} // namespace
+
+
+namespace xmlrpc_c {
+
+carriageParm_curl0::carriageParm_curl0(
+ string const serverUrl
+ ) {
+
+ this->instantiate(serverUrl);
+}
+
+
+
+carriageParm_curl0Ptr::carriageParm_curl0Ptr() {
+ // Base class constructor will construct pointer that points to nothing
+}
+
+
+
+carriageParm_curl0Ptr::carriageParm_curl0Ptr(
+ carriageParm_curl0 * const carriageParmP) {
+ this->point(carriageParmP);
+}
+
+
+
+carriageParm_curl0 *
+carriageParm_curl0Ptr::operator->() const {
+
+ autoObject * const p(this->objectP);
+ return dynamic_cast<carriageParm_curl0 *>(p);
+}
+
+
+
+clientXmlTransport_curl::constrOpt::constrOpt() {
+
+ present.network_interface = false;
+ present.no_ssl_verifypeer = false;
+ present.no_ssl_verifyhost = false;
+ present.user_agent = false;
+ present.ssl_cert = false;
+ present.sslcerttype = false;
+ present.sslcertpasswd = false;
+ present.sslkey = false;
+ present.sslkeytype = false;
+ present.sslkeypasswd = false;
+ present.sslengine = false;
+ present.sslengine_default = false;
+ present.sslversion = false;
+ present.cainfo = false;
+ present.capath = false;
+ present.randomfile = false;
+ present.egdsocket = false;
+ present.ssl_cipher_list = false;
+ present.timeout = false;
+}
+
+
+
+#define DEFINE_OPTION_SETTER(OPTION_NAME, TYPE) \
+clientXmlTransport_curl::constrOpt & \
+clientXmlTransport_curl::constrOpt::OPTION_NAME(TYPE const& arg) { \
+ this->value.OPTION_NAME = arg; \
+ this->present.OPTION_NAME = true; \
+ return *this; \
+}
+
+DEFINE_OPTION_SETTER(network_interface, string);
+DEFINE_OPTION_SETTER(no_ssl_verifypeer, bool);
+DEFINE_OPTION_SETTER(no_ssl_verifyhost, bool);
+DEFINE_OPTION_SETTER(user_agent, string);
+DEFINE_OPTION_SETTER(ssl_cert, string);
+DEFINE_OPTION_SETTER(sslcerttype, string);
+DEFINE_OPTION_SETTER(sslcertpasswd, string);
+DEFINE_OPTION_SETTER(sslkey, string);
+DEFINE_OPTION_SETTER(sslkeytype, string);
+DEFINE_OPTION_SETTER(sslkeypasswd, string);
+DEFINE_OPTION_SETTER(sslengine, string);
+DEFINE_OPTION_SETTER(sslengine_default, bool);
+DEFINE_OPTION_SETTER(sslversion, xmlrpc_sslversion);
+DEFINE_OPTION_SETTER(cainfo, string);
+DEFINE_OPTION_SETTER(capath, string);
+DEFINE_OPTION_SETTER(randomfile, string);
+DEFINE_OPTION_SETTER(egdsocket, string);
+DEFINE_OPTION_SETTER(ssl_cipher_list, string);
+DEFINE_OPTION_SETTER(timeout, unsigned int);
+
+#undef DEFINE_OPTION_SETTER
+
+#if MUST_BUILD_CURL_CLIENT
+
+void
+clientXmlTransport_curl::initialize(constrOpt const& opt) {
+ struct xmlrpc_curl_xportparms transportParms;
+
+ transportParms.network_interface = opt.present.network_interface ?
+ opt.value.network_interface.c_str() : NULL;
+ transportParms.no_ssl_verifypeer = opt.present.no_ssl_verifypeer ?
+ opt.value.no_ssl_verifypeer : false;
+ transportParms.no_ssl_verifyhost = opt.present.no_ssl_verifyhost ?
+ opt.value.no_ssl_verifyhost : false;
+ transportParms.user_agent = opt.present.user_agent ?
+ opt.value.user_agent.c_str() : NULL;
+ transportParms.ssl_cert = opt.present.ssl_cert ?
+ opt.value.ssl_cert.c_str() : NULL;
+ transportParms.sslcerttype = opt.present.sslcerttype ?
+ opt.value.sslcerttype.c_str() : NULL;
+ transportParms.sslcertpasswd = opt.present.sslcertpasswd ?
+ opt.value.sslcertpasswd.c_str() : NULL;
+ transportParms.sslkey = opt.present.sslkey ?
+ opt.value.sslkey.c_str() : NULL;
+ transportParms.sslkeytype = opt.present.sslkeytype ?
+ opt.value.sslkeytype.c_str() : NULL;
+ transportParms.sslkeypasswd = opt.present.sslkeypasswd ?
+ opt.value.sslkeypasswd.c_str() : NULL;
+ transportParms.sslengine = opt.present.sslengine ?
+ opt.value.sslengine.c_str() : NULL;
+ transportParms.sslengine_default = opt.present.sslengine_default ?
+ opt.value.sslengine_default : false;
+ transportParms.sslversion = opt.present.sslversion ?
+ opt.value.sslversion : XMLRPC_SSLVERSION_DEFAULT;
+ transportParms.cainfo = opt.present.cainfo ?
+ opt.value.cainfo.c_str() : NULL;
+ transportParms.capath = opt.present.capath ?
+ opt.value.capath.c_str() : NULL;
+ transportParms.randomfile = opt.present.randomfile ?
+ opt.value.randomfile.c_str() : NULL;
+ transportParms.egdsocket = opt.present.egdsocket ?
+ opt.value.egdsocket.c_str() : NULL;
+ transportParms.ssl_cipher_list = opt.present.ssl_cipher_list ?
+ opt.value.ssl_cipher_list.c_str() : NULL;
+ transportParms.timeout = opt.present.timeout ?
+ opt.value.timeout : 0;
+
+ this->c_transportOpsP = &xmlrpc_curl_transport_ops;
+
+ env_wrap env;
+
+ xmlrpc_curl_transport_ops.create(
+ &env.env_c, 0, "", "",
+ &transportParms, XMLRPC_CXPSIZE(timeout),
+ &this->c_transportP);
+
+ if (env.env_c.fault_occurred)
+ throw(error(env.env_c.fault_string));
+}
+
+#else // MUST_BUILD_CURL_CLIENT
+
+void
+clientXmlTransport_curl::initialize(constrOpt const& opt) {
+
+ throw(error("There is no Curl client XML transport in this XML-RPC client "
+ "library"));
+}
+
+#endif
+
+clientXmlTransport_curl::clientXmlTransport_curl(constrOpt const& opt) {
+
+ this->initialize(opt);
+}
+
+
+
+clientXmlTransport_curl::clientXmlTransport_curl(
+ string const networkInterface,
+ bool const noSslVerifyPeer,
+ bool const noSslVerifyHost,
+ string const userAgent) {
+
+ clientXmlTransport_curl::constrOpt opt;
+
+ if (networkInterface.size() > 0)
+ opt.network_interface(networkInterface);
+ opt.no_ssl_verifypeer(noSslVerifyPeer);
+ opt.no_ssl_verifyhost(noSslVerifyHost);
+ if (userAgent.size() > 0)
+ opt.user_agent(userAgent);
+
+ this->initialize(opt);
+}
+
+
+
+clientXmlTransport_curl::~clientXmlTransport_curl() {
+
+ this->c_transportOpsP->destroy(this->c_transportP);
+}
+
+
+} // namespace
Added: freeswitch/trunk/libs/xmlrpc-c/src/cpp/env_wrap.cpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/cpp/env_wrap.cpp Fri May 23 16:56:24 2008
@@ -0,0 +1,18 @@
+#include "xmlrpc-c/util.h"
+
+#include "env_wrap.hpp"
+
+namespace xmlrpc_c {
+
+env_wrap::env_wrap() {
+ xmlrpc_env_init(&this->env_c);
+}
+
+
+
+env_wrap::~env_wrap() {
+ xmlrpc_env_clean(&this->env_c);
+}
+
+
+} // namespace
Added: freeswitch/trunk/libs/xmlrpc-c/src/cpp/env_wrap.hpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/cpp/env_wrap.hpp Fri May 23 16:56:24 2008
@@ -0,0 +1,26 @@
+#ifndef ENV_INT_HPP_INCLUDED
+#define ENV_INT_HPP_INCLUDED
+
+#include "xmlrpc-c/util.h"
+
+namespace xmlrpc_c {
+
+class env_wrap {
+/*----------------------------------------------------------------------------
+ A wrapper to assist in using the Xmlrpc-c C libraries in
+ Xmlrpc-c C++ code.
+
+ To use the C libraries, you have to use type xmlrpc_env, but that type
+ does not have an automatic destructor (because it's C), so it's hard
+ to throw an error from a context in which a variable of that type
+ exists. This wrapper provides that automatic destructor.
+-----------------------------------------------------------------------------*/
+public:
+ env_wrap();
+ ~env_wrap();
+ xmlrpc_env env_c;
+};
+
+
+} // namespace
+#endif
Added: freeswitch/trunk/libs/xmlrpc-c/src/cpp/girerr.cpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/cpp/girerr.cpp Fri May 23 16:56:24 2008
@@ -0,0 +1,28 @@
+#include <string>
+
+#include "xmlrpc-c/string_int.h"
+#include "xmlrpc-c/girerr.hpp"
+
+using namespace std;
+
+namespace girerr {
+
+void
+throwf(const char * const format, ...) {
+
+ va_list varargs;
+ va_start(varargs, format);
+
+ const char * value;
+ xmlrpc_vasprintf(&value, format, varargs);
+
+ string const valueString(value);
+
+ xmlrpc_strfree(value);
+
+ throw(girerr::error(valueString));
+
+ va_end(varargs);
+}
+
+} // namespace
Modified: freeswitch/trunk/libs/xmlrpc-c/src/cpp/girmem.cpp
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/src/cpp/girmem.cpp (original)
+++ freeswitch/trunk/libs/xmlrpc-c/src/cpp/girmem.cpp Fri May 23 16:56:24 2008
@@ -64,6 +64,22 @@
autoObjectPtr::autoObjectPtr(autoObject * const objectP) {
+
+ // Note: When someone attempts to use this constructor with a null
+ // argument, it's normally because a 'new' of the autoObject
+ // failed, before calling the autoObject's constructor, thus
+ // generating a null pointer.
+
+ // E.g. the following code, where the system is out of memory:
+ //
+ // class client : public autoObject { ... }
+ // class clientPtr : public autoObjectPtr { ... }
+ // clientPtr clientP(new client);
+
+ if (objectP == NULL)
+ throw(error("Object creation failed; trying to create autoObjectPtr "
+ "with a null autoObject pointer"));
+
this->objectP = objectP;
objectP->incref();
}
@@ -81,33 +97,54 @@
autoObjectPtr::~autoObjectPtr() {
- if (this->objectP) {
- bool dead;
- this->objectP->decref(&dead);
- if (dead)
- delete(this->objectP);
- }
+
+ this->unpoint();
}
void
-autoObjectPtr::instantiate(autoObject * const objectP) {
+autoObjectPtr::point(autoObject * const objectP) {
+ if (this->objectP != NULL)
+ throw(error("Already pointing"));
this->objectP = objectP;
objectP->incref();
}
-autoObjectPtr
-autoObjectPtr::operator=(autoObjectPtr const& autoObjectPtr) {
+void
+autoObjectPtr::unpoint() {
- if (this->objectP != NULL)
- throw(error("Already instantiated"));
- this->objectP = autoObjectPtr.objectP;
- this->objectP->incref();
+ if (this->objectP) {
+ bool dead;
+ this->objectP->decref(&dead);
+ if (dead) {
+ delete(this->objectP);
+ this->objectP = NULL;
+ }
+ }
+}
+
+
+
+autoObjectPtr
+autoObjectPtr::operator=(autoObjectPtr const& source) {
+ // If we're overwriting a variable that already points to something,
+ // we have to unpoint it from what it points to now before we can point
+ // it to what 'source' points to. But if the source and destination
+ // are the same object, we just want to leave the pointing alone.
+
+ if (this == &source) {
+ // Assignment of variable to itself; no-op
+ } else {
+ this->unpoint();
+ this->objectP = source.objectP;
+ if (this->objectP)
+ this->objectP->incref();
+ }
return *this;
}
@@ -115,9 +152,18 @@
autoObject *
autoObjectPtr::operator->() const {
+ if (this->objectP == NULL)
+ throw(error("attempt to dereference autoObjectPtr "
+ "which does not point to anything"));
return this->objectP;
}
+autoObject *
+autoObjectPtr::get() const {
+
+ return this->objectP;
+}
+
} // namespace
Added: freeswitch/trunk/libs/xmlrpc-c/src/cpp/libwww.cpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/cpp/libwww.cpp Fri May 23 16:56:24 2008
@@ -0,0 +1,158 @@
+/*=============================================================================
+ libwww.cpp
+===============================================================================
+ This is the Libwww XML transport of the C++ XML-RPC client library for
+ Xmlrpc-c.
+=============================================================================*/
+
+#include <stdlib.h>
+#include <cassert>
+#include <string>
+
+#include "xmlrpc-c/girerr.hpp"
+using girerr::error;
+using girerr::throwf;
+#include "xmlrpc-c/girmem.hpp"
+using girmem::autoObjectPtr;
+using girmem::autoObject;
+#include "env_wrap.hpp"
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/client.h"
+#include "xmlrpc-c/transport.h"
+#include "xmlrpc-c/base_int.h"
+
+/* transport_config.h defines MUST_BUILD_LIBWWW_CLIENT */
+#include "transport_config.h"
+
+#include "xmlrpc-c/client_transport.hpp"
+
+
+using namespace std;
+using namespace xmlrpc_c;
+
+
+namespace {
+
+class globalConstant {
+public:
+ globalConstant();
+ ~globalConstant();
+};
+
+
+
+globalConstant::globalConstant() {
+
+ // Not thread safe
+
+ xmlrpc_transport_setup setupFn;
+
+#if MUST_BUILD_LIBWWW_CLIENT
+ setupFn = xmlrpc_libwww_transport_ops.setup_global_const;
+#else
+ setupFn = NULL;
+#endif
+ if (setupFn) {
+ env_wrap env;
+
+ setupFn(&env.env_c); // Not thread safe
+
+ if (env.env_c.fault_occurred)
+ throwf("Failed to do global initialization "
+ "of Libwww transport code. %s", env.env_c.fault_string);
+ }
+}
+
+
+
+globalConstant::~globalConstant() {
+
+ // Not thread safe
+
+ xmlrpc_transport_teardown teardownFn;
+
+#if MUST_BUILD_LIBWWW_CLIENT
+ teardownFn = xmlrpc_libwww_transport_ops.teardown_global_const;
+#else
+ teardownFn = NULL;
+#endif
+ if (teardownFn)
+ teardownFn(); // not thread safe
+}
+
+
+globalConstant globalConst;
+ // This object is never accessed. Its whole purpose to to be born and
+ // to die, which it does automatically as part of C++ program
+ // program initialization and termination.
+
+} // namespace
+
+
+namespace xmlrpc_c {
+
+carriageParm_libwww0::carriageParm_libwww0(
+ string const serverUrl
+ ) {
+
+ this->instantiate(serverUrl);
+}
+
+
+
+carriageParm_libwww0Ptr::carriageParm_libwww0Ptr() {
+ // Base class constructor will construct pointer that points to nothing
+}
+
+
+
+carriageParm_libwww0Ptr::carriageParm_libwww0Ptr(
+ carriageParm_libwww0 * const carriageParmP) {
+ this->point(carriageParmP);
+}
+
+
+
+carriageParm_libwww0 *
+carriageParm_libwww0Ptr::operator->() const {
+
+ autoObject * const p(this->objectP);
+ return dynamic_cast<carriageParm_libwww0 *>(p);
+}
+
+
+
+#if MUST_BUILD_LIBWWW_CLIENT
+
+clientXmlTransport_libwww::clientXmlTransport_libwww(
+ string const appname,
+ string const appversion) {
+
+ this->c_transportOpsP = &xmlrpc_libwww_transport_ops;
+
+ env_wrap env;
+
+ xmlrpc_libwww_transport_ops.create(
+ &env.env_c, 0, appname.c_str(), appversion.c_str(), NULL, 0,
+ &this->c_transportP);
+
+ if (env.env_c.fault_occurred)
+ throw(error(env.env_c.fault_string));
+}
+
+#else // MUST_BUILD_LIBWWW_CLIENT
+ clientXmlTransport_libwww::clientXmlTransport_libwww(string, string) {
+
+ throw(error("There is no Libwww client XML transport "
+ "in this XML-RPC client library"));
+}
+
+#endif
+
+
+clientXmlTransport_libwww::~clientXmlTransport_libwww() {
+
+ this->c_transportOpsP->destroy(this->c_transportP);
+}
+
+} // namespace
Modified: freeswitch/trunk/libs/xmlrpc-c/src/cpp/outcome.cpp
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/src/cpp/outcome.cpp (original)
+++ freeswitch/trunk/libs/xmlrpc-c/src/cpp/outcome.cpp Fri May 23 16:56:24 2008
@@ -6,7 +6,7 @@
namespace xmlrpc_c {
- rpcOutcome::rpcOutcome() : valid(false) {}
+rpcOutcome::rpcOutcome() : valid(false) {}
rpcOutcome::rpcOutcome(xmlrpc_c::value const result) :
valid(true), _succeeded(true), result(result)
Added: freeswitch/trunk/libs/xmlrpc-c/src/cpp/packetsocket.cpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/cpp/packetsocket.cpp Fri May 23 16:56:24 2008
@@ -0,0 +1,590 @@
+/*============================================================================
+ packetsocket
+==============================================================================
+
+ This is a facility for communicating socket-style, with defined
+ packets like a datagram socket but with reliable delivery like a
+ stream socket. It's like a POSIX "sequential packet" socket, except
+ it is built on top of a stream socket, so it is usable on the many
+ systems that have stream sockets but not sequential packet sockets.
+
+ By Bryan Henderson 2007.05.12
+
+ Contributed to the public domain by its author.
+============================================================================*/
+
+
+/*============================================================================
+ The protocol for carrying packets on a character stream:
+
+ The protocol consists of the actual bytes to be transported with a bare
+ minimum of framing information added:
+
+ An ASCII Escape (<ESC> == 0x1B) character marks the start of a
+ 4-ASCII-character control word. These are defined:
+
+ <ESC>PKT : marks the beginning of a packet.
+ <ESC>END : marks the end of a packet.
+ <ESC>ESC : represents an <ESC> character in the packet
+ <ESC>NOP : no meaning
+
+ Any other bytes after <ESC> is a protocol error.
+
+ A stream is all the data transmitted during a single socket
+ connection.
+
+ End of stream in the middle of a packet is a protocol error.
+
+ All bytes not part of a control word are literal bytes of a packet.
+
+ You can create a packet socket from any file descriptor from which
+ you can read and write a bidirectional character stream. Typically,
+ it's a TCP socket.
+
+ One use of the NOP control word is to validate that the connection
+ is still working. You might send one periodically to detect, for
+ example, an unplugged TCP/IP network cable. It's probably better
+ to use the TCP keepalive facility for that.
+============================================================================*/
+
+#include <cassert>
+#include <string>
+#include <queue>
+#include <iostream>
+#include <sstream>
+#include <cstdio>
+#include <cstdlib>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <sys/types.h>
+
+#include "c_util.h"
+#include "xmlrpc-c/string_int.h"
+#include "xmlrpc-c/girerr.hpp"
+using girerr::throwf;
+
+#include "xmlrpc-c/packetsocket.hpp"
+
+
+#define ESC 0x1B // ASCII Escape character
+#define ESC_STR "\x1B"
+
+namespace xmlrpc_c {
+
+
+packet::packet() :
+ bytes(NULL), length(0), allocSize(0) {}
+
+
+
+void
+packet::initialize(const unsigned char * const data,
+ size_t const dataLength) {
+
+ this->bytes = reinterpret_cast<unsigned char *>(malloc(dataLength));
+
+ if (this->bytes == NULL)
+ throwf("Can't get storage for a %u-byte packet.", dataLength);
+
+ this->allocSize = dataLength;
+
+ memcpy(this->bytes, data, dataLength);
+
+ this->length = dataLength;
+}
+
+
+
+packet::packet(const unsigned char * const data,
+ size_t const dataLength) {
+
+ this->initialize(data, dataLength);
+}
+
+
+
+packet::packet(const char * const data,
+ size_t const dataLength) {
+
+ this->initialize(reinterpret_cast<const unsigned char *>(data),
+ dataLength);
+}
+
+
+
+packet::~packet() {
+
+ if (this->bytes)
+ free(bytes);
+}
+
+
+
+void
+packet::addData(const unsigned char * const data,
+ size_t const dataLength) {
+/*----------------------------------------------------------------------------
+ Add the 'length' bytes at 'data' to the packet.
+
+ We allocate whatever additional memory is needed to fit the new
+ data in.
+-----------------------------------------------------------------------------*/
+ size_t const neededSize(this->length + dataLength);
+
+ if (this->allocSize < neededSize)
+ this->bytes = reinterpret_cast<unsigned char *>(
+ realloc(this->bytes, neededSize));
+
+ if (this->bytes == NULL)
+ throwf("Can't get storage for a %u-byte packet.", neededSize);
+
+ memcpy(this->bytes + this->length, data, dataLength);
+
+ this->length += dataLength;
+}
+
+
+
+packetPtr::packetPtr() {
+ // Base class constructor will construct pointer that points to nothing
+}
+
+
+
+packetPtr::packetPtr(packet * const packetP) : autoObjectPtr(packetP) {}
+
+
+
+packet *
+packetPtr::operator->() const {
+
+ girmem::autoObject * const p(this->objectP);
+ return dynamic_cast<packet *>(p);
+}
+
+
+
+packetSocket::packetSocket(int const sockFd) {
+
+ int dupRc;
+
+ dupRc = dup(sockFd);
+
+ if (dupRc < 0)
+ throwf("dup() failed. errno=%d (%s)", errno, strerror(errno));
+ else {
+ this->sockFd = dupRc;
+
+ this->inEscapeSeq = false;
+ this->inPacket = false;
+
+ this->escAccum.len = 0;
+
+ fcntl(this->sockFd, F_SETFL, O_NONBLOCK);
+
+ this->eof = false;
+ }
+}
+
+
+
+packetSocket::~packetSocket() {
+
+ close(this->sockFd);
+}
+
+
+
+/*----------------------------------------------------------------------------
+ To complete the job, we should provide writing services analogous
+ to the reading services. That means a no-wait write method and
+ the ability to interrupt with a signal without corrupting the write
+ stream.
+
+ We're a little to lazy to do that now, since we don't need it yet,
+ but here's a design for that:
+
+ The packetSocket has a send queue of packets called the write
+ buffer. It stores packetPtr pointers to packets created by the
+ user.
+
+ packetSocket::write() adds a packet to the write buffer, then calls
+ packetSocket::writeToFile(). If you give it a null packetPtr,
+ it just calls writeToFile().
+
+ packetSocket::writeToFile() writes from the write buffer to the
+ socket whatever the socket will take immediately. It writes the
+ start sequence, writes the packet data, then writes the end
+ sequence. The packetSocket keeps track of where it is in the
+ process of writing the current send packet (including start end
+ end sequences) it is.
+
+ packetSocket::write() returns a "flushed" flag indicating that there
+ is nothing left in the write buffer.
+
+ packetSocket::writeWait() just calls packetSocket::write(), then
+ packetSocket::flush() in a poll() loop.
+-----------------------------------------------------------------------------*/
+
+
+static void
+writeFd(int const fd,
+ const unsigned char * const data,
+ size_t const size,
+ size_t * const bytesWrittenP) {
+
+ size_t totalBytesWritten;
+ bool full; // File image is "full" for now - won't take any more data
+
+ full = false;
+ totalBytesWritten = 0;
+
+ while (totalBytesWritten < size && !full) {
+ ssize_t rc;
+
+ rc = write(fd, &data[totalBytesWritten], size - totalBytesWritten);
+
+ if (rc < 0) {
+ if (errno == EAGAIN)
+ full = true;
+ else
+ throwf("write() of socket failed with errno %d (%s)",
+ errno, strerror(errno));
+ } else if (rc == 0)
+ throwf("Zero byte short write.");
+ else {
+ size_t const bytesWritten(rc);
+ totalBytesWritten += bytesWritten;
+ }
+ }
+ *bytesWrittenP = totalBytesWritten;
+}
+
+
+
+static void
+writeFdWait(int const fd,
+ const unsigned char * const data,
+ size_t const size) {
+/*----------------------------------------------------------------------------
+ Write the 'size' bytes at 'data' to the file image 'fd'. Wait as long
+ as it takes for the file image to be able to take all the data.
+-----------------------------------------------------------------------------*/
+ size_t totalBytesWritten;
+
+ // We do the first one blind because it will probably just work
+ // and we don't want to waste the poll() call and buffer arithmetic.
+
+ writeFd(fd, data, size, &totalBytesWritten);
+
+ while (totalBytesWritten < size) {
+ struct pollfd pollfds[1];
+
+ pollfds[0].fd = fd;
+ pollfds[0].events = POLLOUT;
+
+ poll(pollfds, ARRAY_SIZE(pollfds), -1);
+
+ size_t bytesWritten;
+
+ writeFd(fd, &data[totalBytesWritten], size - totalBytesWritten,
+ &bytesWritten);
+
+ totalBytesWritten += bytesWritten;
+ }
+}
+
+
+
+void
+packetSocket::writeWait(packetPtr const& packetP) const {
+
+ const unsigned char * const packetStart(
+ reinterpret_cast<const unsigned char *>(ESC_STR "PKT"));
+ const unsigned char * const packetEnd(
+ reinterpret_cast<const unsigned char *>(ESC_STR "END"));
+
+ writeFdWait(this->sockFd, packetStart, 4);
+
+ writeFdWait(this->sockFd, packetP->getBytes(), packetP->getLength());
+
+ writeFdWait(this->sockFd, packetEnd, 4);
+}
+
+
+
+static ssize_t
+libc_read(int const fd,
+ void * const buf,
+ size_t const count) {
+
+ return read(fd, buf, count);
+}
+
+
+
+void
+packetSocket::takeSomeEscapeSeq(const unsigned char * const buffer,
+ size_t const length,
+ size_t * const bytesTakenP) {
+/*----------------------------------------------------------------------------
+ Take and process some bytes from the incoming stream 'buffer',
+ which contains 'length' bytes, assuming they are within an escape
+ sequence.
+-----------------------------------------------------------------------------*/
+ size_t bytesTaken;
+
+ bytesTaken = 0;
+
+ while (this->escAccum.len < 3 && bytesTaken < length)
+ this->escAccum.bytes[this->escAccum.len++] = buffer[bytesTaken++];
+
+ assert(this->escAccum.len <= 3);
+
+ if (this->escAccum.len == 3) {
+ if (0) {
+ } else if (xmlrpc_memeq(this->escAccum.bytes, "NOP", 3)) {
+ // Nothing to do
+ } else if (xmlrpc_memeq(this->escAccum.bytes, "PKT", 3)) {
+ this->packetAccumP = packetPtr(new packet);
+ this->inPacket = true;
+ } else if (xmlrpc_memeq(this->escAccum.bytes, "END", 3)) {
+ if (this->inPacket) {
+ this->readBuffer.push(this->packetAccumP);
+ this->inPacket = false;
+ this->packetAccumP = packetPtr();
+ } else
+ throwf("END control word received without preceding PKT");
+ } else if (xmlrpc_memeq(this->escAccum.bytes, "ESC", 3)) {
+ if (this->inPacket)
+ this->packetAccumP->addData((const unsigned char *)ESC_STR, 1);
+ else
+ throwf("ESC control work received outside of a packet");
+ } else
+ throwf("Invalid escape sequence 0x%02x%02x%02x read from "
+ "stream socket under packet socket",
+ this->escAccum.bytes[0],
+ this->escAccum.bytes[1],
+ this->escAccum.bytes[2]);
+
+ this->inEscapeSeq = false;
+ this->escAccum.len = 0;
+ }
+ *bytesTakenP = bytesTaken;
+}
+
+
+
+void
+packetSocket::takeSomePacket(const unsigned char * const buffer,
+ size_t const length,
+ size_t * const bytesTakenP) {
+
+ assert(!this->inEscapeSeq);
+
+ const unsigned char * const escPos(
+ (const unsigned char *)memchr(buffer, ESC, length));
+
+ if (escPos) {
+ size_t const escOffset(escPos - &buffer[0]);
+ // move everything before the escape sequence into the
+ // packet accumulator.
+ this->packetAccumP->addData(buffer, escOffset);
+
+ // Caller can pick up from here; we don't know nothin' 'bout
+ // no escape sequences.
+
+ *bytesTakenP = escOffset;
+ } else {
+ // No complete packet yet and no substitution to do;
+ // just throw the whole thing into the accumulator.
+ this->packetAccumP->addData(buffer, length);
+ *bytesTakenP = length;
+ }
+}
+
+
+
+void
+packetSocket::verifyNothingAccumulated() {
+/*----------------------------------------------------------------------------
+ Throw an error if there is a partial packet accumulated.
+-----------------------------------------------------------------------------*/
+ if (this->inEscapeSeq)
+ throwf("Streams socket closed in the middle of an "
+ "escape sequence");
+
+ if (this->inPacket)
+ throwf("Stream socket closed in the middle of a packet "
+ "(%u bytes of packet received; no END marker to mark "
+ "end of packet)", this->packetAccumP->getLength());
+}
+
+
+
+void
+packetSocket::processBytesRead(const unsigned char * const buffer,
+ size_t const bytesRead) {
+
+ unsigned int cursor; // Cursor into buffer[]
+ cursor = 0;
+ while (cursor < bytesRead) {
+ size_t bytesTaken;
+
+ if (this->inEscapeSeq)
+ this->takeSomeEscapeSeq(&buffer[cursor],
+ bytesRead - cursor,
+ &bytesTaken);
+ else if (buffer[cursor] == ESC) {
+ this->inEscapeSeq = true;
+ bytesTaken = 1;
+ } else if (this->inPacket)
+ this->takeSomePacket(&buffer[cursor],
+ bytesRead - cursor,
+ &bytesTaken);
+ else
+ throwf("Byte 0x%02x is not in a packet or escape sequence. "
+ "Sender is probably not using packet socket protocol",
+ buffer[cursor]);
+
+ cursor += bytesTaken;
+ }
+}
+
+
+
+void
+packetSocket::readFromFile() {
+/*----------------------------------------------------------------------------
+ Read some data from the underlying stream socket. Read as much as is
+ available right now, up to 4K. Update 'this' to reflect the data read.
+
+ E.g. if we read an entire packet, we add it to the packet buffer
+ (this->readBuffer). If we read the first part of a packet, we add
+ it to the packet accumulator (*this->packetAccumP). If we read the end
+ of a packet, we add the full packet to the packet buffer and empty
+ the packet accumulator. Etc.
+-----------------------------------------------------------------------------*/
+ bool wouldblock;
+
+ wouldblock = false;
+
+ while (this->readBuffer.empty() && !this->eof && !wouldblock) {
+ unsigned char buffer[4096];
+ ssize_t rc;
+
+ rc = libc_read(this->sockFd, buffer, sizeof(buffer));
+
+ if (rc < 0) {
+ if (errno == EWOULDBLOCK)
+ wouldblock = true;
+ else
+ throwf("read() of socket failed with errno %d (%s)",
+ errno, strerror(errno));
+ } else {
+ size_t const bytesRead(rc);
+
+ if (bytesRead == 0) {
+ this->eof = true;
+ this->verifyNothingAccumulated();
+ } else
+ this->processBytesRead(buffer, bytesRead);
+ }
+ }
+}
+
+
+
+void
+packetSocket::read(bool * const eofP,
+ bool * const gotPacketP,
+ packetPtr * const packetPP) {
+/*----------------------------------------------------------------------------
+ Read one packet from the socket, through the internal packet buffer.
+
+ If there is a packet immediately available, return it as *packetPP and
+ return *gotPacketP true. Otherwise, return *gotPacketP false.
+
+ Iff the socket has no more data coming (it is shut down) and there
+ is no complete packet in the packet buffer, return *eofP.
+
+ This leaves one other possibility: there is no full packet immediately
+ available, but there may be in the future because the socket is still
+ alive. In that case, we return *eofP == false and *gotPacketP == false.
+
+ Any packet we return belongs to caller; Caller must delete it.
+-----------------------------------------------------------------------------*/
+ // Move any packets now waiting to be read in the underlying stream
+ // socket into our packet buffer (this->readBuffer).
+
+ this->readFromFile();
+
+ if (this->readBuffer.empty()) {
+ *gotPacketP = false;
+ *eofP = this->eof;
+ } else {
+ *gotPacketP = true;
+ *eofP = false;
+ *packetPP = this->readBuffer.front();
+ readBuffer.pop();
+ }
+}
+
+
+
+void
+packetSocket::readWait(volatile const int * const interruptP,
+ bool * const eofP,
+ bool * const gotPacketP,
+ packetPtr * const packetPP) {
+
+ bool gotPacket;
+ bool eof;
+
+ gotPacket = false;
+ eof = false;
+
+ while (!gotPacket && !eof && !*interruptP) {
+ struct pollfd pollfds[1];
+
+ pollfds[0].fd = this->sockFd;
+ pollfds[0].events = POLLIN;
+
+ poll(pollfds, ARRAY_SIZE(pollfds), -1);
+
+ this->read(&eof, &gotPacket, packetPP);
+ }
+
+ *gotPacketP = gotPacket;
+ *eofP = eof;
+}
+
+
+
+void
+packetSocket::readWait(volatile const int * const interruptP,
+ bool * const eofP,
+ packetPtr * const packetPP) {
+
+ bool gotPacket;
+
+ this->readWait(interruptP, eofP, &gotPacket, packetPP);
+
+ if (!gotPacket)
+ throwf("Packet read was interrupted");
+}
+
+
+
+void
+packetSocket::readWait(bool * const eofP,
+ packetPtr * const packetPP) {
+
+ int const interrupt(0); // Never interrupt
+
+ this->readWait(&interrupt, eofP, packetPP);
+}
+
+} // namespace
Modified: freeswitch/trunk/libs/xmlrpc-c/src/cpp/param_list.cpp
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/src/cpp/param_list.cpp (original)
+++ freeswitch/trunk/libs/xmlrpc-c/src/cpp/param_list.cpp Fri May 23 16:56:24 2008
@@ -21,10 +21,28 @@
-void
+paramList&
paramList::add(xmlrpc_c::value const param) {
+ // Note: Before Xmlrpc-c 1.10, the return value was void. Old programs
+ // using this new add() won't notice the difference. New programs
+ // using this new add() against an old library will, since the old
+ // add() will not return anything. A new program that wants to get
+ // a link error instead of a crash in this case can use addx() instead.
+
this->paramVector.push_back(param);
+
+ return *this;
+}
+
+
+
+paramList&
+paramList::addx(xmlrpc_c::value const param) {
+
+ // See add() for an explanation of why this exists.
+
+ return this->add(param);
}
@@ -50,8 +68,8 @@
int
paramList::getInt(unsigned int const paramNumber,
- int const minimum,
- int const maximum) const {
+ int const minimum,
+ int const maximum) const {
if (paramNumber >= this->paramVector.size())
throw(fault("Not enough parameters", fault::CODE_TYPE));
@@ -91,8 +109,8 @@
double
paramList::getDouble(unsigned int const paramNumber,
- double const minimum,
- double const maximum) const {
+ double const minimum,
+ double const maximum) const {
if (paramNumber >= this->paramVector.size())
throw(fault("Not enough parameters", fault::CODE_TYPE));
@@ -247,6 +265,32 @@
+long long
+paramList::getI8(unsigned int const paramNumber,
+ long long const minimum,
+ long long const maximum) const {
+
+ if (paramNumber >= this->paramVector.size())
+ throw(fault("Not enough parameters", fault::CODE_TYPE));
+
+ if (this->paramVector[paramNumber].type() != value::TYPE_I8)
+ throw(fault("Parameter that is supposed to be 64-bit integer is not",
+ fault::CODE_TYPE));
+
+ long long const longlongvalue(static_cast<long long>(
+ value_i8(this->paramVector[paramNumber])));
+
+ if (longlongvalue < minimum)
+ throw(fault("64-bit integer parameter too low", fault::CODE_TYPE));
+
+ if (longlongvalue > maximum)
+ throw(fault("64-bit integer parameter too high", fault::CODE_TYPE));
+
+ return longlongvalue;
+}
+
+
+
void
paramList::verifyEnd(unsigned int const paramNumber) const {
Added: freeswitch/trunk/libs/xmlrpc-c/src/cpp/pstream.cpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/cpp/pstream.cpp Fri May 23 16:56:24 2008
@@ -0,0 +1,127 @@
+/*=============================================================================
+ pstream
+===============================================================================
+
+ Client XML transport for Xmlrpc-c based on a very simple byte
+ stream.
+
+ The protocol we use is the "packet socket" protocol, which
+ is an Xmlrpc-c invention. It is an almost trivial representation of
+ a sequence of packets on a byte stream.
+
+ A transport object talks to exactly one server over its lifetime.
+
+ You can create a pstream transport from any file descriptor from which
+ you can read and write a bidirectional character stream. Typically,
+ it's a TCP socket.
+
+ This transport is synchronous only. It does not provide a working
+ 'start' method. You have at most one outstanding RPC and wait for
+ it to complete.
+
+ By Bryan Henderson 07.05.12.
+
+ Contributed to the public domain by its author.
+=============================================================================*/
+
+#include <memory>
+
+#include "xmlrpc-c/girerr.hpp"
+using girerr::throwf;
+#include "xmlrpc-c/packetsocket.hpp"
+
+#include "xmlrpc-c/client_transport.hpp"
+
+using namespace std;
+
+namespace xmlrpc_c {
+
+
+clientXmlTransport_pstream::constrOpt::constrOpt() {
+
+ present.fd = false;
+}
+
+
+
+#define DEFINE_OPTION_SETTER(OPTION_NAME, TYPE) \
+clientXmlTransport_pstream::constrOpt & \
+clientXmlTransport_pstream::constrOpt::OPTION_NAME(TYPE const& arg) { \
+ this->value.OPTION_NAME = arg; \
+ this->present.OPTION_NAME = true; \
+ return *this; \
+}
+
+DEFINE_OPTION_SETTER(fd, xmlrpc_socket);
+
+#undef DEFINE_OPTION_SETTER
+
+
+
+clientXmlTransport_pstream::clientXmlTransport_pstream(constrOpt const& opt) {
+
+ if (!opt.present.fd)
+ throwf("You must provide a 'fd' constructor option.");
+
+ auto_ptr<packetSocket> packetSocketAP;
+
+ try {
+ auto_ptr<packetSocket> p(new packetSocket(opt.value.fd));
+ packetSocketAP = p;
+ } catch (exception const& e) {
+ throwf("Unable to create packet socket out of file descriptor %d. %s",
+ opt.value.fd, e.what());
+ }
+ this->packetSocketP = packetSocketAP.get();
+ packetSocketAP.release();
+}
+
+
+
+clientXmlTransport_pstream::~clientXmlTransport_pstream() {
+
+ delete(this->packetSocketP);
+}
+
+
+void
+clientXmlTransport_pstream::call(
+ carriageParm * const carriageParmP,
+ string const& callXml,
+ string * const responseXmlP) {
+
+ carriageParm_pstream * const carriageParmPstreamP(
+ dynamic_cast<carriageParm_pstream *>(carriageParmP));
+
+ if (carriageParmPstreamP == NULL)
+ throwf("Pstream client XML transport called with carriage "
+ "parameter object not of class carriageParm_pstream");
+
+ packetPtr const callPacketP(new packet(callXml.c_str(), callXml.length()));
+
+ try {
+ this->packetSocketP->writeWait(callPacketP);
+ } catch (exception const& e) {
+ throwf("Failed to write the call to the packet socket. %s", e.what());
+ }
+ packetPtr responsePacketP;
+
+ try {
+ bool eof;
+ this->packetSocketP->readWait(&eof, &responsePacketP);
+
+ if (eof)
+ throwf("The other end closed the socket before sending "
+ "the response.");
+ } catch (exception const& e) {
+ throwf("We sent the call, but couldn't get the response. %s",
+ e.what());
+ }
+ *responseXmlP =
+ string(reinterpret_cast<char *>(responsePacketP->getBytes()),
+ responsePacketP->getLength());
+}
+
+
+
+} // namespace
Modified: freeswitch/trunk/libs/xmlrpc-c/src/cpp/registry.cpp
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/src/cpp/registry.cpp (original)
+++ freeswitch/trunk/libs/xmlrpc-c/src/cpp/registry.cpp Fri May 23 16:56:24 2008
@@ -1,19 +1,35 @@
+#include <cassert>
#include <string>
#include <memory>
#include <algorithm>
#include "xmlrpc-c/girerr.hpp"
-using girerr::error;
+using girerr::throwf;
#include "xmlrpc-c/girmem.hpp"
using girmem::autoObject;
using girmem::autoObjectPtr;
#include "xmlrpc-c/base.h"
#include "xmlrpc-c/base.hpp"
+#include "env_wrap.hpp"
+
#include "xmlrpc-c/registry.hpp"
using namespace std;
using namespace xmlrpc_c;
+
+namespace {
+
+void
+throwIfError(env_wrap const& env) {
+
+ if (env.env_c.fault_occurred)
+ throw(girerr::error(env.env_c.fault_string));
+}
+
+
+} // namespace
+
namespace xmlrpc_c {
@@ -24,20 +40,12 @@
-method *
-method::self() {
-
- return this;
-}
-
-
-
method::~method() {}
methodPtr::methodPtr(method * const methodP) {
- this->instantiate(methodP);
+ this->point(methodP);
}
@@ -59,7 +67,7 @@
defaultMethodPtr::defaultMethodPtr(defaultMethod * const methodP) {
- this->instantiate(methodP);
+ this->point(methodP);
}
@@ -74,23 +82,21 @@
defaultMethod *
-defaultMethod::self() {
+defaultMethodPtr::get() const {
- return this;
+ autoObject * const p(this->objectP);
+ return dynamic_cast<defaultMethod *>(p);
}
registry::registry() {
- xmlrpc_env env;
-
- xmlrpc_env_init(&env);
+ env_wrap env;
- this->c_registryP = xmlrpc_registry_new(&env);
+ this->c_registryP = xmlrpc_registry_new(&env.env_c);
- if (env.fault_occurred)
- throw(error(env.fault_string));
+ throwIfError(env);
}
@@ -102,6 +108,34 @@
+registryPtr::registryPtr() {}
+
+
+
+registryPtr::registryPtr(registry * const registryP) {
+ this->point(registryP);
+}
+
+
+
+registry *
+registryPtr::operator->() const {
+
+ autoObject * const p(this->objectP);
+ return dynamic_cast<registry *>(p);
+}
+
+
+
+registry *
+registryPtr::get() const {
+
+ autoObject * const p(this->objectP);
+ return dynamic_cast<registry *>(p);
+}
+
+
+
static xmlrpc_c::paramList
pListFromXmlrpcArray(xmlrpc_value * const arrayP) {
/*----------------------------------------------------------------------------
@@ -111,19 +145,21 @@
This is glue code to allow us to hook up C++ Xmlrpc-c code to
C Xmlrpc-c code.
-----------------------------------------------------------------------------*/
- xmlrpc_env env;
-
- xmlrpc_env_init(&env);
+ env_wrap env;
XMLRPC_ASSERT_ARRAY_OK(arrayP);
- unsigned int const arraySize = xmlrpc_array_size(&env, arrayP);
+ unsigned int const arraySize = xmlrpc_array_size(&env.env_c, arrayP);
+
+ assert(!env.env_c.fault_occurred);
xmlrpc_c::paramList paramList(arraySize);
for (unsigned int i = 0; i < arraySize; ++i) {
xmlrpc_value * arrayItemP;
- xmlrpc_array_read_item(&env, arrayP, i, &arrayItemP);
+
+ xmlrpc_array_read_item(&env.env_c, arrayP, i, &arrayItemP);
+ assert(!env.env_c.fault_occurred);
paramList.add(xmlrpc_c::value(arrayItemP));
@@ -164,23 +200,30 @@
try {
methodP->execute(paramList, &result);
- } catch (xmlrpc_c::fault caughtFault) {
- xmlrpc_env_set_fault(envP, caughtFault.getCode(),
- caughtFault.getDescription().c_str());
- } catch (girerr::error caughtError) {
- xmlrpc_env_set_fault(envP, 0, caughtError.what());
+ } catch (xmlrpc_c::fault const& fault) {
+ xmlrpc_env_set_fault(envP, fault.getCode(),
+ fault.getDescription().c_str());
}
- if (envP->fault_occurred)
- retval = NULL;
- else
- retval = result.cValue();
+ if (!envP->fault_occurred) {
+ if (result.isInstantiated())
+ retval = result.cValue();
+ else
+ throwf("Xmlrpc-c user's xmlrpc_c::method object's "
+ "'execute method' failed to set the RPC result "
+ "value.");
+ }
+ } catch (exception const& e) {
+ xmlrpc_faultf(envP, "Unexpected error executing code for "
+ "particular method, detected by Xmlrpc-c "
+ "method registry code. Method did not "
+ "fail; rather, it did not complete at all. %s",
+ e.what());
} catch (...) {
xmlrpc_env_set_fault(envP, XMLRPC_INTERNAL_ERROR,
- "Unexpected error executing the code for this "
- "particular method, detected by the Xmlrpc-c "
- "method registry code. The method did not "
+ "Unexpected error executing code for "
+ "particular method, detected by Xmlrpc-c "
+ "method registry code. Method did not "
"fail; rather, it did not complete at all.");
- retval = NULL;
}
return retval;
}
@@ -208,34 +251,41 @@
XML-RPC method failure. This will cause a leak if the execute()
method actually created a result, since it will not get destroyed.
-----------------------------------------------------------------------------*/
- xmlrpc_c::defaultMethod * const methodP =
- static_cast<xmlrpc_c::defaultMethod *>(methodPtr);
- xmlrpc_c::paramList const paramList(pListFromXmlrpcArray(paramArrayP));
+ defaultMethod * const methodP =
+ static_cast<defaultMethod *>(methodPtr);
+ paramList const paramList(pListFromXmlrpcArray(paramArrayP));
xmlrpc_value * retval;
try {
xmlrpc_c::value result;
-
+
try {
methodP->execute(methodName, paramList, &result);
- } catch (xmlrpc_c::fault caughtFault) {
- xmlrpc_env_set_fault(envP, caughtFault.getCode(),
- caughtFault.getDescription().c_str());
- } catch (girerr::error caughtError) {
- xmlrpc_env_set_fault(envP, 0, caughtError.what());
+ } catch (xmlrpc_c::fault const& fault) {
+ xmlrpc_env_set_fault(envP, fault.getCode(),
+ fault.getDescription().c_str());
+ }
+ if (!envP->fault_occurred) {
+ if (result.isInstantiated())
+ retval = result.cValue();
+ else
+ throwf("Xmlrpc-c user's xmlrpc_c::defaultMethod object's "
+ "'execute method' failed to set the RPC result "
+ "value.");
}
- if (envP->fault_occurred)
- retval = NULL;
- else
- retval = result.cValue();
+ } catch (exception const& e) {
+ xmlrpc_faultf(envP, "Unexpected error executing default "
+ "method code, detected by Xmlrpc-c "
+ "method registry code. Method did not "
+ "fail; rather, it did not complete at all. %s",
+ e.what());
} catch (...) {
xmlrpc_env_set_fault(envP, XMLRPC_INTERNAL_ERROR,
- "Unexpected error executing the default "
- "method code, detected by the Xmlrpc-c "
- "method registry code. The method did not "
+ "Unexpected error executing default "
+ "method code, detected by Xmlrpc-c "
+ "method registry code. Method did not "
"fail; rather, it did not complete at all.");
- retval = NULL;
}
return retval;
}
@@ -243,46 +293,36 @@
void
-registry::addMethod(string const name,
- xmlrpc_c::methodPtr const methodPtr) {
+registry::addMethod(string const name,
+ methodPtr const methodP) {
+ this->methodList.push_back(methodP);
- this->methodList.push_back(methodPtr);
-
- xmlrpc_env env;
+ env_wrap env;
- xmlrpc_env_init(&env);
-
- xmlrpc_c::method * const methodP(methodPtr->self());
-
xmlrpc_registry_add_method_w_doc(
- &env, this->c_registryP, NULL,
+ &env.env_c, this->c_registryP, NULL,
name.c_str(), &c_executeMethod,
- (void*) methodP,
+ (void*) methodP.get(),
methodP->signature().c_str(), methodP->help().c_str());
- if (env.fault_occurred)
- throw(error(env.fault_string));
+ throwIfError(env);
}
void
-registry::setDefaultMethod(defaultMethodPtr const methodPtr) {
-
- xmlrpc_env env;
-
- xmlrpc_env_init(&env);
+registry::setDefaultMethod(defaultMethodPtr const methodP) {
- this->defaultMethodP = methodPtr;
-
- xmlrpc_c::defaultMethod * const methodP(methodPtr->self());
+ this->defaultMethodP = methodP;
+ env_wrap env;
+
xmlrpc_registry_set_default_method(
- &env, this->c_registryP, &c_executeDefaultMethod, (void*) methodP);
+ &env.env_c, this->c_registryP,
+ &c_executeDefaultMethod, (void*) methodP.get());
- if (env.fault_occurred)
- throw(error(env.fault_string));
+ throwIfError(env);
}
@@ -295,6 +335,52 @@
+static xmlrpc_server_shutdown_fn shutdownServer;
+
+static void
+shutdownServer(xmlrpc_env * const envP,
+ void * const context,
+ const char * const comment,
+ void * const callInfo) {
+
+ registry::shutdown * const shutdownP(
+ static_cast<registry::shutdown *>(context));
+
+ assert(shutdownP != NULL);
+
+ try {
+ shutdownP->doit(string(comment), callInfo);
+ } catch (exception const& e) {
+ xmlrpc_env_set_fault(envP, XMLRPC_INTERNAL_ERROR, e.what());
+ }
+}
+
+
+
+void
+registry::setShutdown(const registry::shutdown * const shutdownP) {
+
+ void * const context(const_cast<registry::shutdown *>(shutdownP));
+
+ xmlrpc_registry_set_shutdown(this->c_registryP,
+ &shutdownServer,
+ context);
+}
+
+
+
+void
+registry::setDialect(xmlrpc_dialect const dialect) {
+
+ env_wrap env;
+
+ xmlrpc_registry_set_dialect(&env.env_c, this->c_registryP, dialect);
+
+ throwIfError(env);
+}
+
+
+
void
registry::processCall(string const& callXml,
string * const responseXmlP) const {
@@ -307,11 +393,9 @@
the call executes and the method merely fails in an XML-RPC sense, we
don't. In that case, *responseXmlP indicates the failure.
-----------------------------------------------------------------------------*/
- xmlrpc_env env;
+ env_wrap env;
xmlrpc_mem_block * output;
- xmlrpc_env_init(&env);
-
// For the pure C++ version, this will have to parse 'callXml'
// into a method name and parameters, look up the method name in
// the registry, call the method's execute() method, then marshall
@@ -321,10 +405,10 @@
// xmlrpc_registry_process_call() does.
output = xmlrpc_registry_process_call(
- &env, this->c_registryP, NULL, callXml.c_str(), callXml.length());
+ &env.env_c, this->c_registryP, NULL,
+ callXml.c_str(), callXml.length());
- if (env.fault_occurred)
- throw(error(env.fault_string));
+ throwIfError(env);
*responseXmlP = string(XMLRPC_MEMBLOCK_CONTENTS(char, output),
XMLRPC_MEMBLOCK_SIZE(char, output));
@@ -339,3 +423,6 @@
}
} // namespace
+
+
+registry::shutdown::~shutdown() {}
Modified: freeswitch/trunk/libs/xmlrpc-c/src/cpp/server_abyss.cpp
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/src/cpp/server_abyss.cpp (original)
+++ freeswitch/trunk/libs/xmlrpc-c/src/cpp/server_abyss.cpp Fri May 23 16:56:24 2008
@@ -1,11 +1,18 @@
-#include <cassert>
+#include <cstdlib>
#include <string>
#include <memory>
#include <signal.h>
+#include <errno.h>
+#include <iostream>
+#ifndef _WIN32
#include <sys/wait.h>
+#endif
+#include "assertx.hpp"
+#include "xmlrpc-c/string_int.h"
#include "xmlrpc-c/girerr.hpp"
using girerr::error;
+using girerr::throwf;
#include "xmlrpc-c/base.h"
#include "xmlrpc-c/base.hpp"
#include "xmlrpc-c/server_abyss.h"
@@ -17,47 +24,21 @@
namespace xmlrpc_c {
-serverAbyss::serverAbyss(
- xmlrpc_c::registry const& registry,
- unsigned int const portNumber,
- string const& logFileName,
- unsigned int const keepaliveTimeout,
- unsigned int const keepaliveMaxConn,
- unsigned int const timeout,
- bool const dontAdvertise) {
-
- this->registryP = ®istry;
- this->logFileName = logFileName;
- this->keepaliveTimeout = keepaliveTimeout;
- this->keepaliveMaxConn = keepaliveMaxConn;
- this->timeout = timeout;
- this->dontAdvertise = dontAdvertise;
-
- if (portNumber > 0xffff)
- throw(error("Port number exceeds the maximum possible port number "
- "(65535)"));
- else {
- this->portNumber = portNumber;
- }
-}
-
-
-serverAbyss::~serverAbyss() {
-}
-
-
-
namespace {
static void
-sigterm(int const sig) {
- TraceExit("Signal %d received. Exiting...\n",sig);
+sigterm(int const signalClass) {
+
+ cerr << "Signal of Class " << signalClass << " received. Exiting" << endl;
+
+ exit(1);
}
+
static void
-sigchld(int const sig) {
+sigchld(int const ASSERT_ONLY_ARG(signalClass)) {
/*----------------------------------------------------------------------------
This is a signal handler for a SIGCHLD signal (which informs us that
one of our child processes has terminated).
@@ -65,7 +46,8 @@
We respond by reaping the zombie process.
Implementation note: In some systems, just setting the signal handler
- to SIG_IGN (ignore signal) does this. In others, it doesn't.
+ to SIG_IGN (ignore signal) does this. In some, the system does this
+ automatically if the signal is blocked.
-----------------------------------------------------------------------------*/
#ifndef _WIN32
/* Reap zombie children until there aren't any more. */
@@ -73,7 +55,7 @@
bool zombiesExist;
bool error;
- assert(sig == SIGCHLD);
+ assert(signalClass == SIGCHLD);
zombiesExist = true; // initial assumption
error = false; // no error yet
@@ -94,8 +76,25 @@
#endif /* _WIN32 */
}
+
+
+struct signalHandlers {
+#ifndef WIN32
+ struct sigaction term;
+ struct sigaction int_;
+ struct sigaction hup;
+ struct sigaction usr1;
+ struct sigaction pipe;
+ struct sigaction chld;
+#else
+ int dummy;
+#endif
+};
+
+
+
void
-setupSignalHandlers(void) {
+setupSignalHandlers(struct signalHandlers * const oldHandlersP) {
#ifndef _WIN32
struct sigaction mysigaction;
@@ -104,93 +103,366 @@
/* These signals abort the program, with tracing */
mysigaction.sa_handler = sigterm;
- sigaction(SIGTERM, &mysigaction, NULL);
- sigaction(SIGINT, &mysigaction, NULL);
- sigaction(SIGHUP, &mysigaction, NULL);
- sigaction(SIGUSR1, &mysigaction, NULL);
+ sigaction(SIGTERM, &mysigaction, &oldHandlersP->term);
+ sigaction(SIGINT, &mysigaction, &oldHandlersP->int_);
+ sigaction(SIGHUP, &mysigaction, &oldHandlersP->hup);
+ sigaction(SIGUSR1, &mysigaction, &oldHandlersP->usr1);
/* This signal indicates connection closed in the middle */
mysigaction.sa_handler = SIG_IGN;
- sigaction(SIGPIPE, &mysigaction, NULL);
+ sigaction(SIGPIPE, &mysigaction, &oldHandlersP->pipe);
/* This signal indicates a child process (request handler) has died */
mysigaction.sa_handler = sigchld;
- sigaction(SIGCHLD, &mysigaction, NULL);
+ sigaction(SIGCHLD, &mysigaction, &oldHandlersP->chld);
#endif
}
-static void
-setAdditionalServerParms(
- unsigned int const keepaliveTimeout,
- unsigned int const keepaliveMaxConn,
- unsigned int const timeout,
- bool const dontAdvertise,
- TServer * const srvP) {
+
+void
+restoreSignalHandlers(struct signalHandlers const& oldHandlers) {
+
+#ifndef _WIN32
+ sigaction(SIGCHLD, &oldHandlers.chld, NULL);
+ sigaction(SIGPIPE, &oldHandlers.pipe, NULL);
+ sigaction(SIGUSR1, &oldHandlers.usr1, NULL);
+ sigaction(SIGHUP, &oldHandlers.hup, NULL);
+ sigaction(SIGINT, &oldHandlers.int_, NULL);
+ sigaction(SIGTERM, &oldHandlers.term, NULL);
+#endif
+}
+
+
+
+// We need 'global' because methods of class serverAbyss call
+// functions in the Abyss C library. By virtue of global's static
+// storage class, the program loader will call its constructor and
+// destructor and thus initialize and terminate the Abyss C library.
+
+class abyssGlobalState {
+public:
+ abyssGlobalState() {
+ const char * error;
+ AbyssInit(&error);
+ if (error) {
+ string const e(error);
+ xmlrpc_strfree(error);
+ throwf("AbyssInit() failed. %s", e.c_str());
+ }
+ }
+ ~abyssGlobalState() {
+ AbyssTerm();
+ }
+} const global;
+
+} // namespace
+
+
+
+serverAbyss::shutdown::shutdown(serverAbyss * const serverAbyssP) :
+ serverAbyssP(serverAbyssP) {}
+
+
+
+serverAbyss::shutdown::~shutdown() {}
+
+
+
+void
+serverAbyss::shutdown::doit(string const&,
+ void * const) const {
+
+ this->serverAbyssP->terminate();
+}
+
+
+
+serverAbyss::constrOpt::constrOpt() {
+ present.registryPtr = false;
+ present.registryP = false;
+ present.socketFd = false;
+ present.portNumber = false;
+ present.logFileName = false;
+ present.keepaliveTimeout = false;
+ present.keepaliveMaxConn = false;
+ present.timeout = false;
+ present.dontAdvertise = false;
+ present.uriPath = false;
+ present.chunkResponse = false;
+
+ // Set default values
+ value.dontAdvertise = false;
+ value.uriPath = string("/RPC2");
+ value.chunkResponse = false;
+}
+
+
+
+#define DEFINE_OPTION_SETTER(OPTION_NAME, TYPE) \
+serverAbyss::constrOpt & \
+serverAbyss::constrOpt::OPTION_NAME(TYPE const& arg) { \
+ this->value.OPTION_NAME = arg; \
+ this->present.OPTION_NAME = true; \
+ return *this; \
+}
+
+DEFINE_OPTION_SETTER(registryPtr, xmlrpc_c::registryPtr);
+DEFINE_OPTION_SETTER(registryP, const registry *);
+DEFINE_OPTION_SETTER(socketFd, XMLRPC_SOCKET);
+DEFINE_OPTION_SETTER(portNumber, unsigned int);
+DEFINE_OPTION_SETTER(logFileName, string);
+DEFINE_OPTION_SETTER(keepaliveTimeout, unsigned int);
+DEFINE_OPTION_SETTER(keepaliveMaxConn, unsigned int);
+DEFINE_OPTION_SETTER(timeout, unsigned int);
+DEFINE_OPTION_SETTER(dontAdvertise, bool);
+DEFINE_OPTION_SETTER(uriPath, string);
+DEFINE_OPTION_SETTER(chunkResponse, bool);
+
+
+
+void
+serverAbyss::setAdditionalServerParms(constrOpt const& opt) {
/* The following ought to be parameters on ServerCreate(), but it
looks like plugging them straight into the TServer structure is
the only way to set them.
*/
+ if (opt.present.keepaliveTimeout)
+ ServerSetKeepaliveTimeout(&this->cServer, opt.value.keepaliveTimeout);
+ if (opt.present.keepaliveMaxConn)
+ ServerSetKeepaliveMaxConn(&this->cServer, opt.value.keepaliveMaxConn);
+ if (opt.present.timeout)
+ ServerSetTimeout(&this->cServer, opt.value.timeout);
+ ServerSetAdvertise(&this->cServer, !opt.value.dontAdvertise);
+}
+
+
+
+static void
+createServer(bool const logFileNameGiven,
+ string const& logFileName,
+ bool const socketFdGiven,
+ int const socketFd,
+ bool const portNumberGiven,
+ unsigned int const portNumber,
+ TServer * const srvPP) {
+
+ const char * const logfileArg(logFileNameGiven ?
+ logFileName.c_str() : NULL);
+
+ const char * const serverName("XmlRpcServer");
+
+ abyss_bool created;
+
+ if (socketFdGiven)
+ created =
+ ServerCreateSocket(srvPP, serverName, socketFd,
+ DEFAULT_DOCS, logfileArg);
+ else if (portNumberGiven) {
+ if (portNumber > 0xffff)
+ throwf("Port number %u exceeds the maximum possible port number "
+ "(65535)", portNumber);
+
+ created =
+ ServerCreate(srvPP, serverName, portNumber,
+ DEFAULT_DOCS, logfileArg);
+ } else
+ created =
+ ServerCreateNoAccept(srvPP, serverName,
+ DEFAULT_DOCS, logfileArg);
+
+ if (!created)
+ throw(error("Failed to create Abyss server. See Abyss error log for "
+ "reason."));
+}
+
+
+
+void
+serverAbyss::initialize(constrOpt const& opt) {
+
+ const registry * registryP;
+
+ if (!opt.present.registryP && !opt.present.registryPtr)
+ throwf("You must specify the 'registryP' or 'registryPtr' option");
+ else if (opt.present.registryP && opt.present.registryPtr)
+ throwf("You may not specify both the 'registryP' and "
+ "the 'registryPtr' options");
+ else {
+ if (opt.present.registryP)
+ registryP = opt.value.registryP;
+ else {
+ this->registryPtr = opt.value.registryPtr;
+ registryP = this->registryPtr.get();
+ }
+ }
+ if (opt.present.portNumber && opt.present.socketFd)
+ throwf("You can't specify both portNumber and socketFd options");
+
+ DateInit();
+
+ createServer(opt.present.logFileName, opt.value.logFileName,
+ opt.present.socketFd, opt.value.socketFd,
+ opt.present.portNumber, opt.value.portNumber,
+ &this->cServer);
+
+ try {
+ setAdditionalServerParms(opt);
+
+ // chunked response implementation is incomplete. We must
+ // eventually get away from libxmlrpc_server_abyss and
+ // register our own handler with the Abyss server. At that
+ // time, we'll have some place to pass
+ // opt.value.chunkResponse.
+
+ xmlrpc_c::server_abyss_set_handlers(&this->cServer,
+ registryP,
+ opt.value.uriPath);
+
+ if (opt.present.portNumber || opt.present.socketFd)
+ ServerInit(&this->cServer);
+ } catch (...) {
+ ServerFree(&this->cServer);
+ throw;
+ }
+}
+
+
+
+serverAbyss::serverAbyss(constrOpt const& opt) {
+
+ initialize(opt);
+}
+
+
+
+serverAbyss::serverAbyss(
+ xmlrpc_c::registry const& registry,
+ unsigned int const portNumber,
+ string const& logFileName,
+ unsigned int const keepaliveTimeout,
+ unsigned int const keepaliveMaxConn,
+ unsigned int const timeout,
+ bool const dontAdvertise,
+ bool const socketBound,
+ XMLRPC_SOCKET const socketFd) {
+/*----------------------------------------------------------------------------
+ This is a backward compatibility interface. This used to be the only
+ constructor.
+-----------------------------------------------------------------------------*/
+ serverAbyss::constrOpt opt;
+
+ opt.registryP(®istry);
+ if (logFileName.length() > 0)
+ opt.logFileName(logFileName);
if (keepaliveTimeout > 0)
- srvP->keepalivetimeout = keepaliveTimeout;
+ opt.keepaliveTimeout(keepaliveTimeout);
if (keepaliveMaxConn > 0)
- srvP->keepalivemaxconn = keepaliveMaxConn;
+ opt.keepaliveMaxConn(keepaliveMaxConn);
if (timeout > 0)
- srvP->timeout = timeout;
- srvP->advertise = !dontAdvertise;
+ opt.timeout(timeout);
+ opt.dontAdvertise(dontAdvertise);
+ if (socketBound)
+ opt.socketFd(socketFd);
+ else
+ opt.portNumber(portNumber);
+
+ initialize(opt);
}
-} // namespace
+
+serverAbyss::~serverAbyss() {
+
+ ServerFree(&this->cServer);
+}
void
serverAbyss::run() {
- xmlrpc_env env;
- xmlrpc_env_init(&env);
-
- DateInit();
- MIMETypeInit();
-
- TServer srv;
+ /* We do some pretty ugly stuff for an object method: we set signal
+ handlers, which are process-global.
- const char * const logfileArg(this->logFileName.length() == 0 ?
- NULL : this->logFileName.c_str());
+ One example of where this can be hairy is: Caller has a child
+ process unrelated to the Abyss server. That child dies. We
+ get his death of a child signal and Caller never knows.
+
+ We really expect to be the only thing in the process, at least
+ for the time we're running. If you want the Abyss Server
+ to behave more like an object and own the signals yourself,
+ use runOnce() in a loop instead of run().
+ */
+ signalHandlers oldHandlers;
- ServerCreate(&srv, "XmlRpcServer", this->portNumber,
- DEFAULT_DOCS, logfileArg);
+ setupSignalHandlers(&oldHandlers);
- setAdditionalServerParms(
- this->keepaliveTimeout, this->keepaliveMaxConn, this->timeout,
- this->dontAdvertise, &srv);
-
- xmlrpc_c::server_abyss_set_handlers(&srv, *this->registryP);
-
- ServerInit(&srv);
-
- setupSignalHandlers();
-
- ServerRun(&srv);
+ ServerRun(&this->cServer);
- /* We can't exist here because ServerRun doesn't return */
- assert(false);
+ restoreSignalHandlers(oldHandlers);
}
void
-server_abyss_set_handlers(TServer * const srvP,
- xmlrpc_c::registry const& registry) {
-
+serverAbyss::runOnce() {
- xmlrpc_server_abyss_set_handlers(srvP, registry.c_registry());
+ ServerRunOnce(&this->cServer);
}
-} // namespace
+void
+serverAbyss::runConn(int const socketFd) {
+
+ ServerRunConn(&this->cServer, socketFd);
+}
+
+
+
+void
+serverAbyss::terminate() {
+ ServerTerminate(&this->cServer);
+}
+
+void
+server_abyss_set_handlers(TServer * const srvP,
+ registry const& registry,
+ string const& uriPath) {
+
+ xmlrpc_server_abyss_set_handlers2(srvP,
+ uriPath.c_str(),
+ registry.c_registry());
+}
+
+
+
+void
+server_abyss_set_handlers(TServer * const srvP,
+ const registry * const registryP,
+ string const& uriPath) {
+
+ xmlrpc_server_abyss_set_handlers2(srvP,
+ uriPath.c_str(),
+ registryP->c_registry());
+}
+
+
+
+void
+server_abyss_set_handlers(TServer * const srvP,
+ registryPtr const registryPtr,
+ string const& uriPath) {
+
+ xmlrpc_server_abyss_set_handlers2(srvP,
+ uriPath.c_str(),
+ registryPtr->c_registry());
+}
+
+
+
+} // namespace
Added: freeswitch/trunk/libs/xmlrpc-c/src/cpp/server_pstream.cpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/cpp/server_pstream.cpp Fri May 23 16:56:24 2008
@@ -0,0 +1,187 @@
+/*=============================================================================
+ server_pstream
+===============================================================================
+
+ RPC server based on a very simple byte stream and XML-RPC XML
+ (But this is not an XML-RPC server because it doesn't use HTTP).
+
+ The protocol we use is the "packet socket" protocol, which
+ is an Xmlrpc-c invention. It is an almost trivial representation of
+ a sequence of packets on a byte stream.
+
+ You can create a pstream server from any file descriptor from which
+ you can read and write a bidirectional character stream. Typically,
+ it's a TCP socket. Such a server talks to one client its entire life.
+
+ Some day, we'll also have a version that you create from a "listening"
+ socket, which can talk to multiple clients serially (a client connects,
+ does some RPCs, and disconnects).
+
+ By Bryan Henderson 07.05.12.
+
+ Contributed to the public domain by its author.
+=============================================================================*/
+
+#include <memory>
+
+#include "xmlrpc-c/girerr.hpp"
+using girerr::throwf;
+#include "xmlrpc-c/packetsocket.hpp"
+
+#include "xmlrpc-c/server_pstream.hpp"
+
+using namespace std;
+
+namespace xmlrpc_c {
+
+
+serverPstreamConn::constrOpt::constrOpt() {
+
+ present.socketFd = false;
+ present.registryP = false;
+ present.registryPtr = false;
+}
+
+
+
+#define DEFINE_OPTION_SETTER(OPTION_NAME, TYPE) \
+serverPstreamConn::constrOpt & \
+serverPstreamConn::constrOpt::OPTION_NAME(TYPE const& arg) { \
+ this->value.OPTION_NAME = arg; \
+ this->present.OPTION_NAME = true; \
+ return *this; \
+}
+
+DEFINE_OPTION_SETTER(socketFd, XMLRPC_SOCKET);
+DEFINE_OPTION_SETTER(registryP, const registry *);
+DEFINE_OPTION_SETTER(registryPtr, xmlrpc_c::registryPtr);
+
+#undef DEFINE_OPTION_SETTER
+
+
+
+void
+serverPstreamConn::establishRegistry(constrOpt const& opt) {
+
+ if (!opt.present.registryP && !opt.present.registryPtr)
+ throwf("You must specify the 'registryP' or 'registryPtr' option");
+ else if (opt.present.registryP && opt.present.registryPtr)
+ throwf("You may not specify both the 'registryP' and "
+ "the 'registryPtr' options");
+ else {
+ if (opt.present.registryP)
+ this->registryP = opt.value.registryP;
+ else {
+ this->registryHolder = opt.value.registryPtr;
+ this->registryP = opt.value.registryPtr.get();
+ }
+ }
+}
+
+
+
+void
+serverPstreamConn::establishPacketSocket(constrOpt const& opt) {
+
+ if (!opt.present.socketFd)
+ throwf("You must provide a 'socketFd' constructor option.");
+
+ auto_ptr<packetSocket> packetSocketAP;
+
+ try {
+ auto_ptr<packetSocket> p(new packetSocket(opt.value.socketFd));
+ packetSocketAP = p;
+ } catch (exception const& e) {
+ throwf("Unable to create packet socket out of file descriptor %d. %s",
+ opt.value.socketFd, e.what());
+ }
+ this->packetSocketP = packetSocketAP.get();
+ packetSocketAP.release();
+}
+
+
+
+serverPstreamConn::serverPstreamConn(constrOpt const& opt) {
+
+ this->establishRegistry(opt);
+
+ this->establishPacketSocket(opt);
+}
+
+
+
+serverPstreamConn::~serverPstreamConn() {
+
+ delete(this->packetSocketP);
+}
+
+
+
+void
+processCall(const registry * const registryP,
+ packetPtr const& callPacketP,
+ packetPtr * const responsePacketPP) {
+
+ string const callXml(reinterpret_cast<char *>(callPacketP->getBytes()),
+ callPacketP->getLength());
+
+ string responseXml;
+
+ registryP->processCall(callXml, &responseXml);
+
+ *responsePacketPP = packetPtr(new packet(responseXml.c_str(),
+ responseXml.length()));
+}
+
+
+
+void
+serverPstreamConn::runOnce(volatile const int * const interruptP,
+ bool * const eofP) {
+/*----------------------------------------------------------------------------
+ Get and execute one RPC from the client.
+
+ Unless *interruptP gets set nonzero first.
+-----------------------------------------------------------------------------*/
+ bool gotPacket;
+ packetPtr callPacketP;
+
+ try {
+ this->packetSocketP->readWait(interruptP, eofP, &gotPacket,
+ &callPacketP);
+ } catch (exception const& e) {
+ throwf("Error reading a packet from the packet socket. %s",
+ e.what());
+ }
+ if (gotPacket) {
+ packetPtr responsePacketP;
+ try {
+ processCall(this->registryP, callPacketP, &responsePacketP);
+ } catch (exception const& e) {
+ throwf("Error executing received packet as an XML-RPC RPC. %s",
+ e.what());
+ }
+ try {
+ this->packetSocketP->writeWait(responsePacketP);
+ } catch (exception const& e) {
+ throwf("Failed to write the response to the packet socket. %s",
+ e.what());
+ }
+ }
+}
+
+
+
+void
+serverPstreamConn::runOnce(bool * const eofP) {
+/*----------------------------------------------------------------------------
+ Get and execute one RPC from the client.
+-----------------------------------------------------------------------------*/
+ int const interrupt(0); // Never interrupt
+
+ this->runOnce(&interrupt, eofP);
+}
+
+
+
+} // namespace
Added: freeswitch/trunk/libs/xmlrpc-c/src/cpp/test/Makefile
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/cpp/test/Makefile Fri May 23 16:56:24 2008
@@ -0,0 +1,107 @@
+ifeq ($(SRCDIR),)
+ updir = $(shell echo $(dir $(1)) | sed 's/.$$//')
+ SRCCPPDIR := $(call updir,$(CURDIR))
+ srcDIR := $(call updir,$(SRCCPPDIR))
+ SRCDIR := $(call updir,$(srcDIR))
+ BLDDIR := $(SRCDIR)
+endif
+SUBDIR := src/test/cpp
+
+include $(BLDDIR)/config.mk
+
+PROGS = test
+
+default: all
+
+all: $(PROGS)
+
+XMLRPC_C_CONFIG = $(BLDDIR)/xmlrpc-c-config.test
+
+CXXFLAGS = $(CXXFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD)
+
+LDFLAGS += $(shell $(XMLRPC_C_CONFIG) client --ldadd)
+
+ifeq ($(MUST_BUILD_CURL_CLIENT),yes)
+ LDFLAGS += $(shell curl-config --libs)
+endif
+ifeq ($(MUST_BUILD_LIBWWW_CLIENT),yes)
+ LDFLAGS += $(shell libwww-config --libs)
+endif
+
+LDFLAGS += "-lpthread"
+
+LDFLAGS += $(LADD)
+
+INCLUDES = -Isrcdir/include -I$(BLDDIR) -Isrcdir -Isrcdir/lib/util/include
+
+# This 'Makefile' dependency makes sure the symlinks get built before
+# this make file is used for anything.
+
+Makefile: srcdir
+
+include $(SRCDIR)/common.mk
+
+
+TEST_OBJS = test.o registry.o server_abyss.o server_pstream.o tools.o
+
+ifeq ($(MUST_BUILD_CLIENT),yes)
+ TEST_OBJS += testclient.o
+ CLIENT_LIBS = $(LIBXMLRPC_CLIENTPP_A) $(LIBXMLRPC_CLIENT_A)
+else
+ TEST_OBJS += testclient_dummy.o
+ CLIENT_LIBS =
+endif
+
+
+TEST_LIBS = \
+ $(LIBXMLRPC_SERVER_ABYSSPP_A) \
+ $(LIBXMLRPC_SERVER_PSTREAMPP_A) \
+ $(LIBXMLRPC_SERVERPP_A) \
+ $(CLIENT_LIBS) $(LIBXMLRPCPP_A) \
+ $(LIBXMLRPC_CPP_A) \
+ $(LIBXMLRPC_SERVER_ABYSS_A) \
+ $(LIBXMLRPC_SERVER_A) \
+ $(LIBXMLRPC_A) \
+ $(LIBXMLRPC_ABYSS_A) \
+ $(LIBXMLRPC_PACKETSOCKET_A) \
+ $(LIBXMLRPC_UTIL_A) \
+
+ifneq ($(ENABLE_LIBXML2_BACKEND),yes)
+ # We're using the internal Expat XML parser
+ TEST_LIBS += $(LIBXMLRPC_XMLPARSE_A) $(LIBXMLRPC_XMLTOK_A)
+ LDADD_XML =
+else
+ LDADD_XML = $(shell xml2-config --libs)
+endif
+
+test: $(TEST_OBJS) $(TEST_LIBS)
+ $(CXXLD) -o $@ $(LDFLAGS) $(LDADD_XML) $^
+
+%.o:%.cpp
+ $(CXX) -c $(INCLUDES) $(CXXFLAGS) $<
+
+# Note the difference between 'check' and 'runtests'. 'check' means to check
+# our own correctness. 'runtests' means to run the tests that check our
+# parent's correctness
+
+.PHONY: check
+check:
+
+.PHONY: runtests
+runtests: test
+ ./test
+
+.PHONY: install
+install:
+
+.PHONY: clean clean-local distclean
+clean: clean-common clean-local
+clean-local:
+ rm -f $(PROGS)
+
+distclean: clean distclean-common
+
+.PHONY: dep
+dep: dep-common
+
+include Makefile.depend
Added: freeswitch/trunk/libs/xmlrpc-c/src/cpp/test/registry.cpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/cpp/test/registry.cpp Fri May 23 16:56:24 2008
@@ -0,0 +1,358 @@
+/*=============================================================================
+ registry
+===============================================================================
+ Test the method registry (server) C++ facilities of XML-RPC for C/C++.
+
+=============================================================================*/
+
+#include <string>
+
+#include "xmlrpc-c/girerr.hpp"
+using girerr::error;
+using girerr::throwf;
+#include "xmlrpc-c/base.hpp"
+#include "xmlrpc-c/registry.hpp"
+
+#include "tools.hpp"
+#include "registry.hpp"
+
+using namespace xmlrpc_c;
+using namespace std;
+
+
+string const xmlPrologue("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n");
+
+
+
+namespace {
+string const noElementFoundXml(
+ xmlPrologue +
+ "<methodResponse>\r\n"
+ "<fault>\r\n"
+ "<value><struct>\r\n"
+ "<member><name>faultCode</name>\r\n"
+ "<value><i4>-503</i4></value></member>\r\n"
+ "<member><name>faultString</name>\r\n"
+ "<value><string>Call XML not a proper XML-RPC call. "
+ "Call is not valid XML. no element found</string></value>"
+ "</member>\r\n"
+ "</struct></value>\r\n"
+ "</fault>\r\n"
+ "</methodResponse>\r\n"
+ );
+
+string const sampleAddGoodCallXml(
+ xmlPrologue +
+ "<methodCall>\r\n"
+ "<methodName>sample.add</methodName>\r\n"
+ "<params>\r\n"
+ "<param><value><i4>5</i4></value></param>\r\n"
+ "<param><value><i4>7</i4></value></param>\r\n"
+ "</params>\r\n"
+ "</methodCall>\r\n"
+ );
+
+string const sampleAddGoodResponseXml(
+ xmlPrologue +
+ "<methodResponse>\r\n"
+ "<params>\r\n"
+ "<param><value><i4>12</i4></value></param>\r\n"
+ "</params>\r\n"
+ "</methodResponse>\r\n"
+ );
+
+
+string const sampleAddBadCallXml(
+ xmlPrologue +
+ "<methodCall>\r\n"
+ "<methodName>sample.add</methodName>\r\n"
+ "<params>\r\n"
+ "<param><value><i4>5</i4></value></param>\r\n"
+ "</params>\r\n"
+ "</methodCall>\r\n"
+ );
+
+string const sampleAddBadResponseXml(
+ xmlPrologue +
+ "<methodResponse>\r\n"
+ "<fault>\r\n"
+ "<value><struct>\r\n"
+ "<member><name>faultCode</name>\r\n"
+ "<value><i4>-501</i4></value></member>\r\n"
+ "<member><name>faultString</name>\r\n"
+ "<value><string>Not enough parameters</string></value></member>\r\n"
+ "</struct></value>\r\n"
+ "</fault>\r\n"
+ "</methodResponse>\r\n"
+ );
+
+
+string const nonexistentMethodCallXml(
+ xmlPrologue +
+ "<methodCall>\r\n"
+ "<methodName>nosuchmethod</methodName>\r\n"
+ "<params>\r\n"
+ "<param><value><i4>5</i4></value></param>\r\n"
+ "<param><value><i4>7</i4></value></param>\r\n"
+ "</params>\r\n"
+ "</methodCall>\r\n"
+ );
+
+string const nonexistentMethodYesDefResponseXml(
+ xmlPrologue +
+ "<methodResponse>\r\n"
+ "<params>\r\n"
+ "<param><value><string>no such method: nosuchmethod</string>"
+ "</value></param>\r\n"
+ "</params>\r\n"
+ "</methodResponse>\r\n"
+ );
+
+string const nonexistentMethodNoDefResponseXml(
+ xmlPrologue +
+ "<methodResponse>\r\n"
+ "<fault>\r\n"
+ "<value><struct>\r\n"
+ "<member><name>faultCode</name>\r\n"
+ "<value><i4>-506</i4></value></member>\r\n"
+ "<member><name>faultString</name>\r\n"
+ "<value><string>Method 'nosuchmethod' not defined</string></value>"
+ "</member>\r\n"
+ "</struct></value>\r\n"
+ "</fault>\r\n"
+ "</methodResponse>\r\n"
+ );
+
+} // namespace
+
+
+string const echoI8ApacheCall(
+ xmlPrologue +
+ "<methodCall>\r\n"
+ "<methodName>echo</methodName>\r\n"
+ "<params>\r\n"
+ "<param><value><ex.i8>5</ex.i8></value></param>\r\n"
+ "</params>\r\n"
+ "</methodCall>\r\n"
+ );
+
+string const echoI8ApacheResponse(
+ xmlPrologue +
+ "<methodResponse>\r\n"
+ "<params>\r\n"
+ "<param><value><ex.i8>5</ex.i8></value></param>\r\n"
+ "</params>\r\n"
+ "</methodResponse>\r\n"
+ );
+
+string const echoNilApacheCall(
+ xmlPrologue +
+ "<methodCall>\r\n"
+ "<methodName>echo</methodName>\r\n"
+ "<params>\r\n"
+ "<param><value><nil/></value></param>\r\n"
+ "</params>\r\n"
+ "</methodCall>\r\n"
+ );
+
+string const echoNilApacheResponse(
+ xmlPrologue +
+ "<methodResponse>\r\n"
+ "<params>\r\n"
+ "<param><value><ex.nil/></value></param>\r\n"
+ "</params>\r\n"
+ "</methodResponse>\r\n"
+ );
+
+
+class sampleAddMethod : public method {
+public:
+ sampleAddMethod() {
+ this->_signature = "i:ii";
+ this->_help = "This method adds two integers together";
+ }
+ void
+ execute(xmlrpc_c::paramList const& paramList,
+ value * const retvalP) {
+
+ int const addend(paramList.getInt(0));
+ int const adder(paramList.getInt(1));
+
+ paramList.verifyEnd(2);
+
+ *retvalP = value_int(addend + adder);
+ }
+};
+
+
+
+class nameMethod : public defaultMethod {
+
+ void
+ execute(string const& methodName,
+ xmlrpc_c::paramList const& , // paramList
+ value * const retvalP) {
+
+ *retvalP = value_string(string("no such method: ") + methodName);
+ }
+};
+
+
+
+class echoMethod : public method {
+public:
+ void
+ execute(xmlrpc_c::paramList const& paramList,
+ value * const retvalP) {
+
+ paramList.verifyEnd(1);
+
+ *retvalP = paramList[0];
+ }
+};
+
+
+
+class registryRegMethodTestSuite : public testSuite {
+
+public:
+ virtual string suiteName() {
+ return "registryRegMethodTestSuite";
+ }
+ virtual void runtests(unsigned int const) {
+
+ xmlrpc_c::registry myRegistry;
+
+ myRegistry.addMethod("sample.add",
+ xmlrpc_c::methodPtr(new sampleAddMethod));
+
+ myRegistry.disableIntrospection();
+ {
+ string response;
+ myRegistry.processCall("", &response);
+ TEST(response == noElementFoundXml);
+ }
+ {
+ string response;
+ myRegistry.processCall(sampleAddGoodCallXml, &response);
+ TEST(response == sampleAddGoodResponseXml);
+ }
+ {
+ string response;
+ myRegistry.processCall(sampleAddBadCallXml, &response);
+ TEST(response == sampleAddBadResponseXml);
+ }
+ }
+};
+
+
+
+class registryDefaultMethodTestSuite : public testSuite {
+
+public:
+ virtual string suiteName() {
+ return "registryDefaultMethodTestSuite";
+ }
+ virtual void runtests(unsigned int const) {
+
+ xmlrpc_c::registry myRegistry;
+
+ myRegistry.addMethod("sample.add", methodPtr(new sampleAddMethod));
+
+ {
+ string response;
+ myRegistry.processCall(sampleAddGoodCallXml, &response);
+ TEST(response == sampleAddGoodResponseXml);
+ }
+ {
+ string response;
+ myRegistry.processCall(nonexistentMethodCallXml, &response);
+ TEST(response == nonexistentMethodNoDefResponseXml);
+ }
+ // We're actually violating the spirit of setDefaultMethod by
+ // doing this to a registry that's already been used, but as long
+ // as it works, it's a convenient way to implement this test.
+ myRegistry.setDefaultMethod(defaultMethodPtr(new nameMethod));
+
+ {
+ string response;
+ myRegistry.processCall(nonexistentMethodCallXml, &response);
+ TEST(response == nonexistentMethodYesDefResponseXml);
+ }
+ }
+};
+
+
+
+class registryShutdownTestSuite : public testSuite {
+
+public:
+ virtual string suiteName() {
+ return "registryShutdownTestSuite";
+ }
+ virtual void runtests(unsigned int const) {
+
+ xmlrpc_c::registry myRegistry;
+
+ class myshutdown : public xmlrpc_c::registry::shutdown {
+ public:
+ void doit(string const&,
+ void * const) const {
+
+ }
+ };
+
+ myshutdown shutdown;
+
+ myRegistry.setShutdown(&shutdown);
+ }
+};
+
+
+
+string
+registryTestSuite::suiteName() {
+ return "registryTestSuite";
+}
+
+
+
+void
+registryTestSuite::runtests(unsigned int const indentation) {
+
+ {
+ registryPtr myRegistryP(new registry);
+
+ myRegistryP->addMethod("sample.add", methodPtr(new sampleAddMethod));
+ }
+
+ registryRegMethodTestSuite().run(indentation+1);
+ registryDefaultMethodTestSuite().run(indentation+1);
+
+ registry myRegistry;
+
+ myRegistry.addMethod("sample.add", methodPtr(new sampleAddMethod));
+ myRegistry.addMethod("echo", methodPtr(new echoMethod));
+
+ string response;
+
+ myRegistry.disableIntrospection();
+
+ myRegistry.setDialect(xmlrpc_dialect_i8);
+
+ myRegistry.setDialect(xmlrpc_dialect_apache);
+
+ registryShutdownTestSuite().run(indentation+1);
+
+ myRegistry.processCall(echoI8ApacheCall, &response);
+
+ TEST(response == echoI8ApacheResponse);
+
+ myRegistry.processCall(echoNilApacheCall, &response);
+
+ TEST(response == echoNilApacheResponse);
+
+ EXPECT_ERROR( // invalid dialect
+ myRegistry.setDialect(static_cast<xmlrpc_dialect>(300));
+ );
+}
Added: freeswitch/trunk/libs/xmlrpc-c/src/cpp/test/registry.hpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/cpp/test/registry.hpp Fri May 23 16:56:24 2008
@@ -0,0 +1,9 @@
+#include "tools.hpp"
+
+class registryTestSuite : public testSuite {
+
+public:
+ virtual std::string suiteName();
+ virtual void runtests(unsigned int const indentation);
+};
+
Added: freeswitch/trunk/libs/xmlrpc-c/src/cpp/test/server_abyss.cpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/cpp/test/server_abyss.cpp Fri May 23 16:56:24 2008
@@ -0,0 +1,292 @@
+/*=============================================================================
+ server_abyss
+===============================================================================
+ Test the Abyss server C++ facilities of XML-RPC for C/C++.
+
+=============================================================================*/
+#include <errno.h>
+#include <string>
+#include <iostream>
+#include <vector>
+#include <sstream>
+#include <memory>
+#include <time.h>
+#ifdef WIN32
+ #include <winsock.h>
+#else
+ #include <sys/unistd.h>
+ #include <sys/socket.h>
+ #include <arpa/inet.h>
+#endif
+
+#include "xmlrpc-c/girerr.hpp"
+using girerr::error;
+using girerr::throwf;
+#include "xmlrpc-c/base.hpp"
+#include "xmlrpc-c/registry.hpp"
+#include "xmlrpc-c/server_abyss.hpp"
+#include "xmlrpc-c/abyss.h"
+
+#include "tools.hpp"
+#include "server_abyss.hpp"
+
+using namespace xmlrpc_c;
+using namespace std;
+
+
+static void
+closesock(int const fd) {
+#ifdef WIN32
+ closesocket(fd);
+#else
+ close(fd);
+#endif
+}
+
+
+
+class boundSocket {
+
+public:
+ boundSocket(short const portNumber) {
+ this->fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+
+ if (this->fd < 0)
+ throwf("socket() failed. errno=%d (%s)",
+ errno, strerror(errno));
+
+ struct sockaddr_in sockAddr;
+ int rc;
+
+ sockAddr.sin_family = AF_INET;
+ sockAddr.sin_port = htons(portNumber);
+ sockAddr.sin_addr.s_addr = 0;
+
+ rc = bind(this->fd, (struct sockaddr *)&sockAddr, sizeof(sockAddr));
+
+ if (rc != 0) {
+ closesock(this->fd);
+ throwf("Couldn't bind. bind() failed with errno=%d (%s)",
+ errno, strerror(errno));
+ }
+ }
+
+ ~boundSocket() {
+ closesock(this->fd);
+ }
+
+ int fd;
+};
+
+
+
+class sampleAddMethod : public method {
+public:
+ sampleAddMethod() {
+ this->_signature = "i:ii";
+ this->_help = "This method adds two integers together";
+ }
+ void
+ execute(xmlrpc_c::paramList const& paramList,
+ value * const retvalP) {
+
+ int const addend(paramList.getInt(0));
+ int const adder(paramList.getInt(1));
+
+ paramList.verifyEnd(2);
+
+ *retvalP = value_int(addend + adder);
+ }
+};
+
+
+
+// We need 'global' because methods of class addHandlerTestSuite call
+// functions in the Abyss C library. By virtue of global's static
+// storage class, the program loader will call its constructor and
+// destructor and thus initialize and terminate the Abyss C library.
+
+static class abyssGlobalState {
+public:
+ abyssGlobalState() {
+ const char * error;
+ AbyssInit(&error);
+ if (error) {
+ string const e(error);
+ free(const_cast<char *>(error));
+ throwf("AbyssInit() failed. %s", e.c_str());
+ }
+ }
+ ~abyssGlobalState() {
+ AbyssTerm();
+ }
+} const global;
+
+
+
+class addHandlerTestSuite : public testSuite {
+
+public:
+ virtual string suiteName() {
+ return "addHandlerTestSuite";
+ }
+ virtual void runtests(unsigned int const) {
+ TServer abyssServer;
+
+ ServerCreate(&abyssServer, "testserver", 8080, NULL, NULL);
+
+ registry myRegistry;
+
+ myRegistry.addMethod("sample.add", methodPtr(new sampleAddMethod));
+
+ registryPtr myRegistryP(new registry);
+
+ myRegistryP->addMethod("sample.add", methodPtr(new sampleAddMethod));
+
+ server_abyss_set_handlers(&abyssServer, myRegistry);
+
+ server_abyss_set_handlers(&abyssServer, &myRegistry);
+
+ server_abyss_set_handlers(&abyssServer, myRegistryP);
+
+ server_abyss_set_handlers(&abyssServer, myRegistry, "/RPC3");
+
+ server_abyss_set_handlers(&abyssServer, &myRegistry, "/RPC3");
+
+ server_abyss_set_handlers(&abyssServer, myRegistryP, "/RPC3");
+
+ ServerFree(&abyssServer);
+ }
+};
+
+
+
+class setShutdownTestSuite : public testSuite {
+
+public:
+ virtual string suiteName() {
+ return "setShutdownTestSuite";
+ }
+ virtual void runtests(unsigned int const) {
+
+ registry myRegistry;
+
+ serverAbyss myServer(serverAbyss::constrOpt()
+ .registryP(&myRegistry)
+ .portNumber(12345)
+ );
+
+ serverAbyss::shutdown shutdown(&myServer);
+
+ myRegistry.setShutdown(&shutdown);
+ }
+};
+
+
+
+class createTestSuite : public testSuite {
+
+public:
+ virtual string suiteName() {
+ return "createTestSuite";
+ }
+ virtual void runtests(unsigned int const) {
+
+ registry myRegistry;
+
+ myRegistry.addMethod("sample.add", methodPtr(new sampleAddMethod));
+
+ registryPtr myRegistryP(new registry);
+
+ myRegistryP->addMethod("sample.add", methodPtr(new sampleAddMethod));
+
+ EXPECT_ERROR( // No registry
+ serverAbyss::constrOpt opt;
+ serverAbyss abyssServer(opt);
+ );
+ EXPECT_ERROR( // Both portNumber and socketFd
+ serverAbyss abyssServer(serverAbyss::constrOpt()
+ .portNumber(8080)
+ .socketFd(3));
+ );
+
+ // Due to the vagaries of Abyss, construction of the following
+ // objects may exit the program if it detects an error, such as
+ // port number already in use. We need to fix Abyss some day.
+
+ {
+ serverAbyss abyssServer(serverAbyss::constrOpt()
+ .registryP(&myRegistry)
+ .portNumber(12345)
+ );
+ }
+ {
+ serverAbyss abyssServer(serverAbyss::constrOpt()
+ .registryPtr(myRegistryP)
+ .portNumber(12345)
+ );
+
+ EXPECT_ERROR( // Both registryP and registryPtr
+ serverAbyss abyssServer(serverAbyss::constrOpt()
+ .registryPtr(myRegistryP)
+ .registryP(&myRegistry)
+ .portNumber(12345)
+ );
+ );
+ }
+ {
+ boundSocket socket(12345);
+
+ serverAbyss abyssServer(serverAbyss::constrOpt()
+ .registryP(&myRegistry)
+ .socketFd(socket.fd)
+ );
+ }
+ {
+ serverAbyss abyssServer(serverAbyss::constrOpt()
+ .registryP(&myRegistry)
+ );
+ }
+
+ {
+ // Test all the options
+ serverAbyss abyssServer(serverAbyss::constrOpt()
+ .registryPtr(myRegistryP)
+ .portNumber(12345)
+ .logFileName("/tmp/logfile")
+ .keepaliveTimeout(5)
+ .keepaliveMaxConn(4)
+ .timeout(20)
+ .dontAdvertise(true)
+ .uriPath("/xmlrpc")
+ );
+
+ }
+ {
+ serverAbyss abyssServer(
+ myRegistry,
+ 12345, // TCP port on which to listen
+ "/tmp/xmlrpc_log" // Log file
+ );
+ }
+ }
+};
+
+
+
+string
+serverAbyssTestSuite::suiteName() {
+ return "serverAbyssTestSuite";
+}
+
+
+void
+serverAbyssTestSuite::runtests(unsigned int const indentation) {
+
+ addHandlerTestSuite().run(indentation+1);
+
+ setShutdownTestSuite().run(indentation+1);
+
+ createTestSuite().run(indentation+1);
+
+}
Added: freeswitch/trunk/libs/xmlrpc-c/src/cpp/test/server_abyss.hpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/cpp/test/server_abyss.hpp Fri May 23 16:56:24 2008
@@ -0,0 +1,8 @@
+#include "tools.hpp"
+
+class serverAbyssTestSuite : public testSuite {
+
+public:
+ virtual std::string suiteName();
+ virtual void runtests(unsigned int const);
+};
Added: freeswitch/trunk/libs/xmlrpc-c/src/cpp/test/server_pstream.cpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/cpp/test/server_pstream.cpp Fri May 23 16:56:24 2008
@@ -0,0 +1,177 @@
+/*=============================================================================
+ server_pstream
+===============================================================================
+ Test the pstream server C++ facilities of XML-RPC for C/C++.
+
+=============================================================================*/
+#include <unistd.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <string>
+#include <fcntl.h>
+
+#include "xmlrpc-c/girerr.hpp"
+using girerr::error;
+using girerr::throwf;
+#include "xmlrpc-c/base.hpp"
+#include "xmlrpc-c/registry.hpp"
+#include "xmlrpc-c/server_pstream.hpp"
+
+#include "tools.hpp"
+#include "server_pstream.hpp"
+
+using namespace xmlrpc_c;
+using namespace std;
+
+
+
+class sampleAddMethod : public method {
+public:
+ sampleAddMethod() {
+ this->_signature = "i:ii";
+ this->_help = "This method adds two integers together";
+ }
+ void
+ execute(xmlrpc_c::paramList const& paramList,
+ value * const retvalP) {
+
+ int const addend(paramList.getInt(0));
+ int const adder(paramList.getInt(1));
+
+ paramList.verifyEnd(2);
+
+ *retvalP = value_int(addend + adder);
+ }
+};
+
+
+
+static void
+createTestFile(string const& contents,
+ int * const fdP) {
+
+ string const filename("/tmp/xmlrpc_test_pstream");
+ unlink(filename.c_str());
+ int rc;
+ rc = open(filename.c_str(), O_RDWR | O_CREAT);
+ unlink(filename.c_str());
+
+ if (rc < 0)
+ throwf("Failed to create file '%s' as a test tool. errno=%d (%s)",
+ filename.c_str(), errno, strerror(errno));
+ else {
+ int const fd(rc);
+
+ int rc;
+
+ rc = write(fd, contents.c_str(), contents.length());
+
+ if (rc < 0)
+ throwf("write() of test file failed, errno=%d (%s)",
+ errno, strerror(errno));
+ else {
+ unsigned int bytesWritten(rc);
+
+ if (bytesWritten != contents.length())
+ throwf("Short write");
+ else {
+ int rc;
+ rc = lseek(fd, 0, SEEK_SET);
+
+ if (rc < 0)
+ throwf("lseek(0) of test file failed, errno=%d (%s)",
+ errno, strerror(errno));
+ }
+ }
+ *fdP = fd;
+ }
+}
+
+
+
+class serverPstreamConnTestSuite : public testSuite {
+
+public:
+ virtual string suiteName() {
+ return "serverPstreamConnTestSuite";
+ }
+ virtual void runtests(unsigned int const) {
+ int const devNullFd(open("/dev/null", 0));
+
+ if (devNullFd < 0)
+ throwf("Failed to open /dev/null, needed for test.");
+
+ registry myRegistry;
+
+ myRegistry.addMethod("sample.add", methodPtr(new sampleAddMethod));
+
+ registryPtr myRegistryP(new registry);
+
+ myRegistryP->addMethod("sample.add", methodPtr(new sampleAddMethod));
+
+ EXPECT_ERROR( // Empty options
+ serverPstreamConn::constrOpt opt;
+ serverPstreamConn server(opt);
+ );
+
+ EXPECT_ERROR( // No registry
+ serverPstreamConn server(serverPstreamConn::constrOpt()
+ .socketFd(3));
+ );
+
+ EXPECT_ERROR( // No socket fd
+ serverPstreamConn server(serverPstreamConn::constrOpt()
+ .registryP(&myRegistry));
+ );
+
+ EXPECT_ERROR( // No such file descriptor
+ serverPstreamConn server(serverPstreamConn::constrOpt()
+ .registryP(&myRegistry)
+ .socketFd(37));
+ );
+
+ {
+ serverPstreamConn server(serverPstreamConn::constrOpt()
+ .registryP(&myRegistry)
+ .socketFd(devNullFd));
+
+ bool eof;
+ server.runOnce(&eof);
+ TEST(eof);
+ }
+ {
+ int fd;
+ createTestFile("junk", &fd);
+
+ serverPstreamConn server(serverPstreamConn::constrOpt()
+ .registryP(&myRegistry)
+ .socketFd(fd));
+
+ bool eof;
+
+ EXPECT_ERROR( // EOF in the middle of a packet
+ server.runOnce(&eof);
+ );
+ close(fd);
+ }
+
+ close(devNullFd);
+ }
+};
+
+
+
+string
+serverPstreamTestSuite::suiteName() {
+ return "serverPstreamTestSuite";
+}
+
+
+void
+serverPstreamTestSuite::runtests(unsigned int const indentation) {
+
+ serverPstreamConnTestSuite().run(indentation + 1);
+
+}
+
Added: freeswitch/trunk/libs/xmlrpc-c/src/cpp/test/server_pstream.hpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/cpp/test/server_pstream.hpp Fri May 23 16:56:24 2008
@@ -0,0 +1,8 @@
+#include "tools.hpp"
+
+class serverPstreamTestSuite : public testSuite {
+
+public:
+ virtual std::string suiteName();
+ virtual void runtests(unsigned int const);
+};
Added: freeswitch/trunk/libs/xmlrpc-c/src/cpp/test/test.cpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/cpp/test/test.cpp Fri May 23 16:56:24 2008
@@ -0,0 +1,640 @@
+#include <string>
+#include <iostream>
+#include <iomanip>
+#include <vector>
+#include <sstream>
+#include <memory>
+#include <time.h>
+
+#include "xmlrpc-c/girerr.hpp"
+using girerr::error;
+#include "transport_config.h"
+#include "xmlrpc-c/base.hpp"
+#include "xmlrpc-c/oldcppwrapper.hpp"
+#include "xmlrpc-c/registry.hpp"
+
+#include "testclient.hpp"
+#include "registry.hpp"
+#include "server_abyss.hpp"
+#include "server_pstream.hpp"
+#include "tools.hpp"
+
+using namespace xmlrpc_c;
+using namespace std;
+
+//=========================================================================
+// Test Harness
+//=========================================================================
+//
+// There are two styles of test in here. The older ones are vaguely
+// inspired by Kent Beck's book on eXtreme Programming (XP) and use
+// the TEST...() macros.
+//
+// But this style is not really appropriate for C++. It's based on
+// code that explicitly tests for errors, as one would do in C. In C++,
+// it is cumbersome to catch exceptions on every call, so we don't in
+// the new style.
+
+// And there's not much point in trying to count test successes and
+// failures. Any failure is a problem, so in the new style, we just
+// quit after we recognize one (again, more in line with regular exception
+// throwing). With exception throwing, you can't count what _didn't_
+// cause an exception, so there's no meaningful count of test successes.
+//
+// To run the tests, type './cpptest'.
+// To check for memory leaks, install RedHat's 'memprof' utility, and
+// type 'memprof cpptest'.
+//
+// If you add new tests to this file, please deallocate any data
+// structures you use in the appropriate fashion. This allows us to test
+// various destructor code for memory leaks.
+
+
+//=========================================================================
+// Test Suites
+//=========================================================================
+
+void
+test_fault (void) {
+
+ // Create a new fault and perform basic operations.
+ XmlRpcFault fault1 = XmlRpcFault(6, "Sample fault");
+ TEST(fault1.getFaultCode() == 6);
+ TEST(fault1.getFaultString() == "Sample fault");
+
+ // Extract and examine the underlying xmlrpc_env struct.
+ xmlrpc_env *env1 = fault1.getFaultEnv();
+ TEST(env1 != NULL);
+ TEST(env1->fault_occurred);
+ TEST(env1->fault_code == 6);
+ TEST(strcmp(env1->fault_string, "Sample fault") == 0);
+
+ // Test our copy constructor.
+ XmlRpcFault fault2 = fault1;
+ TEST(fault2.getFaultCode() == 6);
+ TEST(fault2.getFaultString() == "Sample fault");
+
+ // Construct a fault from a pre-existing xmlrpc_env structure.
+ xmlrpc_env env3;
+ xmlrpc_env_init(&env3);
+ xmlrpc_env_set_fault(&env3, 7, "Another fault");
+ XmlRpcFault fault3 = XmlRpcFault(&env3);
+ xmlrpc_env_clean(&env3);
+ TEST(fault3.getFaultCode() == 7);
+ TEST(fault3.getFaultString() == "Another fault");
+
+ // Attempt to construct a fault from a fault-free xmlrpc_env.
+ xmlrpc_env env4;
+ xmlrpc_env_init(&env4);
+ try {
+ XmlRpcFault fault4 = XmlRpcFault(&env4);
+ TEST_FAILED("Constructed invalid XmlRpcFault");
+ } catch (XmlRpcFault const& fault) {
+ TEST_PASSED();
+ TEST(fault.getFaultCode() == XMLRPC_INTERNAL_ERROR);
+ }
+ xmlrpc_env_clean(&env4);
+}
+
+
+
+void test_env (void) {
+
+ // Declare these here to prevent silly compiler warnings about
+ // potentially uninitialized variables.
+ XmlRpcEnv env1;
+ XmlRpcEnv env2;
+
+ // Perform simple environment tests.
+ TEST(!env1.hasFaultOccurred());
+ xmlrpc_env_set_fault(env1, 8, "Fault 8");
+ TEST(env1.hasFaultOccurred());
+ XmlRpcFault fault1 = env1.getFault();
+ TEST(fault1.getFaultCode() == 8);
+ TEST(fault1.getFaultString() == "Fault 8");
+
+ // Test throwIfFaultOccurred.
+ try {
+ env2.throwIfFaultOccurred();
+ TEST_PASSED();
+ } catch (XmlRpcFault const&) {
+ TEST_FAILED("We threw a fault when one hadn't occurred");
+ }
+ xmlrpc_env_set_fault(env2, 9, "Fault 9");
+ try {
+ env2.throwIfFaultOccurred();
+ TEST_FAILED("A fault occurred, and we didn't throw it");
+ } catch (XmlRpcFault const& fault) {
+ TEST_PASSED();
+ TEST(fault.getFaultCode() == 9);
+ TEST(fault.getFaultString() == "Fault 9");
+ }
+
+ // Make sure we can't get a fault if one hasn't occurred.
+ XmlRpcEnv env3;
+ try {
+ XmlRpcFault fault3 = env3.getFault();
+ TEST_FAILED("We retrieved a non-existant fault");
+ } catch (XmlRpcFault const& fault) {
+ TEST_PASSED();
+ TEST(fault.getFaultCode() == XMLRPC_INTERNAL_ERROR);
+ }
+}
+
+void test_value (void) {
+ XmlRpcEnv env;
+
+ // Test basic reference counting behavior.
+ xmlrpc_value *v = xmlrpc_build_value(env, "i", (xmlrpc_int32) 1);
+ env.throwIfFaultOccurred();
+ XmlRpcValue val1 = XmlRpcValue(v, XmlRpcValue::CONSUME_REFERENCE);
+ v = xmlrpc_build_value(env, "i", (xmlrpc_int32) 2);
+ env.throwIfFaultOccurred();
+ XmlRpcValue val2 = v;
+ xmlrpc_DECREF(v);
+
+ // Borrow a reference.
+ v = xmlrpc_build_value(env, "i", (xmlrpc_int32) 3);
+ env.throwIfFaultOccurred();
+ XmlRpcValue val3 = XmlRpcValue(v, XmlRpcValue::CONSUME_REFERENCE);
+ xmlrpc_value *borrowed = val3.borrowReference();
+ TEST(borrowed == v);
+
+ // Make a reference.
+ v = xmlrpc_build_value(env, "i", (xmlrpc_int32) 4);
+ env.throwIfFaultOccurred();
+ XmlRpcValue val4 = XmlRpcValue(v, XmlRpcValue::CONSUME_REFERENCE);
+ xmlrpc_value *made = val4.makeReference();
+ TEST(made == v);
+ xmlrpc_DECREF(made);
+
+ // Test our default constructor.
+ XmlRpcValue val5;
+ TEST(val5.getBool() == false);
+
+ // Test our type introspection.
+ TEST(XmlRpcValue::makeInt(0).getType() == XMLRPC_TYPE_INT);
+
+ // Test our basic data types.
+ TEST(XmlRpcValue::makeInt(30).getInt() == 30);
+ TEST(XmlRpcValue::makeInt(-30).getInt() == -30);
+ TEST(XmlRpcValue::makeBool(true).getBool() == true);
+ TEST(XmlRpcValue::makeBool(false).getBool() == false);
+ TEST(XmlRpcValue::makeDateTime("19980717T14:08:55").getRawDateTime() ==
+ "19980717T14:08:55");
+ TEST(XmlRpcValue::makeString("foo").getString() == "foo");
+ TEST(XmlRpcValue::makeString("bar", 3).getString() == "bar");
+ TEST(XmlRpcValue::makeString("bar", 3).getString() == "bar");
+ TEST(XmlRpcValue::makeString("a\0b").getString() == string("a\0b"));
+ XmlRpcValue::makeArray().getArray();
+ XmlRpcValue::makeStruct().getStruct();
+
+ // Test Base64 values.
+ const unsigned char *b64_data;
+ size_t b64_len;
+ XmlRpcValue val6 = XmlRpcValue::makeBase64((unsigned char*) "a\0\0b", 4);
+ val6.getBase64(b64_data, b64_len);
+ TEST(b64_len == 4);
+ TEST(memcmp(b64_data, "a\0\0b", 4) == 0);
+
+ // Test arrays.
+ XmlRpcValue array = XmlRpcValue::makeArray();
+ TEST(array.arraySize() == 0);
+ array.arrayAppendItem(XmlRpcValue::makeString("foo"));
+ TEST(array.arraySize() == 1);
+ array.arrayAppendItem(XmlRpcValue::makeString("bar"));
+ TEST(array.arraySize() == 2);
+ TEST(array.arrayGetItem(0).getString() == "foo");
+ TEST(array.arrayGetItem(1).getString() == "bar");
+
+ // Test structs.
+ XmlRpcValue strct = XmlRpcValue::makeStruct();
+ TEST(strct.structSize() == 0);
+ strct.structSetValue("foo", XmlRpcValue::makeString("fooval"));
+ TEST(strct.structSize() == 1);
+ strct.structSetValue("bar", XmlRpcValue::makeString("barval"));
+ TEST(strct.structSize() == 2);
+ TEST(strct.structHasKey("bar"));
+ TEST(!strct.structHasKey("nosuch"));
+ for (size_t i = 0; i < strct.structSize(); i++) {
+ string key;
+ XmlRpcValue value;
+ strct.structGetKeyAndValue(i, key, value);
+ TEST(key + "val" == value.getString());
+ }
+}
+
+
+
+static void
+testXmlRpcCpp() {
+/*----------------------------------------------------------------------------
+ Test the legacy XmlRpcCpp.cpp library
+-----------------------------------------------------------------------------*/
+ cout << "Testing XmlRpcCpp library..." << endl;
+
+ test_fault();
+ test_env();
+ test_value();
+}
+
+
+
+class intTestSuite : public testSuite {
+public:
+ virtual string suiteName() {
+ return "intTestSuite";
+ }
+ virtual void runtests(unsigned int const) {
+ value_int int1(7);
+ TEST(static_cast<int>(int1) == 7);
+ value_int int2(-7);
+ TEST(static_cast<int>(int2) == -7);
+ value val1(int1);
+ TEST(val1.type() == value::TYPE_INT);
+ value_int int3(val1);
+ TEST(static_cast<int>(int3) == 7);
+ try {
+ value_int int4(value_double(3.7));
+ TEST_FAILED("invalid cast double-int suceeded");
+ } catch (error) {}
+ }
+};
+
+
+
+class doubleTestSuite : public testSuite {
+public:
+ virtual string suiteName() {
+ return "doubleTestSuite";
+ }
+ virtual void runtests(unsigned int const) {
+ value_double double1(3.14);
+ TEST(static_cast<double>(double1) == 3.14);
+ value val1(double1);
+ TEST(val1.type() == value::TYPE_DOUBLE);
+ value_double double2(val1);
+ TEST(static_cast<double>(double2) == 3.14);
+ try {
+ value_double double4(value_int(4));
+ TEST_FAILED("invalid cast int-double suceeded");
+ } catch (error) {}
+ }
+};
+
+
+
+class booleanTestSuite : public testSuite {
+public:
+ virtual string suiteName() {
+ return "booleanTestSuite";
+ }
+ virtual void runtests(unsigned int const) {
+ value_boolean boolean1(true);
+ TEST(static_cast<bool>(boolean1) == true);
+ value_boolean boolean2(false);
+ TEST(static_cast<bool>(boolean2) == false);
+ value val1(boolean1);
+ TEST(val1.type() == value::TYPE_BOOLEAN);
+ value_boolean boolean3(val1);
+ TEST(static_cast<bool>(boolean3) == true);
+ try {
+ value_boolean boolean4(value_int(4));
+ TEST_FAILED("invalid cast int-boolean suceeded");
+ } catch (error) {}
+ }
+};
+
+
+
+class datetimeTestSuite : public testSuite {
+public:
+ virtual string suiteName() {
+ return "datetimeTestSuite";
+ }
+ virtual void runtests(unsigned int const) {
+ time_t const testTime(900684535);
+ value_datetime datetime1("19980717T14:08:55");
+ TEST(static_cast<time_t>(datetime1) == testTime);
+ value_datetime datetime2(testTime);
+ TEST(static_cast<time_t>(datetime2) == testTime);
+ value val1(datetime1);
+ TEST(val1.type() == value::TYPE_DATETIME);
+ value_datetime datetime3(val1);
+ TEST(static_cast<time_t>(datetime3) == testTime);
+ try {
+ value_datetime datetime4(value_int(4));
+ TEST_FAILED("invalid cast int-datetime suceeded");
+ } catch (error) {}
+ }
+};
+
+
+
+class stringTestSuite : public testSuite {
+public:
+ virtual string suiteName() {
+ return "stringTestSuite";
+ }
+ virtual void runtests(unsigned int const) {
+ value_string string1("hello world");
+ TEST(static_cast<string>(string1) == "hello world");
+ value_string string2("embedded\0null");
+ TEST(static_cast<string>(string2) == "embedded\0null");
+ value val1(string1);
+ TEST(val1.type() == value::TYPE_STRING);
+ value_string string3(val1);
+ TEST(static_cast<string>(string3) == "hello world");
+ try {
+ value_string string4(value_int(4));
+ TEST_FAILED("invalid cast int-string succeeded");
+ } catch (error) {}
+ value_string string5("hello world", value_string::nlCode_all);
+ TEST(static_cast<string>(string5) == "hello world");
+ value_string string6("hello\nthere\rworld\r\n\n",
+ value_string::nlCode_all);
+ TEST(static_cast<string>(string6) == "hello\nthere\nworld\n\n");
+ TEST(string6.crlfValue() == "hello\r\nthere\r\nworld\r\n\r\n");
+ value_string string7("hello\nthere\rworld\r\n\n",
+ value_string::nlCode_lf);
+ TEST(static_cast<string>(string7) == "hello\nthere\rworld\r\n\n");
+ }
+};
+
+
+
+class bytestringTestSuite : public testSuite {
+public:
+ virtual string suiteName() {
+ return "bytestringTestSuite";
+ }
+ virtual void runtests(unsigned int const) {
+ unsigned char bytestringArray[] = {0x10, 0x11, 0x12, 0x13, 0x14};
+ vector<unsigned char>
+ bytestringData(&bytestringArray[0], &bytestringArray[4]);
+ value_bytestring bytestring1(bytestringData);
+
+ vector<unsigned char> const dataReadBack1(
+ bytestring1.vectorUcharValue());
+ TEST(dataReadBack1 == bytestringData);
+ value val1(bytestring1);
+ TEST(val1.type() == value::TYPE_BYTESTRING);
+ value_bytestring bytestring2(val1);
+ vector<unsigned char> const dataReadBack2(
+ bytestring2.vectorUcharValue());
+ TEST(dataReadBack2 == bytestringData);
+ try {
+ value_bytestring bytestring4(value_int(4));
+ TEST_FAILED("invalid cast int-bytestring suceeded");
+ } catch (error) {}
+ }
+};
+
+
+
+class nilTestSuite : public testSuite {
+public:
+ virtual string suiteName() {
+ return "nilTestSuite";
+ }
+ virtual void runtests(unsigned int const) {
+ value_nil nil1;
+ value val1(nil1);
+ TEST(val1.type() == value::TYPE_NIL);
+ value_nil nil2(val1);
+ try {
+ value_nil nil4(value_int(4));
+ TEST_FAILED("invalid cast int-nil suceeded");
+ } catch (error) {}
+ }
+};
+
+
+
+class i8TestSuite : public testSuite {
+public:
+ virtual string suiteName() {
+ return "i8TestSuite";
+ }
+ virtual void runtests(unsigned int const) {
+ value_i8 int1(7);
+ TEST(static_cast<xmlrpc_int64>(int1) == 7);
+ value_i8 int2(-7);
+ TEST(static_cast<xmlrpc_int64>(int2) == -7);
+ value_i8 int5(1ull << 40);
+ TEST(static_cast<xmlrpc_int64>(int5) == (1ull << 40));
+ value val1(int1);
+ TEST(val1.type() == value::TYPE_I8);
+ value_i8 int3(val1);
+ TEST(static_cast<xmlrpc_int64>(int3) == 7);
+ try {
+ value_i8 int4(value_double(3.7));
+ TEST_FAILED("invalid cast double-i8 suceeded");
+ } catch (error) {}
+ }
+};
+
+
+
+class structTestSuite : public testSuite {
+public:
+ virtual string suiteName() {
+ return "structTestSuite";
+ }
+ virtual void runtests(unsigned int const) {
+ map<string, value> structData;
+ pair<string, value> member("the_integer", value_int(9));
+ structData.insert(member);
+
+ value_struct struct1(structData);
+
+ map<string, value> dataReadBack(struct1);
+
+ TEST(static_cast<int>(value_int(dataReadBack["the_integer"])) == 9);
+
+ value val1(struct1);
+ TEST(val1.type() == value::TYPE_STRUCT);
+ value_struct struct2(val1);
+ try {
+ value_struct struct4(value_int(4));
+ TEST_FAILED("invalid cast int-struct suceeded");
+ } catch (error) {}
+ }
+};
+
+
+
+class arrayTestSuite : public testSuite {
+public:
+ virtual string suiteName() {
+ return "arrayTestSuite";
+ }
+ virtual void runtests(unsigned int const) {
+ vector<value> arrayData;
+ arrayData.push_back(value_int(7));
+ arrayData.push_back(value_double(2.78));
+ arrayData.push_back(value_string("hello world"));
+ value_array array1(arrayData);
+
+ TEST(array1.size() == 3);
+ vector<value> dataReadBack1(array1.vectorValueValue());
+ TEST(dataReadBack1[0].type() == value::TYPE_INT);
+ TEST(static_cast<int>(value_int(dataReadBack1[0])) == 7);
+ TEST(dataReadBack1[1].type() == value::TYPE_DOUBLE);
+ TEST(static_cast<double>(value_double(dataReadBack1[1])) == 2.78);
+ TEST(dataReadBack1[2].type() == value::TYPE_STRING);
+ TEST(static_cast<string>(value_string(dataReadBack1[2])) ==
+ "hello world");
+
+ value val1(array1);
+ TEST(val1.type() == value::TYPE_ARRAY);
+ value_array array2(val1);
+ TEST(array2.size() == 3);
+ try {
+ value_array array4(value_int(4));
+ TEST_FAILED("invalid cast int-array suceeded");
+ } catch (error) {}
+ }
+};
+
+
+
+class valueTestSuite : public testSuite {
+
+public:
+ virtual string suiteName() {
+ return "valueTestSuite";
+ }
+ virtual void runtests(unsigned int const indentation) {
+
+ intTestSuite().run(indentation+1);
+ doubleTestSuite().run(indentation+1);
+ booleanTestSuite().run(indentation+1);
+ datetimeTestSuite().run(indentation+1);
+ stringTestSuite().run(indentation+1);
+ bytestringTestSuite().run(indentation+1);
+ nilTestSuite().run(indentation+1);
+ i8TestSuite().run(indentation+1);
+ structTestSuite().run(indentation+1);
+ arrayTestSuite().run(indentation+1);
+ }
+};
+
+
+class paramListTestSuite : public testSuite {
+
+public:
+ virtual string suiteName() {
+ return "paramListTestSuite";
+ }
+ virtual void runtests(unsigned int const) {
+
+ paramList paramList1;
+ TEST(paramList1.size() == 0);
+
+ paramList1.add(value_int(7));
+ paramList1.add(value_boolean(true));
+ paramList1.add(value_double(3.14));
+ time_t const timeZero(0);
+ paramList1.add(value_datetime(timeZero));
+ time_t const timeFuture(time(NULL)+100);
+ paramList1.add(value_datetime(timeFuture));
+ paramList1.add(value_string("hello world"));
+ unsigned char bytestringArray[] = {0x10, 0x11, 0x12, 0x13, 0x14};
+ vector<unsigned char>
+ bytestringData(&bytestringArray[0], &bytestringArray[4]);
+ paramList1.add(value_bytestring(bytestringData));
+ vector<value> arrayData;
+ arrayData.push_back(value_int(7));
+ arrayData.push_back(value_double(2.78));
+ arrayData.push_back(value_string("hello world"));
+ paramList1.add(value_array(arrayData));
+ map<string, value> structData;
+ pair<string, value> member("the_integer", value_int(9));
+ structData.insert(member);
+ paramList1.add(value_struct(structData));
+ paramList1.add(value_nil());
+ paramList1.add(value_i8((xmlrpc_int64)UINT_MAX + 1));
+
+ TEST(paramList1.size() == 11);
+
+ TEST(paramList1.getInt(0) == 7);
+ TEST(paramList1.getInt(0, 7) == 7);
+ TEST(paramList1.getInt(0, -5, 7) == 7);
+ TEST(paramList1.getBoolean(1) == true);
+ TEST(paramList1.getDouble(2) == 3.14);
+ TEST(paramList1.getDouble(2, 1) == 3.14);
+ TEST(paramList1.getDouble(2, 1, 4) == 3.14);
+ TEST(paramList1.getDatetime_sec(3) == 0);
+ TEST(paramList1.getDatetime_sec(3, paramList::TC_ANY) == timeZero);
+ TEST(paramList1.getDatetime_sec(3, paramList::TC_NO_FUTURE)
+ == timeZero);
+ TEST(paramList1.getDatetime_sec(4, paramList::TC_NO_PAST)
+ == timeFuture);
+ TEST(paramList1.getString(5) == "hello world");
+ TEST(paramList1.getBytestring(6)[0] == 0x10);
+ TEST(paramList1.getArray(7).size() == 3);
+ TEST(paramList1.getArray(7, 3).size() == 3);
+ TEST(paramList1.getArray(7, 1, 3).size() == 3);
+ paramList1.getStruct(8)["the_integer"];
+ paramList1.getNil(9);
+ TEST(paramList1.getI8(10) == (xmlrpc_int64)UINT_MAX + 1);
+ paramList1.verifyEnd(11);
+
+ paramList paramList2(5);
+ TEST(paramList2.size() == 0);
+ }
+};
+
+//=========================================================================
+// Test Driver
+//=========================================================================
+
+int
+main(int argc, char**) {
+
+ int retval;
+
+ if (argc-1 > 0) {
+ cout << "Program takes no arguments" << endl;
+ exit(1);
+ }
+
+ bool testsPassed;
+
+ try {
+ // Add your test suites here.
+ valueTestSuite().run(0);
+ paramListTestSuite().run(0);
+ registryTestSuite().run(0);
+ serverAbyssTestSuite().run(0);
+#ifndef WIN32
+ serverPstreamTestSuite().run(0);
+#endif
+ clientTestSuite().run(0);
+
+ testXmlRpcCpp();
+
+ testsPassed = true;
+ } catch (error const& error) {
+ cout << "Unexpected error thrown: " << error.what() << endl;
+ testsPassed = false;
+ } catch (XmlRpcFault const& fault) {
+ cout << "Unexpected XML-RPC fault when running test suites." << endl
+ << "Fault #" << fault.getFaultCode()
+ << ": " << fault.getFaultString() << endl;
+ testsPassed = false;
+ } catch (...) {
+ cout << "Unexpected exception when running test suites." << endl;
+ testsPassed = false;
+ }
+
+ if (testsPassed) {
+ cout << "PASSED" << endl;
+ retval = 0;
+ } else {
+ cout << "FAILED" << endl;
+ retval = 1;
+ }
+ return retval;
+}
Added: freeswitch/trunk/libs/xmlrpc-c/src/cpp/test/testclient.cpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/cpp/test/testclient.cpp Fri May 23 16:56:24 2008
@@ -0,0 +1,861 @@
+/*=============================================================================
+ testclient
+===============================================================================
+ Test the client C++ facilities of XML-RPC for C/C++.
+
+ Contrary to what you might expect, we use the server facilities too
+ because we test much of the client using a simulated server, via the
+ "direct" client XML transport we define herein.
+=============================================================================*/
+#include <string>
+#include <iostream>
+#include <vector>
+#include <sstream>
+#include <memory>
+#include <time.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "xmlrpc-c/girerr.hpp"
+using girerr::error;
+#include "transport_config.h"
+#include "xmlrpc-c/base.hpp"
+#include "xmlrpc-c/registry.hpp"
+#include "xmlrpc-c/client.hpp"
+#include "xmlrpc-c/client_simple.hpp"
+
+#include "tools.hpp"
+#include "testclient.hpp"
+
+using namespace xmlrpc_c;
+using namespace std;
+
+
+
+class sampleAddMethod : public method {
+public:
+ sampleAddMethod() {
+ this->_signature = "ii";
+ this->_help = "This method adds two integers together";
+ }
+ void
+ execute(xmlrpc_c::paramList const& paramList,
+ value * const retvalP) {
+
+ int const addend(paramList.getInt(0));
+ int const adder(paramList.getInt(1));
+
+ paramList.verifyEnd(2);
+
+ *retvalP = value_int(addend + adder);
+ }
+};
+
+
+
+class testApacheDialectMethod : public method {
+public:
+ void
+ execute(xmlrpc_c::paramList const& paramList,
+ value * const retvalP) {
+
+ paramList.getNil(0);
+
+ paramList.verifyEnd(1);
+
+ *retvalP = value_i8(7ll);
+ }
+};
+
+
+
+class carriageParm_direct : public carriageParm {
+public:
+ carriageParm_direct(registry * const registryP) : registryP(registryP) {}
+
+ registry * registryP;
+};
+
+
+class clientXmlTransport_direct : public clientXmlTransport {
+
+public:
+ void
+ call(xmlrpc_c::carriageParm * const carriageParmP,
+ string const& callXml,
+ string * const responseXmlP) {
+
+ carriageParm_direct * const parmP =
+ dynamic_cast<carriageParm_direct *>(carriageParmP);
+
+ if (parmP == NULL)
+ throw(error("Carriage parameter passed to the direct "
+ "transport is not type carriageParm_direct"));
+
+ parmP->registryP->processCall(callXml, responseXmlP);
+ }
+};
+
+
+
+class clientDirectAsyncTestSuite : public testSuite {
+/*----------------------------------------------------------------------------
+ See clientDirectTestSuite for a description of how we use a
+ clientXmlTransport_direct object to test client functions.
+
+ The object of this class tests the async client functions. With
+ clientXmlTransport_direct, these are pretty simple because the
+ transport doesn't even implement an asynchronous interface; it
+ relies on the base class' emulation of start() using call().
+
+ Some day, we should add true asynchronous capability to
+ clientXmlTransport_direct and really test things.
+-----------------------------------------------------------------------------*/
+public:
+ virtual string suiteName() {
+ return "clientDirectAsyncTestSuite";
+ }
+ virtual void runtests(unsigned int const) {
+
+ registry myRegistry;
+
+ myRegistry.addMethod("sample.add", methodPtr(new sampleAddMethod));
+
+ carriageParm_direct carriageParmDirect(&myRegistry);
+ clientXmlTransport_direct transportDirect;
+ client_xml clientDirect(&transportDirect);
+ paramList paramListSampleAdd1;
+ paramListSampleAdd1.add(value_int(5));
+ paramListSampleAdd1.add(value_int(7));
+ paramList paramListSampleAdd2;
+ paramListSampleAdd2.add(value_int(30));
+ paramListSampleAdd2.add(value_int(-10));
+
+ rpcPtr const rpcSampleAdd1P("sample.add", paramListSampleAdd1);
+ rpcSampleAdd1P->start(&clientDirect, &carriageParmDirect);
+ rpcPtr const rpcSampleAdd2P("sample.add", paramListSampleAdd2);
+ rpcSampleAdd2P->start(&clientDirect, &carriageParmDirect);
+
+ // Note that for clientXmlTransport_direct, start() and call() are
+ // the same thing. I.e. the RPC is guaranteed finished as soon
+ // as it is started.
+
+
+ clientDirect.finishAsync(timeout());
+ clientDirect.finishAsync(timeout(50));
+
+ TEST(rpcSampleAdd1P->isFinished());
+ TEST(rpcSampleAdd1P->isSuccessful());
+ value_int const result1(rpcSampleAdd1P->getResult());
+ TEST(static_cast<int>(result1) == 12);
+
+ TEST(rpcSampleAdd2P->isFinished());
+ TEST(rpcSampleAdd1P->isSuccessful());
+ value_int const result2(rpcSampleAdd2P->getResult());
+ TEST(static_cast<int>(result2) == 20);
+ }
+};
+
+
+
+class clientDirectTestSuite : public testSuite {
+/*----------------------------------------------------------------------------
+ The object of this class tests the client facilities by using a
+ special client XML transport defined above and an XML-RPC server we
+ build ourselves and run inline. We build the server out of a
+ xmlrpc_c::registry object and our transport just delivers XML
+ directly to the registry object and gets the response XML from it
+ and delivers that back. There's no network or socket or pipeline or
+ anything -- the transport actually executes the XML-RPC method.
+-----------------------------------------------------------------------------*/
+public:
+ virtual string suiteName() {
+ return "clientDirectTestSuite";
+ }
+ virtual void runtests(unsigned int const indentation) {
+ registry myRegistry;
+
+ myRegistry.addMethod("sample.add", methodPtr(new sampleAddMethod));
+
+ carriageParm_direct carriageParmDirect(&myRegistry);
+ clientXmlTransport_direct transportDirect;
+ client_xml clientDirect(&transportDirect);
+ paramList paramListSampleAdd;
+ paramListSampleAdd.add(value_int(5));
+ paramListSampleAdd.add(value_int(7));
+ paramList paramListEmpty;
+ {
+ /* Test a successful RPC */
+ rpcPtr rpcSampleAddP("sample.add", paramListSampleAdd);
+ rpcSampleAddP->call(&clientDirect, &carriageParmDirect);
+ TEST(rpcSampleAddP->isFinished());
+ TEST(rpcSampleAddP->isSuccessful());
+ value_int const resultDirect(rpcSampleAddP->getResult());
+ TEST(static_cast<int>(resultDirect) == 12);
+ }
+ {
+ /* Test a failed RPC */
+ rpcPtr const rpcSampleAddP("sample.add", paramListEmpty);
+ rpcSampleAddP->call(&clientDirect, &carriageParmDirect);
+ TEST(rpcSampleAddP->isFinished());
+ TEST(!rpcSampleAddP->isSuccessful());
+ fault const fault0(rpcSampleAddP->getFault());
+ TEST(fault0.getCode() == fault::CODE_TYPE);
+ }
+
+ {
+ /* Test with an auto object transport */
+ client_xml clientDirect(
+ clientXmlTransportPtr(new clientXmlTransport_direct));
+ rpcPtr rpcSampleAddP("sample.add", paramListSampleAdd);
+ rpcSampleAddP->call(&clientDirect, &carriageParmDirect);
+ TEST(rpcSampleAddP->isFinished());
+ TEST(rpcSampleAddP->isSuccessful());
+ EXPECT_ERROR(fault fault0(rpcSampleAddP->getFault()););
+ value_int const resultDirect(rpcSampleAddP->getResult());
+ TEST(static_cast<int>(resultDirect) == 12);
+ }
+ {
+ /* Test with implicit RPC -- success */
+ rpcOutcome outcome;
+ clientDirect.call(&carriageParmDirect, "sample.add",
+ paramListSampleAdd, &outcome);
+ TEST(outcome.succeeded());
+ value_int const result(outcome.getResult());
+ TEST(static_cast<int>(result) == 12);
+ }
+ {
+ /* Test with implicit RPC - failure */
+ rpcOutcome outcome;
+ clientDirect.call(&carriageParmDirect, "nosuchmethod",
+ paramList(), &outcome);
+ TEST(!outcome.succeeded());
+ TEST(outcome.getFault().getCode() == fault::CODE_NO_SUCH_METHOD);
+ TEST(outcome.getFault().getDescription().size() > 0);
+ }
+
+ int interruptFlag(0);
+ EXPECT_ERROR(transportDirect.setInterrupt(&interruptFlag););
+ // This transport class isn't interruptible
+ EXPECT_ERROR(clientDirect.setInterrupt(&interruptFlag););
+ // Same as above
+
+ clientDirectAsyncTestSuite().run(indentation+1);
+ }
+};
+
+
+
+class curlTransportTestSuite : public testSuite {
+
+public:
+ virtual string suiteName() {
+ return "curlTransportTestSuite";
+ }
+ virtual void runtests(unsigned int const) {
+#if MUST_BUILD_CURL_CLIENT
+ clientXmlTransport_curl transport0;
+ clientXmlTransport_curl transport1("eth0");
+ clientXmlTransport_curl transport2("eth0", true);
+ clientXmlTransport_curl transport3("eth0", true, true);
+ clientXmlTransport_curl transport4(
+ clientXmlTransport_curl::constrOpt()
+ .network_interface("eth0")
+ .no_ssl_verifypeer(true)
+ .no_ssl_verifyhost(true)
+ .user_agent("my user agent")
+ .ssl_cert("/etc/sslcert")
+ .sslcerttype("PEM")
+ .sslcertpasswd("mypass")
+ .sslkey("/etc/sslkey")
+ .sslkeytype("DER")
+ .sslkeypasswd("mykeypass")
+ .sslengine("mysslengine")
+ .sslengine_default(true)
+ .sslversion(XMLRPC_SSLVERSION_SSLv2)
+ .cainfo("/etc/cainfo")
+ .capath("/etc/cadir")
+ .randomfile("/dev/random")
+ .egdsocket("/tmp/egdsocket")
+ .ssl_cipher_list("RC4-SHA:DEFAULT")
+ );
+
+ clientXmlTransport_curl transport5(
+ clientXmlTransport_curl::constrOpt()
+ .no_ssl_verifypeer(false));
+
+ clientXmlTransport_curl transport6(
+ clientXmlTransport_curl::constrOpt());
+
+ clientXmlTransportPtr transport1P(new clientXmlTransport_curl);
+ clientXmlTransportPtr transport2P;
+ transport2P = transport1P;
+
+ time_t nowtime = time(NULL);
+ transport2P->finishAsync(timeout());
+ transport2P->finishAsync(timeout(2000));
+ transport2P->finishAsync(2000);
+ TEST(time(NULL) <= nowtime + 1);
+
+ int interruptFlag;
+ transport2P->setInterrupt(&interruptFlag);
+ interruptFlag = 0;
+ transport2P->finishAsync(2000);
+ transport2P->finishAsync(timeout());
+#else
+ EXPECT_ERROR(clientXmlTransport_curl transport0;);
+ EXPECT_ERROR(clientXmlTransport_curl transport1("eth0"););
+ EXPECT_ERROR(clientXmlTransport_curl transport0("eth0", true););
+ EXPECT_ERROR(clientXmlTransport_curl transport0("eth0", true, true););
+#endif
+ }
+};
+
+
+
+class libwwwTransportTestSuite : public testSuite {
+
+public:
+ virtual string suiteName() {
+ return "libwwwTransportTestSuite";
+ }
+ virtual void runtests(unsigned int const) {
+#if MUST_BUILD_LIBWWW_CLIENT
+ clientXmlTransport_libwww transport0;
+ clientXmlTransport_libwww transport1("getbent");
+ clientXmlTransport_libwww transport2("getbent", "1.0");
+ clientXmlTransportPtr transport1P(new clientXmlTransport_libwww);
+ clientXmlTransportPtr transport2P;
+ transport2P = transport1P;
+#else
+ EXPECT_ERROR(clientXmlTransport_libwww transport0;);
+ EXPECT_ERROR(clientXmlTransport_libwww transport1("getbent"););
+ EXPECT_ERROR(clientXmlTransport_libwww transport2("getbent", "1.0"););
+#endif
+ }
+};
+
+
+
+class wininetTransportTestSuite : public testSuite {
+
+public:
+ virtual string suiteName() {
+ return "wininetTransportTestSuite";
+ }
+ virtual void runtests(unsigned int const) {
+#if MUST_BUILD_WININET_CLIENT
+ clientXmlTransport_wininet transport0;
+ clientXmlTransport_wininet transport1(true);
+ clientXmlTransportPtr transport1P(new clientXmlTransport_wininet);
+ clientXmlTransportPtr transport2P;
+ transport2P = transport1P;
+#else
+ EXPECT_ERROR(clientXmlTransport_wininet transport0;);
+ EXPECT_ERROR(clientXmlTransport_wininet transport1(true););
+#endif
+ }
+};
+
+
+
+class ambivalentHttpTransportTestSuite : public testSuite {
+
+public:
+ virtual string suiteName() {
+ return "ambivalentHttpTransportTestSuite";
+ }
+ virtual void runtests(unsigned int const) {
+ vector<string> const typeList(
+ clientXmlTransport_http::availableTypes());
+
+ TEST(typeList.size() > 0);
+
+ clientXmlTransportPtr const transportP(
+ clientXmlTransport_http::create());
+ carriageParm_http0 carriageParm0("http://whatsamatta.edux");
+ client_xml client0(transportP);
+
+ rpcOutcome outcome;
+
+ // Fails because there's no such server
+ EXPECT_ERROR(
+ client0.call(&carriageParm0, "nosuchmethod", paramList(),
+ &outcome);
+ );
+ }
+};
+
+
+
+class pstreamTransportTestSuite : public testSuite {
+
+public:
+ virtual string suiteName() {
+ return "pstreamTransportTestSuite";
+ }
+ virtual void runtests(unsigned int const) {
+ int const devNullFd(open("/dev/null", 0));
+
+ if (devNullFd < 0)
+ throw error("Failed to open /dev/null, needed for test.");
+
+ EXPECT_ERROR(clientXmlTransport_pstream transport1(
+ clientXmlTransport_pstream::constrOpt()
+ .fd(37)
+ );); // ERROR: no such file descriptor
+
+ carriageParm_pstream carriageParm0;
+
+ {
+ clientXmlTransport_pstream transport2(
+ clientXmlTransport_pstream::constrOpt()
+ .fd(devNullFd)
+ );
+
+ string callXml("hello");
+ string responseXml;
+ EXPECT_ERROR(transport2.call(NULL, callXml, &responseXml););
+ // Error: carriage parm not of type carriageParm_pstream
+ EXPECT_ERROR(transport2.call(&carriageParm0, callXml,
+ &responseXml););
+ // Error: no response
+ }
+ clientXmlTransportPtr transport1P(new clientXmlTransport_pstream(
+ clientXmlTransport_pstream::constrOpt()
+ .fd(devNullFd)
+ ));
+ clientXmlTransportPtr transport2P;
+ transport2P = transport1P;
+
+ close(devNullFd);
+ }
+};
+
+
+
+class clientXmlTransportTestSuite : public testSuite {
+
+public:
+ virtual string suiteName() {
+ return "clientXmlTransportTestSuite";
+ }
+ virtual void runtests(unsigned int const indentation) {
+ curlTransportTestSuite().run(indentation + 1);
+ libwwwTransportTestSuite().run(indentation + 1);
+ wininetTransportTestSuite().run(indentation + 1);
+ ambivalentHttpTransportTestSuite().run(indentation + 1);
+ pstreamTransportTestSuite().run(indentation + 1);
+ }
+};
+
+
+
+class clientSimpleTestSuite : public testSuite {
+
+public:
+ virtual string suiteName() {
+ return "clientSimpleTestSuite";
+ }
+ virtual void runtests(unsigned int const) {
+
+ clientSimple clientS0;
+ paramList paramList0;
+
+ value result0;
+
+ // These will fail because there's no such server
+ EXPECT_ERROR(clientS0.call("http://mf.comm", "biteme", &result0););
+
+ EXPECT_ERROR(
+ clientS0.call("http://mf.comm", "biteme", "s", &result0, "hard");
+ );
+
+ EXPECT_ERROR(
+ clientS0.call("http://mf.comm", "biteme", paramList0, &result0);
+ );
+ }
+};
+
+
+
+class clientCurlIntTestSuite : public testSuite {
+/*----------------------------------------------------------------------------
+ The object of this class tests interruptibility functions of the
+ combination of a client with Curl transport.
+
+ We don't have an HTTP server, so we test only superficially.
+-----------------------------------------------------------------------------*/
+public:
+ virtual string suiteName() {
+ return "clientCurlIntTestSuite";
+ }
+ virtual void runtests(unsigned int) {
+#if MUST_BUILD_CURL_CLIENT
+ clientXmlTransport_curl transportc0;
+ client_xml client0(&transportc0);
+ carriageParm_curl0 carriageParmCurl("http://suckthis.com");
+
+ paramList paramList0;
+
+ rpcOutcome outcome0;
+
+ int interruptFlag;
+ client0.setInterrupt(&interruptFlag);
+
+ interruptFlag = 1;
+ // This fails because the call gets immediately interrupted
+ EXPECT_ERROR(
+ client0.call(&carriageParmCurl, "blowme", paramList0, &outcome0);
+ );
+ interruptFlag = 0;
+ // This fails because server doesn't exist
+ EXPECT_ERROR(
+ client0.call(&carriageParmCurl, "blowme", paramList0, &outcome0);
+ );
+#endif
+ }
+};
+
+
+
+class clientCurlTestSuite : public testSuite {
+/*----------------------------------------------------------------------------
+ The object of this class tests the combination of a client with
+ Curl transport. We assume Curl transports themselves have already
+ been tested and clients with direct transports have already been tested.
+
+ We don't have an HTTP server, so we test only superficially.
+
+ In the future, we could either start a server or use some server that's
+ normally avaailble on the Internet.
+-----------------------------------------------------------------------------*/
+public:
+ virtual string suiteName() {
+ return "clientCurlTestSuite";
+ }
+ virtual void runtests(unsigned int const indentation) {
+#if MUST_BUILD_CURL_CLIENT
+ clientXmlTransport_curl transportc0;
+ client_xml client0(&transportc0);
+ carriageParm_http0 carriageParmHttp("http://suckthis.com");
+ carriageParm_curl0 carriageParmCurl("http://suckthis.com");
+ connection connection0(&client0, &carriageParmHttp);
+
+ paramList paramList0;
+
+ rpcOutcome outcome0;
+
+ // This fails because server doesn't exist
+ EXPECT_ERROR(
+ client0.call(&carriageParmHttp, "blowme", paramList0, &outcome0);
+ );
+
+ // This fails because server doesn't exist
+ EXPECT_ERROR(
+ client0.call(&carriageParmCurl, "blowme", paramList0, &outcome0);
+ );
+
+ rpcPtr rpc0P("blowme", paramList0);
+
+ // This fails because server doesn't exist
+ EXPECT_ERROR(rpc0P->call(&client0, &carriageParmCurl););
+
+ rpcPtr rpc1P("blowme", paramList0);
+ // This fails because server doesn't exist
+ EXPECT_ERROR(rpc1P->call(connection0););
+
+ rpcPtr rpc2P("blowme", paramList0);
+
+ // This RPC fails to execute because the server doesn't exist,
+ // But libcurl "starts" it just fine.
+ rpc2P->start(&client0, &carriageParmCurl);
+
+ transportc0.finishAsync(5000);
+
+ TEST(rpc2P->isFinished());
+
+ TEST(!rpc2P->isSuccessful());
+
+ // Because the RPC did not return an XML-RPC failure (because the
+ // server doesn't exist), this throws:
+ EXPECT_ERROR(rpc2P->getFault(););
+
+ rpcPtr rpc3P("blowme", paramList0);
+ // This RPC fails to execute because the server doesn't exist
+ rpc3P->start(connection0);
+
+ transportc0.finishAsync(5000);
+ TEST(rpc2P->isFinished());
+ TEST(!rpc2P->isSuccessful());
+
+ clientCurlIntTestSuite().run(indentation+1);
+#else
+ // This fails because there is no Curl transport in the library.
+ EXPECT_ERROR(clientXmlTransport_curl transportc0;);
+#endif
+ }
+};
+
+
+
+class carriageParmTestSuite : public testSuite {
+
+public:
+ virtual string suiteName() {
+ return "carriageParmTestSuite";
+ }
+ virtual void runtests(unsigned int) {
+ carriageParm_http0 carriageParm1("http://suckthis.com");
+ carriageParm_curl0 carriageParm2("http://suckthis.com");
+ carriageParm_libwww0 carriageParm3("http://suckthis.com");
+ carriageParm_wininet0 carriageParm4("http://suckthis.com");
+
+ carriageParm_http0Ptr carriageParm_http1P(
+ new carriageParm_http0("http://suckthis.com"));
+
+ carriageParm_http1P->setBasicAuth("bryanh", "12345");
+
+ carriageParm_curl0Ptr carriageParm_curl1P(
+ new carriageParm_curl0("http://suckthis.com"));
+
+ carriageParm_curl1P->setBasicAuth("bryanh", "12345");
+
+ carriageParm_curl1P->setUser("bryanh", "12345");
+ carriageParm_curl1P->allowAuthBasic();
+ carriageParm_curl1P->disallowAuthBasic();
+ carriageParm_curl1P->allowAuthDigest();
+ carriageParm_curl1P->disallowAuthDigest();
+ carriageParm_curl1P->allowAuthNegotiate();
+ carriageParm_curl1P->disallowAuthNegotiate();
+ carriageParm_curl1P->allowAuthNtlm();
+ carriageParm_curl1P->disallowAuthNtlm();
+
+ carriageParm_libwww0Ptr carriageParm_libwww1P(
+ new carriageParm_libwww0("http://suckthis.com"));
+
+ carriageParm_libwww1P->setUser("bryanh", "12345");
+ carriageParm_libwww1P->allowAuthBasic();
+
+ carriageParm_wininet0Ptr carriageParm_wininet1P(
+ new carriageParm_wininet0("http://suckthis.com"));
+
+ carriageParm_wininet1P->setUser("bryanh", "12345");
+ carriageParm_wininet1P->allowAuthBasic();
+ }
+};
+
+
+
+class clientRpcTestSuite : public testSuite {
+
+public:
+ virtual string suiteName() {
+ return "clientRpcTestSuite";
+ }
+ virtual void runtests(unsigned int) {
+
+ registry myRegistry;
+
+ myRegistry.addMethod("sample.add", methodPtr(new sampleAddMethod));
+
+ carriageParm_direct carriageParm0(&myRegistry);
+ clientXmlTransport_direct transportDirect;
+ client_xml client0(&transportDirect);
+ paramList paramListSampleAdd;
+ paramListSampleAdd.add(value_int(5));
+ paramListSampleAdd.add(value_int(7));
+ paramList paramListEmpty;
+
+ {
+ /* Test a successful RPC */
+ rpcPtr rpcSampleAddP("sample.add", paramListSampleAdd);
+ TEST(!rpcSampleAddP->isFinished());
+ // This fails because RPC has not been executed
+ EXPECT_ERROR(value result(rpcSampleAddP->getResult()););
+
+ rpcSampleAddP->call(&client0, &carriageParm0);
+
+ TEST(rpcSampleAddP->isFinished());
+ TEST(rpcSampleAddP->isSuccessful());
+ value_int const resultDirect(rpcSampleAddP->getResult());
+ TEST(static_cast<int>(resultDirect) == 12);
+ // This fails because the RPC succeeded
+ EXPECT_ERROR(fault fault0(rpcSampleAddP->getFault()););
+ // This fails because the RPC has already been executed
+ EXPECT_ERROR(
+ rpcSampleAddP->call(&client0, &carriageParm0););
+ // This fails because the RPC has already been executed
+ EXPECT_ERROR(
+ rpcSampleAddP->start(&client0, &carriageParm0););
+ }
+ {
+ /* Test a failed RPC */
+ rpcPtr const rpcSampleAddP("sample.add", paramListEmpty);
+ rpcSampleAddP->call(&client0, &carriageParm0);
+ TEST(rpcSampleAddP->isFinished());
+ TEST(!rpcSampleAddP->isSuccessful());
+ fault const fault0(rpcSampleAddP->getFault());
+ TEST(fault0.getCode() == fault::CODE_TYPE);
+ // This fails because the RPC failed
+ EXPECT_ERROR(value result(rpcSampleAddP->getResult()););
+ // This fails because the RPC has already been executed
+ EXPECT_ERROR(
+ rpcSampleAddP->call(&client0, &carriageParm0););
+ // This fails because the RPC has already been executed
+ EXPECT_ERROR(
+ rpcSampleAddP->start(&client0, &carriageParm0););
+ }
+ {
+ /* Test with a connection */
+
+ connection connection0(&client0, &carriageParm0);
+
+ rpcPtr const rpcSampleAddP("sample.add", paramListSampleAdd);
+
+ rpcSampleAddP->call(connection0);
+
+ TEST(rpcSampleAddP->isFinished());
+ value_int const resultDirect(rpcSampleAddP->getResult());
+ TEST(static_cast<int>(resultDirect) == 12);
+ }
+ }
+};
+
+
+
+class clientPtrTestSuite : public testSuite {
+
+public:
+ virtual string suiteName() {
+ return "clientPtrTestSuite";
+ }
+ virtual void runtests(unsigned int) {
+ registry myRegistry;
+
+ myRegistry.addMethod("sample.add", methodPtr(new sampleAddMethod));
+ carriageParm_direct carriageParmDirect(&myRegistry);
+ clientXmlTransport_direct transportDirect;
+
+ clientPtr clientP(new client_xml(&transportDirect));
+
+ clientPtr client2P(clientP);
+
+ {
+ clientPtr client3P;
+ client3P = client2P;
+ }
+ rpcOutcome outcome;
+
+ clientP->call(&carriageParmDirect, "nosuchmethod",
+ paramList(), &outcome);
+ TEST(!outcome.succeeded());
+ TEST(outcome.getFault().getCode() == fault::CODE_NO_SUCH_METHOD);
+ }
+};
+
+
+
+class serverAccessorTestSuite : public testSuite {
+
+public:
+ virtual string suiteName() {
+ return "serverAccessorTestSuite";
+ }
+ virtual void runtests(unsigned int) {
+ clientXmlTransportPtr const transportP(new clientXmlTransport_direct);
+ clientPtr const clientP(new client_xml(transportP));
+ registry myRegistry;
+ carriageParmPtr const carriageParmP(
+ new carriageParm_direct(&myRegistry));
+
+ serverAccessor server1(clientP, carriageParmP);
+
+ rpcOutcome outcome;
+ server1.call("nosuchmethod", paramList(), &outcome);
+ TEST(!outcome.succeeded());
+ TEST(outcome.getFault().getCode() == fault::CODE_NO_SUCH_METHOD);
+ TEST(outcome.getFault().getDescription().size() > 0);
+ }
+};
+
+
+
+class xmlTestSuite : public testSuite {
+/*----------------------------------------------------------------------------
+ This test suite tests the generation an interpretation of XML-RPC
+ XML, by doing RPCs via an XML client and server. Each complete RPC
+ involves generating XML and interpreting it, so this is a handy way
+ to test.
+
+ A stronger test would be to make an XML transport that actually verifies
+ the XML. We're too lazy for that.
+-----------------------------------------------------------------------------*/
+public:
+ virtual string suiteName() {
+ return "xmlTestSuite";
+ }
+ virtual void runtests(unsigned int) {
+ registry myRegistry;
+ myRegistry.addMethod("sample.add", methodPtr(new sampleAddMethod));
+ myRegistry.addMethod("apache", methodPtr(new testApacheDialectMethod));
+ carriageParm_direct carriageParmDirect(&myRegistry);
+ clientXmlTransport_direct transportDirect;
+ client_xml clientDirect(&transportDirect, xmlrpc_dialect_apache);
+
+ paramList paramListSampleAdd;
+ paramListSampleAdd.add(value_int(5));
+ paramListSampleAdd.add(value_int(7));
+
+ {
+ rpcPtr rpcSampleAddP("sample.add", paramListSampleAdd);
+ rpcSampleAddP->call(&clientDirect, &carriageParmDirect);
+ TEST(rpcSampleAddP->isFinished());
+ TEST(rpcSampleAddP->isSuccessful());
+ value_int const result(rpcSampleAddP->getResult());
+ TEST(static_cast<int>(result) == 12);
+ }
+ paramList paramListApache;
+ paramListApache.add(value_nil());
+
+ {
+ rpcPtr rpcApacheP("apache", paramListApache);
+ rpcApacheP->call(&clientDirect, &carriageParmDirect);
+ TEST(rpcApacheP->isFinished());
+ TEST(rpcApacheP->isSuccessful());
+ value_i8 const result(rpcApacheP->getResult());
+ TEST(static_cast<xmlrpc_int64>(result) == 7ll);
+ }
+ }
+};
+
+
+
+string
+clientTestSuite::suiteName() {
+ return "clientTestSuite";
+}
+
+
+
+void
+clientTestSuite::runtests(unsigned int const indentation) {
+
+ clientDirectTestSuite().run(indentation+1);
+
+ clientXmlTransportTestSuite().run(indentation+1);
+
+ carriageParmTestSuite().run(indentation+1);
+
+ clientCurlTestSuite().run(indentation+1);
+
+ clientRpcTestSuite().run(indentation+1);
+
+ clientPtrTestSuite().run(indentation+1);
+
+ clientSimpleTestSuite().run(indentation+1);
+
+ serverAccessorTestSuite().run(indentation+1);
+
+ xmlTestSuite().run(indentation+1);
+}
Added: freeswitch/trunk/libs/xmlrpc-c/src/cpp/test/testclient.hpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/cpp/test/testclient.hpp Fri May 23 16:56:24 2008
@@ -0,0 +1,9 @@
+#include "tools.hpp"
+
+class clientTestSuite : public testSuite {
+
+public:
+ virtual std::string suiteName();
+ virtual void runtests(unsigned int const indentation);
+};
+
Added: freeswitch/trunk/libs/xmlrpc-c/src/cpp/test/testclient_dummy.cpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/cpp/test/testclient_dummy.cpp Fri May 23 16:56:24 2008
@@ -0,0 +1,29 @@
+/*=============================================================================
+ testclient_dummy
+===============================================================================
+ This is a substitute for testclient.cpp, for use in a test program that is
+ not linked with the client libraries.
+
+ It simply passes the test.
+=============================================================================*/
+
+#include <string>
+#include <iostream>
+
+#include "tools.hpp"
+#include "testclient.hpp"
+
+using namespace std;
+
+string
+clientTestSuite::suiteName() {
+ return "clientTestSuite";
+}
+
+
+void
+clientTestSuite::runtests(unsigned int const indentation) {
+
+ cout << string((indentation+1)*2, ' ')
+ << "Running dummy test." << endl;
+}
Added: freeswitch/trunk/libs/xmlrpc-c/src/cpp/test/tools.cpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/cpp/test/tools.cpp Fri May 23 16:56:24 2008
@@ -0,0 +1,64 @@
+#include <string>
+#include <sstream>
+#include <iostream>
+#include "xmlrpc-c/girerr.hpp"
+using girerr::error;
+using girerr::throwf;
+
+#include "tools.hpp"
+
+using namespace std;
+
+testSuite::~testSuite() {
+}
+
+
+
+void
+testSuite::run(unsigned int const indentation) {
+ try {
+ cout << string(indentation*2, ' ')
+ << "Running " << suiteName() << endl;
+ this->runtests(indentation);
+ } catch (error const& error) {
+ throwf("%s failed. %s", suiteName().c_str(), error.what());
+ } catch (...) {
+ throw(error(suiteName() + string(" failed. ") +
+ string("It threw an unexpected type of object")));
+ }
+ cout << string(indentation*2, ' ')
+ << suiteName() << " tests passed." << endl;
+}
+
+
+
+// This is a good place to set a breakpoint.
+void
+logFailedTest(const char * const fileName,
+ unsigned int const lineNum,
+ const char * const statement) {
+
+ ostringstream msg;
+
+ msg << endl
+ << fileName << ":" << lineNum
+ << ": expected (" << statement << ")" << endl;
+
+ throw(error(msg.str()));
+}
+
+
+error
+fileLineError(string const filename,
+ unsigned int const lineNumber,
+ string const description) {
+
+ ostringstream combined;
+
+ combined << filename << ":" << lineNumber << " " << description;
+
+ return error(combined.str());
+}
+
+
+
Added: freeswitch/trunk/libs/xmlrpc-c/src/cpp/test/tools.hpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/cpp/test/tools.hpp Fri May 23 16:56:24 2008
@@ -0,0 +1,72 @@
+#ifndef TEST_HPP_INCLUDED
+#define TEST_HPP_INCLUDED
+
+#include <string>
+
+#include "xmlrpc-c/girerr.hpp"
+using girerr::error;
+
+class testSuite {
+/*----------------------------------------------------------------------------
+ This is a base class for a test suite. Give the suite a name
+ (to be used in messages about it) and some test code via
+ virtual methods suiteName() and runtests(), respectively.
+
+ runtests() should throw either an 'error' object or an 'XmlRpcFault'
+ object if the test fails. It should throw something else if the
+ test can't run. It should throw nothing if the tests pass.
+
+ You don't normally keep an object of this class around. You don't
+ even give it a name. You simply refer to a literal object, like so:
+
+ myTestSuite().run(0)
+-----------------------------------------------------------------------------*/
+public:
+ virtual ~testSuite();
+
+ void run(unsigned int const indentation);
+
+ virtual void runtests(unsigned int const) {
+ throw(error("test suite does not have a runtests() method"));
+ };
+ virtual std::string suiteName() {
+ return "unnamed test suite";
+ }
+};
+
+
+
+void
+logFailedTest(const char * const fileName,
+ unsigned int const lineNum,
+ const char * const statement);
+
+error
+fileLineError(std::string const filename,
+ unsigned int const lineNumber,
+ std::string const description);
+
+#define TEST(statement) \
+ do { \
+ if (!(statement)) \
+ logFailedTest(__FILE__, __LINE__, #statement); \
+ } while (0)
+
+
+#define TEST_PASSED() \
+ do { } while (0)
+
+#define TEST_FAILED(reason) \
+ do { \
+ logFailedTest(__FILE__, __LINE__, (reason)); \
+ } while (0)
+
+#define EXPECT_ERROR(statement) \
+ do { try { statement } catch (error) {break;} \
+ throw(fileLineError(__FILE__, __LINE__, "Expected error; didn't get one")); \
+ } while (0)
+
+#define trickToStraightenOutEmacsIndentation \
+;
+
+#endif
Modified: freeswitch/trunk/libs/xmlrpc-c/src/cpp/value.cpp
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/src/cpp/value.cpp (original)
+++ freeswitch/trunk/libs/xmlrpc-c/src/cpp/value.cpp Fri May 23 16:56:24 2008
@@ -1,9 +1,9 @@
/*****************************************************************************
- xmlrpc_value.cpp
+ value.cpp
******************************************************************************
- This module provides services for dealwith XML-RPC values. Each type
- of XML-RPC value is a C++ class. An object represents a particular
- XML-RPC value.
+ This module provides services for dealing with XML-RPC values. Each
+ type of XML-RPC value is a C++ class. An object represents a
+ particular XML-RPC value.
Everything is based on the C services in libxmlrpc.
@@ -25,34 +25,44 @@
class members had to be declared public so that other components of
the library could see them, but the user is not supposed to access
those members.
-
*****************************************************************************/
+#include <cstdlib>
#include <string>
#include <vector>
-#include <time.h>
+#include <ctime>
#include "xmlrpc-c/girerr.hpp"
using girerr::error;
#include "xmlrpc-c/base.h"
#include "xmlrpc-c/base_int.h"
+#include "env_wrap.hpp"
+
#include "xmlrpc-c/base.hpp"
using namespace std;
+using namespace xmlrpc_c;
namespace {
+void
+throwIfError(env_wrap const& env) {
+
+ if (env.env_c.fault_occurred)
+ throw(error(env.env_c.fault_string));
+}
+
+
+
class cDatetimeValueWrapper {
public:
xmlrpc_value * valueP;
cDatetimeValueWrapper(time_t const cppvalue) {
- xmlrpc_env env;
- xmlrpc_env_init(&env);
+ env_wrap env;
- this->valueP = xmlrpc_datetime_new_sec(&env, cppvalue);
- if (env.fault_occurred)
- throw(error(env.fault_string));
+ this->valueP = xmlrpc_datetime_new_sec(&env.env_c, cppvalue);
+ throwIfError(env);
}
~cDatetimeValueWrapper() {
xmlrpc_DECREF(this->valueP);
@@ -65,18 +75,17 @@
const char * str;
size_t length;
cStringWrapper(xmlrpc_value * valueP) {
- xmlrpc_env env;
- xmlrpc_env_init(&env);
+ env_wrap env;
- xmlrpc_read_string_lp(&env, valueP, &length, &str);
- if (env.fault_occurred)
- throw(error(env.fault_string));
+ xmlrpc_read_string_lp(&env.env_c, valueP, &length, &str);
+ throwIfError(env);
}
~cStringWrapper() {
free((char*)str);
}
};
-
+
+
} // namespace
@@ -123,6 +132,17 @@
+bool
+value::isInstantiated() const {
+/*----------------------------------------------------------------------------
+ Return whether the value is actually a value, as opposed to a placeholder
+ variable waiting to be assigned a value.
+-----------------------------------------------------------------------------*/
+ return (this->cValueP != NULL);
+}
+
+
+
void
value::instantiate(xmlrpc_value * const valueP) {
@@ -148,13 +168,11 @@
/*----------------------------------------------------------------------------
Append this value to the C array 'arrayP'.
----------------------------------------------------------------------------*/
- xmlrpc_env env;
- xmlrpc_env_init(&env);
+ env_wrap env;
- xmlrpc_array_append_item(&env, arrayP, this->cValueP);
-
- if (env.fault_occurred)
- throw(error(env.fault_string));
+ xmlrpc_array_append_item(&env.env_c, arrayP, this->cValueP);
+
+ throwIfError(env);
}
@@ -165,15 +183,13 @@
/*----------------------------------------------------------------------------
Add this value to the C array 'arrayP' with key 'key'.
----------------------------------------------------------------------------*/
- xmlrpc_env env;
- xmlrpc_env_init(&env);
+ env_wrap env;
- xmlrpc_struct_set_value_n(&env, structP,
+ xmlrpc_struct_set_value_n(&env.env_c, structP,
key.c_str(), key.length(),
this->cValueP);
- if (env.fault_occurred)
- throw(error(env.fault_string));
+ throwIfError(env);
}
@@ -203,12 +219,10 @@
xmlrpc_value * valueP;
cWrapper(int const cppvalue) {
- xmlrpc_env env;
- xmlrpc_env_init(&env);
+ env_wrap env;
- this->valueP = xmlrpc_int_new(&env, cppvalue);
- if (env.fault_occurred)
- throw(error(env.fault_string));
+ this->valueP = xmlrpc_int_new(&env.env_c, cppvalue);
+ throwIfError(env);
}
~cWrapper() {
xmlrpc_DECREF(this->valueP);
@@ -236,13 +250,10 @@
value_int::operator int() const {
int retval;
+ env_wrap env;
- xmlrpc_env env;
- xmlrpc_env_init(&env);
-
- xmlrpc_read_int(&env, this->cValueP, &retval);
- if (env.fault_occurred)
- throw(error(env.fault_string));
+ xmlrpc_read_int(&env.env_c, this->cValueP, &retval);
+ throwIfError(env);
return retval;
}
@@ -256,12 +267,10 @@
xmlrpc_value * valueP;
cWrapper(double const cppvalue) {
- xmlrpc_env env;
- xmlrpc_env_init(&env);
+ env_wrap env;
- this->valueP = xmlrpc_double_new(&env, cppvalue);
- if (env.fault_occurred)
- throw(error(env.fault_string));
+ this->valueP = xmlrpc_double_new(&env.env_c, cppvalue);
+ throwIfError(env);
}
~cWrapper() {
xmlrpc_DECREF(this->valueP);
@@ -288,12 +297,10 @@
double retval;
- xmlrpc_env env;
- xmlrpc_env_init(&env);
+ env_wrap env;
- xmlrpc_read_double(&env, this->cValueP, &retval);
- if (env.fault_occurred)
- throw(error(env.fault_string));
+ xmlrpc_read_double(&env.env_c, this->cValueP, &retval);
+ throwIfError(env);
return retval;
}
@@ -307,12 +314,10 @@
xmlrpc_value * valueP;
cWrapper(xmlrpc_bool const cppvalue) {
- xmlrpc_env env;
- xmlrpc_env_init(&env);
+ env_wrap env;
- this->valueP = xmlrpc_bool_new(&env, cppvalue);
- if (env.fault_occurred)
- throw(error(env.fault_string));
+ this->valueP = xmlrpc_bool_new(&env.env_c, cppvalue);
+ throwIfError(env);
}
~cWrapper() {
xmlrpc_DECREF(this->valueP);
@@ -330,14 +335,12 @@
xmlrpc_bool retval;
- xmlrpc_env env;
- xmlrpc_env_init(&env);
+ env_wrap env;
- xmlrpc_read_bool(&env, this->cValueP, &retval);
- if (env.fault_occurred)
- throw(error(env.fault_string));
+ xmlrpc_read_bool(&env.env_c, this->cValueP, &retval);
+ throwIfError(env);
- return (bool)retval;
+ return (retval != false);
}
@@ -360,12 +363,11 @@
xmlrpc_value * valueP;
cWrapper(string const cppvalue) {
- xmlrpc_env env;
- xmlrpc_env_init(&env);
+ env_wrap env;
- this->valueP = xmlrpc_datetime_new_str(&env, cppvalue.c_str());
- if (env.fault_occurred)
- throw(error(env.fault_string));
+ this->valueP = xmlrpc_datetime_new_str(&env.env_c,
+ cppvalue.c_str());
+ throwIfError(env);
}
~cWrapper() {
xmlrpc_DECREF(this->valueP);
@@ -388,21 +390,25 @@
+#if XMLRPC_HAVE_TIMEVAL
value_datetime::value_datetime(struct timeval const& cppvalue) {
cDatetimeValueWrapper wrapper(cppvalue.tv_sec);
this->instantiate(wrapper.valueP);
}
+#endif
+#if XMLRPC_HAVE_TIMESPEC
value_datetime::value_datetime(struct timespec const& cppvalue) {
cDatetimeValueWrapper wrapper(cppvalue.tv_sec);
this->instantiate(wrapper.valueP);
}
+#endif
@@ -420,45 +426,68 @@
value_datetime::operator time_t() const {
time_t retval;
+ env_wrap env;
- xmlrpc_env env;
- xmlrpc_env_init(&env);
-
- xmlrpc_read_datetime_sec(&env, this->cValueP, &retval);
- if (env.fault_occurred)
- throw(error(env.fault_string));
+ xmlrpc_read_datetime_sec(&env.env_c, this->cValueP, &retval);
+ throwIfError(env);
return retval;
}
-value_string::value_string(string const& cppvalue) {
-
- class cWrapper {
- public:
- xmlrpc_value * valueP;
+class cNewStringWrapper {
+public:
+ xmlrpc_value * valueP;
- cWrapper(string const cppvalue) {
- xmlrpc_env env;
- xmlrpc_env_init(&env);
+ cNewStringWrapper(string const cppvalue,
+ value_string::nlCode const nlCode) {
+ env_wrap env;
- this->valueP = xmlrpc_string_new(&env, cppvalue.c_str());
- if (env.fault_occurred)
- throw(error(env.fault_string));
- }
- ~cWrapper() {
- xmlrpc_DECREF(this->valueP);
+ switch (nlCode) {
+ case value_string::nlCode_all:
+ this->valueP = xmlrpc_string_new_lp(&env.env_c,
+ cppvalue.length(),
+ cppvalue.c_str());
+ break;
+ case value_string::nlCode_lf:
+ this->valueP = xmlrpc_string_new_lp_cr(&env.env_c,
+ cppvalue.length(),
+ cppvalue.c_str());
+ break;
+ default:
+ throw(error("Newline encoding argument to value_string "
+ "constructor is not one of the defined "
+ "enumerations of value_string::nlCode"));
}
- };
+ throwIfError(env);
+ }
+ ~cNewStringWrapper() {
+ xmlrpc_DECREF(this->valueP);
+ }
+};
- cWrapper wrapper(cppvalue);
+
+
+value_string::value_string(std::string const& cppvalue,
+ value_string::nlCode const nlCode) {
+
+ cNewStringWrapper wrapper(cppvalue, nlCode);
this->instantiate(wrapper.valueP);
}
+value_string::value_string(std::string const& cppvalue) {
+
+ cNewStringWrapper wrapper(cppvalue, nlCode_all);
+
+ this->instantiate(wrapper.valueP);
+}
+
+
+
value_string::value_string(xmlrpc_c::value const baseValue) {
if (baseValue.type() != xmlrpc_c::value::TYPE_STRING)
@@ -470,10 +499,34 @@
+std::string
+value_string::crlfValue() const {
+
+ class cWrapper {
+ public:
+ const char * str;
+ size_t length;
+ cWrapper(xmlrpc_value * valueP) {
+ env_wrap env;
+
+ xmlrpc_read_string_lp_crlf(&env.env_c, valueP, &length, &str);
+ throwIfError(env);
+ }
+ ~cWrapper() {
+ free((char*)str);
+ }
+ };
+
+ cWrapper wrapper(this->cValueP);
+
+ return string(wrapper.str, wrapper.length);
+}
+
+
+
value_string::operator string() const {
- xmlrpc_env env;
- xmlrpc_env_init(&env);
+ env_wrap env;
cStringWrapper adapter(this->cValueP);
@@ -490,13 +543,11 @@
xmlrpc_value * valueP;
cWrapper(vector<unsigned char> const& cppvalue) {
- xmlrpc_env env;
- xmlrpc_env_init(&env);
+ env_wrap env;
this->valueP =
- xmlrpc_base64_new(&env, cppvalue.size(), &cppvalue[0]);
- if (env.fault_occurred)
- throw(error(env.fault_string));
+ xmlrpc_base64_new(&env.env_c, cppvalue.size(), &cppvalue[0]);
+ throwIfError(env);
}
~cWrapper() {
xmlrpc_DECREF(this->valueP);
@@ -519,12 +570,10 @@
size_t length;
cWrapper(xmlrpc_value * const valueP) {
- xmlrpc_env env;
- xmlrpc_env_init(&env);
+ env_wrap env;
- xmlrpc_read_base64(&env, valueP, &length, &contents);
- if (env.fault_occurred)
- throw(error(env.fault_string));
+ xmlrpc_read_base64(&env.env_c, valueP, &length, &contents);
+ throwIfError(env);
}
~cWrapper() {
free((void*)contents);
@@ -542,13 +591,11 @@
size_t
value_bytestring::length() const {
- xmlrpc_env env;
- xmlrpc_env_init(&env);
-
+ env_wrap env;
size_t length;
- xmlrpc_read_base64_size(&env, this->cValueP, &length);
- if (env.fault_occurred)
- throw(error(env.fault_string));
+
+ xmlrpc_read_base64_size(&env.env_c, this->cValueP, &length);
+ throwIfError(env);
return length;
}
@@ -573,12 +620,10 @@
xmlrpc_value * valueP;
cWrapper() {
- xmlrpc_env env;
- xmlrpc_env_init(&env);
+ env_wrap env;
- this->valueP = xmlrpc_array_new(&env);
- if (env.fault_occurred)
- throw(error(env.fault_string));
+ this->valueP = xmlrpc_array_new(&env.env_c);
+ throwIfError(env);
}
~cWrapper() {
xmlrpc_DECREF(this->valueP);
@@ -610,14 +655,12 @@
vector<xmlrpc_c::value>
value_array::vectorValueValue() const {
- xmlrpc_env env;
- xmlrpc_env_init(&env);
+ env_wrap env;
unsigned int arraySize;
- arraySize = xmlrpc_array_size(&env, this->cValueP);
- if (env.fault_occurred)
- throw(error(env.fault_string));
+ arraySize = xmlrpc_array_size(&env.env_c, this->cValueP);
+ throwIfError(env);
vector<xmlrpc_c::value> retval(arraySize);
@@ -629,14 +672,11 @@
cWrapper(xmlrpc_value * const arrayP,
unsigned int const index) {
+ env_wrap env;
- xmlrpc_env env;
- xmlrpc_env_init(&env);
-
- xmlrpc_array_read_item(&env, arrayP, index, &valueP);
+ xmlrpc_array_read_item(&env.env_c, arrayP, index, &valueP);
- if (env.fault_occurred)
- throw(error(env.fault_string));
+ throwIfError(env);
}
~cWrapper() {
xmlrpc_DECREF(valueP);
@@ -656,14 +696,11 @@
size_t
value_array::size() const {
- xmlrpc_env env;
- xmlrpc_env_init(&env);
-
+ env_wrap env;
unsigned int arraySize;
- arraySize = xmlrpc_array_size(&env, this->cValueP);
- if (env.fault_occurred)
- throw(error(env.fault_string));
+ arraySize = xmlrpc_array_size(&env.env_c, this->cValueP);
+ throwIfError(env);
return arraySize;
}
@@ -678,12 +715,10 @@
xmlrpc_value * valueP;
cWrapper() {
- xmlrpc_env env;
- xmlrpc_env_init(&env);
+ env_wrap env;
- this->valueP = xmlrpc_struct_new(&env);
- if (env.fault_occurred)
- throw(error(env.fault_string));
+ this->valueP = xmlrpc_struct_new(&env.env_c);
+ throwIfError(env);
}
~cWrapper() {
xmlrpc_DECREF(this->valueP);
@@ -717,14 +752,11 @@
value_struct::operator map<string, xmlrpc_c::value>() const {
- xmlrpc_env env;
- xmlrpc_env_init(&env);
-
+ env_wrap env;
unsigned int structSize;
- structSize = xmlrpc_struct_size(&env, this->cValueP);
- if (env.fault_occurred)
- throw(error(env.fault_string));
+ structSize = xmlrpc_struct_size(&env.env_c, this->cValueP);
+ throwIfError(env);
map<string, xmlrpc_c::value> retval;
@@ -737,14 +769,12 @@
cMemberWrapper(xmlrpc_value * const structP,
unsigned int const index) {
- xmlrpc_env env;
- xmlrpc_env_init(&env);
+ env_wrap env;
- xmlrpc_struct_read_member(&env, structP, index,
+ xmlrpc_struct_read_member(&env.env_c, structP, index,
&keyP, &valueP);
- if (env.fault_occurred)
- throw(error(env.fault_string));
+ throwIfError(env);
}
~cMemberWrapper() {
xmlrpc_DECREF(keyP);
@@ -773,12 +803,10 @@
xmlrpc_value * valueP;
cWrapper() {
- xmlrpc_env env;
- xmlrpc_env_init(&env);
+ env_wrap env;
- this->valueP = xmlrpc_nil_new(&env);
- if (env.fault_occurred)
- throw(error(env.fault_string));
+ this->valueP = xmlrpc_nil_new(&env.env_c);
+ throwIfError(env);
}
~cWrapper() {
xmlrpc_DECREF(this->valueP);
@@ -803,5 +831,52 @@
-} // namespace
+value_i8::value_i8(xmlrpc_int64 const cppvalue) {
+ class cWrapper {
+ public:
+ xmlrpc_value * valueP;
+
+ cWrapper(xmlrpc_int64 const cppvalue) {
+ env_wrap env;
+
+ this->valueP = xmlrpc_i8_new(&env.env_c, cppvalue);
+ throwIfError(env);
+ }
+ ~cWrapper() {
+ xmlrpc_DECREF(this->valueP);
+ }
+ };
+
+ cWrapper wrapper(cppvalue);
+
+ this->instantiate(wrapper.valueP);
+}
+
+
+
+value_i8::value_i8(xmlrpc_c::value const baseValue) {
+
+ if (baseValue.type() != xmlrpc_c::value::TYPE_I8)
+ throw(error("Not 64 bit integer type. See type() method"));
+ else {
+ this->instantiate(baseValue.cValueP);
+ }
+}
+
+
+
+value_i8::operator xmlrpc_int64() const {
+
+ xmlrpc_int64 retval;
+ env_wrap env;
+
+ xmlrpc_read_i8(&env.env_c, this->cValueP, &retval);
+ throwIfError(env);
+
+ return retval;
+}
+
+
+
+} // namespace
Added: freeswitch/trunk/libs/xmlrpc-c/src/cpp/wininet.cpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/cpp/wininet.cpp Fri May 23 16:56:24 2008
@@ -0,0 +1,166 @@
+/*=============================================================================
+ wininet.cpp
+===============================================================================
+ This is the Wininet XML transport of the C++ XML-RPC client library for
+ Xmlrpc-c.
+=============================================================================*/
+
+#include <stdlib.h>
+#include <cassert>
+#include <string>
+
+#include "xmlrpc-c/girerr.hpp"
+using girerr::error;
+using girerr::throwf;
+#include "xmlrpc-c/girmem.hpp"
+using girmem::autoObjectPtr;
+using girmem::autoObject;
+#include "env_wrap.hpp"
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/client.h"
+#include "xmlrpc-c/transport.h"
+#include "xmlrpc-c/base_int.h"
+
+/* transport_config.h defines MUST_BUILD_WININET_CLIENT */
+#include "transport_config.h"
+
+#include "xmlrpc-c/client_transport.hpp"
+
+
+using namespace std;
+using namespace xmlrpc_c;
+
+
+namespace {
+
+class globalConstant {
+public:
+ globalConstant();
+ ~globalConstant();
+};
+
+
+
+globalConstant::globalConstant() {
+
+ // Not thread safe
+
+ xmlrpc_transport_setup setupFn;
+
+#if MUST_BUILD_WININET_CLIENT
+ setupFn = xmlrpc_wininet_transport_ops.setup_global_const;
+#else
+ setupFn = NULL;
+#endif
+ if (setupFn) {
+ env_wrap env;
+
+ setupFn(&env.env_c); // Not thread safe
+
+ if (env.env_c.fault_occurred)
+ throwf("Failed to do global initialization "
+ "of Wininet transport code. %s", env.env_c.fault_string);
+ }
+}
+
+
+
+globalConstant::~globalConstant() {
+
+ // Not thread safe
+
+ xmlrpc_transport_teardown teardownFn;
+
+#if MUST_BUILD_WININET_CLIENT
+ teardownFn = xmlrpc_wininet_transport_ops.teardown_global_const;
+#else
+ teardownFn = NULL;
+#endif
+ if (teardownFn)
+ teardownFn(); // not thread safe
+}
+
+
+
+globalConstant globalConst;
+ // This object is never accessed. Its whole purpose to to be born and
+ // to die, which it does automatically as part of C++ program
+ // program initialization and termination.
+
+} // namespace
+
+
+namespace xmlrpc_c {
+
+carriageParm_wininet0::carriageParm_wininet0(
+ string const serverUrl
+ ) {
+
+ this->instantiate(serverUrl);
+}
+
+
+
+carriageParm_wininet0Ptr::carriageParm_wininet0Ptr() {
+ // Base class constructor will construct pointer that points to nothing
+}
+
+
+
+carriageParm_wininet0Ptr::carriageParm_wininet0Ptr(
+ carriageParm_wininet0 * const carriageParmP) {
+ this->point(carriageParmP);
+}
+
+
+
+carriageParm_wininet0 *
+carriageParm_wininet0Ptr::operator->() const {
+
+ autoObject * const p(this->objectP);
+ return dynamic_cast<carriageParm_wininet0 *>(p);
+}
+
+
+
+#if MUST_BUILD_WININET_CLIENT
+
+clientXmlTransport_wininet::clientXmlTransport_wininet(
+ bool const allowInvalidSslCerts
+ ) {
+
+ struct xmlrpc_wininet_xportparms transportParms;
+
+ transportParms.allowInvalidSSLCerts = allowInvalidSslCerts;
+
+ this->c_transportOpsP = &xmlrpc_wininet_transport_ops;
+
+ env_wrap env;
+
+ xmlrpc_wininet_transport_ops.create(
+ &env.env_c, 0, "", "",
+ &transportParms, XMLRPC_WXPSIZE(allowInvalidSSLCerts),
+ &this->c_transportP);
+
+ if (env.env_c.fault_occurred)
+ throw(error(env.env_c.fault_string));
+}
+
+#else // MUST_BUILD_WININET_CLIENT
+
+clientXmlTransport_wininet::clientXmlTransport_wininet(bool const) {
+
+ throw(error("There is no Wininet client XML transport "
+ "in this XML-RPC client library"));
+}
+
+#endif
+
+
+
+clientXmlTransport_wininet::~clientXmlTransport_wininet() {
+
+ this->c_transportOpsP->destroy(this->c_transportP);
+}
+
+} // namespace
Modified: freeswitch/trunk/libs/xmlrpc-c/src/cpp/xml.cpp
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/src/cpp/xml.cpp (original)
+++ freeswitch/trunk/libs/xmlrpc-c/src/cpp/xml.cpp Fri May 23 16:56:24 2008
@@ -2,9 +2,13 @@
#include "xmlrpc-c/girerr.hpp"
using girerr::error;
+using girerr::throwf;
#include "xmlrpc-c/base.h"
#include "xmlrpc-c/base_int.h"
+#include "xmlrpc-c/string_int.h"
#include "xmlrpc-c/base.hpp"
+#include "env_wrap.hpp"
+
#include "xmlrpc-c/xml.hpp"
using namespace std;
@@ -28,25 +32,23 @@
xmlrpc_value *
cArrayFromParamList(paramList const& paramList) {
- xmlrpc_env env;
-
- xmlrpc_env_init(&env);
+ env_wrap env;
xmlrpc_value * paramArrayP;
- paramArrayP = xmlrpc_array_new(&env);
- if (!env.fault_occurred) {
+ paramArrayP = xmlrpc_array_new(&env.env_c);
+ if (!env.env_c.fault_occurred) {
for (unsigned int i = 0;
- i < paramList.size() && !env.fault_occurred;
+ i < paramList.size() && !env.env_c.fault_occurred;
++i) {
cValueWrapper const param(paramList[i].cValue());
- xmlrpc_array_append_item(&env, paramArrayP, param.valueP);
+ xmlrpc_array_append_item(&env.env_c, paramArrayP, param.valueP);
}
}
- if (env.fault_occurred) {
+ if (env.env_c.fault_occurred) {
xmlrpc_DECREF(paramArrayP);
- throw(error(env.fault_string));
+ throw(error(env.env_c.fault_string));
}
return paramArrayP;
}
@@ -59,12 +61,15 @@
void
-generateCall(string const& methodName,
- paramList const& paramList,
- string * const callXmlP) {
+generateCall(string const& methodName,
+ paramList const& paramList,
+ xmlrpc_dialect const dialect,
+ string * const callXmlP) {
/*----------------------------------------------------------------------------
Generate the XML for an XML-RPC call, given a method name and parameter
list.
+
+ Use dialect 'dialect' of XML-RPC.
-----------------------------------------------------------------------------*/
class memblockWrapper {
xmlrpc_mem_block * const memblockP;
@@ -78,27 +83,36 @@
};
xmlrpc_mem_block * callXmlMP;
- xmlrpc_env env;
-
- xmlrpc_env_init(&env);
+ env_wrap env;
- callXmlMP = XMLRPC_MEMBLOCK_NEW(char, &env, 0);
- if (!env.fault_occurred) {
+ callXmlMP = XMLRPC_MEMBLOCK_NEW(char, &env.env_c, 0);
+ if (!env.env_c.fault_occurred) {
memblockWrapper callXmlHolder(callXmlMP);
// Makes callXmlMP get freed at end of scope
xmlrpc_value * const paramArrayP(cArrayFromParamList(paramList));
- xmlrpc_serialize_call(&env, callXmlMP, methodName.c_str(),
- paramArrayP);
+ xmlrpc_serialize_call2(&env.env_c, callXmlMP, methodName.c_str(),
+ paramArrayP, dialect);
*callXmlP = string(XMLRPC_MEMBLOCK_CONTENTS(char, callXmlMP),
XMLRPC_MEMBLOCK_SIZE(char, callXmlMP));
xmlrpc_DECREF(paramArrayP);
}
- if (env.fault_occurred)
- throw(error(env.fault_string));
+ if (env.env_c.fault_occurred)
+ throw(error(env.env_c.fault_string));
+}
+
+
+
+void
+generateCall(string const& methodName,
+ paramList const& paramList,
+ string * const callXmlP) {
+
+ generateCall(methodName, paramList, xmlrpc_dialect_i8, callXmlP);
+
}
@@ -109,27 +123,29 @@
/*----------------------------------------------------------------------------
Parse the XML for an XML-RPC response into an XML-RPC result value.
-----------------------------------------------------------------------------*/
- xmlrpc_env env;
-
- xmlrpc_env_init(&env);
+ env_wrap env;
xmlrpc_value * c_resultP;
+ int faultCode;
+ const char * faultString;
- c_resultP =
- xmlrpc_parse_response(&env, responseXml.c_str(), responseXml.size());
+ xmlrpc_parse_response2(&env.env_c, responseXml.c_str(), responseXml.size(),
+ &c_resultP, &faultCode, &faultString);
- /* Unfortunately, xmlrpc_parse_response() does not distinguish between
- unparseable XML and XML that cleanly indicates an RPC failure or
- other failure on the server end. We'll fix that some day, but for
- now, we just assume any failure is an XML-RPC RPC failure.
- */
- if (env.fault_occurred)
- *outcomeP =
- rpcOutcome(fault(env.fault_string,
- static_cast<fault::code_t>(env.fault_code)));
+ if (env.env_c.fault_occurred)
+ throwf("Unable to find XML-RPC response in what server sent back. %s",
+ env.env_c.fault_string);
else {
- *outcomeP = rpcOutcome(value(c_resultP));
- xmlrpc_DECREF(c_resultP);
+ if (faultString) {
+ *outcomeP =
+ rpcOutcome(fault(faultString,
+ static_cast<fault::code_t>(faultCode)));
+ xmlrpc_strfree(faultString);
+ } else {
+ XMLRPC_ASSERT_VALUE_OK(c_resultP);
+ *outcomeP = rpcOutcome(value(c_resultP));
+ xmlrpc_DECREF(c_resultP);
+ }
}
}
@@ -147,7 +163,8 @@
parseResponse(responseXml, &outcome);
if (!outcome.succeeded())
- throw(error("RPC failed. " + outcome.getFault().getDescription()));
+ throwf("RPC response indicates it failed. %s",
+ outcome.getFault().getDescription().c_str());
*resultP = outcome.getResult();
}
Added: freeswitch/trunk/libs/xmlrpc-c/src/double.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/double.c Fri May 23 16:56:24 2008
@@ -0,0 +1,215 @@
+#include <assert.h>
+#include <stdlib.h>
+#include <float.h>
+
+#include "xmlrpc-c/util.h"
+
+#include "double.h"
+
+typedef struct {
+ char * bytes;
+ char * next;
+ char * end;
+} buffer;
+
+
+static void
+bufferInit(buffer * const bufferP) {
+
+ unsigned int const initialSize = 64;
+
+ bufferP->bytes = malloc(initialSize);
+
+ if (bufferP->bytes) {
+ bufferP->next = bufferP->bytes;
+ bufferP->end = bufferP->bytes + initialSize;
+ }
+}
+
+
+
+static void
+bufferConcat(buffer * const bufferP,
+ char const newChar) {
+
+ if (bufferP->bytes) {
+ if (bufferP->next >= bufferP->end) {
+ unsigned int const oldSize = bufferP->end - bufferP->bytes;
+ unsigned int const newSize = oldSize + 64;
+ bufferP->bytes = realloc(bufferP->bytes, newSize);
+ bufferP->next = bufferP->bytes + oldSize;
+ bufferP->end = bufferP->bytes + newSize;
+ }
+
+ if (bufferP->bytes)
+ *(bufferP->next++) = newChar;
+ }
+}
+
+
+
+static char
+digitChar(unsigned int const digitValue) {
+
+ assert(digitValue < 10);
+
+ return '0' + digitValue;
+}
+
+
+
+static void
+floatWhole(double const value,
+ buffer * const formattedP,
+ double * const formattedAmountP,
+ double * const precisionP) {
+
+ if (value < 1.0) {
+ /* No digits to add to the whole part */
+ *formattedAmountP = 0;
+ *precisionP = DBL_EPSILON;
+ } else {
+ double nonLeastAmount;
+ double nonLeastPrecision;
+ unsigned int leastValue;
+
+ /* Add all digits but the least significant to *formattedP */
+
+ floatWhole(value/10.0, formattedP, &nonLeastAmount,
+ &nonLeastPrecision);
+
+ /* Add the least significant digit to *formattedP */
+
+ if (nonLeastPrecision > 0.1) {
+ /* We're down in the noise now; no point in showing any more
+ significant digits (and we couldn't if we wanted to, because
+ nonLeastPrecision * 10 might be more than 10 less than
+ 'value').
+ */
+ leastValue = 0;
+ } else
+ leastValue = (unsigned int)(value - nonLeastAmount * 10);
+
+ bufferConcat(formattedP, digitChar(leastValue));
+
+ *formattedAmountP = nonLeastAmount * 10 + leastValue;
+ *precisionP = nonLeastPrecision * 10;
+ }
+}
+
+
+
+static void
+floatFractionPart(double const value,
+ double const wholePrecision,
+ buffer * const formattedP) {
+/*----------------------------------------------------------------------------
+ Serialize the part that comes after the decimal point, assuming there
+ is something (nonzero) before the decimal point that uses up all but
+ 'wholePrecision' of the available precision.
+-----------------------------------------------------------------------------*/
+ double precision;
+ double d;
+
+ assert(value < 1.0);
+
+ for (d = value, precision = wholePrecision;
+ d > precision;
+ precision *= 10) {
+
+ unsigned int digitValue;
+
+ d *= 10;
+ digitValue = (unsigned int) d;
+
+ d -= digitValue;
+
+ assert(d < 1.0);
+
+ bufferConcat(formattedP, digitChar(digitValue));
+ }
+}
+
+
+
+static void
+floatFraction(double const value,
+ buffer * const formattedP) {
+/*----------------------------------------------------------------------------
+ Serialize the part that comes after the decimal point, assuming there
+ is nothing before the decimal point.
+-----------------------------------------------------------------------------*/
+ double precision;
+ double d;
+
+ assert(0.0 < value && value < 1.0);
+
+ /* Do the leading zeroes, which eat no precision */
+
+ for (d = value * 10; d < 1.0; d *= 10)
+ bufferConcat(formattedP, '0');
+
+ /* Now the significant digits */
+
+ precision = DBL_EPSILON;
+
+ while (d > precision) {
+ unsigned int const digitValue = (unsigned int) d;
+
+ bufferConcat(formattedP, digitChar(digitValue));
+
+ d -= digitValue;
+
+ assert(d < 1.0);
+
+ d *= 10;
+ precision *= 10;
+ }
+}
+
+
+
+void
+xmlrpc_formatFloat(xmlrpc_env * const envP,
+ double const value,
+ const char ** const formattedP) {
+
+ double absvalue;
+ buffer formatted;
+
+ bufferInit(&formatted);
+
+ if (value < 0.0) {
+ bufferConcat(&formatted, '-');
+ absvalue = - value;
+ } else
+ absvalue = value;
+
+ if (absvalue >= 1.0) {
+ double wholePart, fractionPart;
+ double wholePrecision;
+
+ floatWhole(absvalue, &formatted, &wholePart, &wholePrecision);
+
+ fractionPart = absvalue - wholePart;
+
+ if (fractionPart > wholePrecision) {
+ bufferConcat(&formatted, '.');
+
+ floatFractionPart(fractionPart, wholePrecision, &formatted);
+ }
+ } else {
+ bufferConcat(&formatted, '0');
+
+ if (absvalue > 0.0) {
+ bufferConcat(&formatted, '.');
+ floatFraction(absvalue, &formatted);
+ }
+ }
+ bufferConcat(&formatted, '\0');
+
+ if (formatted.bytes == NULL)
+ xmlrpc_faultf(envP, "Couldn't allocate memory to format %g", value);
+ else
+ *formattedP = formatted.bytes;
+}
Added: freeswitch/trunk/libs/xmlrpc-c/src/double.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/double.h Fri May 23 16:56:24 2008
@@ -0,0 +1,11 @@
+#ifndef DOUBLE_H_INCLUDED
+#define DOUBLE_H_INCLUDED
+
+#include "xmlrpc-c/util.h"
+
+void
+xmlrpc_formatFloat(xmlrpc_env * const envP,
+ double const value,
+ const char ** const formattedP);
+
+#endif
Added: freeswitch/trunk/libs/xmlrpc-c/src/method.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/method.c Fri May 23 16:56:24 2008
@@ -0,0 +1,450 @@
+/*=========================================================================
+ XML-RPC server method registry
+ Method services
+===========================================================================
+ These are the functions that implement the method objects that
+ the XML-RPC method registry uses.
+
+ By Bryan Henderson, December 2006.
+
+ Contributed to the public domain by its author.
+=========================================================================*/
+
+#include "xmlrpc_config.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "bool.h"
+#include "mallocvar.h"
+#include "xmlrpc-c/base_int.h"
+#include "xmlrpc-c/string_int.h"
+#include "xmlrpc-c/base.h"
+#include "registry.h"
+
+#include "method.h"
+
+
+static void
+signatureDestroy(struct xmlrpc_signature * const signatureP) {
+
+ if (signatureP->argList)
+ free((void*)signatureP->argList);
+
+ free(signatureP);
+}
+
+
+
+static void
+translateTypeSpecifierToName(xmlrpc_env * const envP,
+ char const typeSpecifier,
+ const char ** const typeNameP) {
+
+ switch (typeSpecifier) {
+ case 'i': *typeNameP = "int"; break;
+ case 'b': *typeNameP = "boolean"; break;
+ case 'd': *typeNameP = "double"; break;
+ case 's': *typeNameP = "string"; break;
+ case '8': *typeNameP = "dateTime.iso8601"; break;
+ case '6': *typeNameP = "base64"; break;
+ case 'S': *typeNameP = "struct"; break;
+ case 'A': *typeNameP = "array"; break;
+ case 'n': *typeNameP = "nil"; break;
+ default:
+ xmlrpc_faultf(envP,
+ "Method registry contains invalid signature "
+ "data. It contains the type specifier '%c'",
+ typeSpecifier);
+ }
+}
+
+
+
+#if defined(_MSC_VER)
+/* MSVC 8 complains that const char ** is incompatible with void * in the
+ REALLOCARRAY. It's not.
+*/
+#pragma warning(push)
+#pragma warning(disable:4090)
+#endif
+
+static void
+makeRoomInArgList(xmlrpc_env * const envP,
+ struct xmlrpc_signature * const signatureP,
+ unsigned int const minArgCount) {
+
+ if (signatureP->argListSpace < minArgCount) {
+ REALLOCARRAY(signatureP->argList, minArgCount);
+ if (signatureP->argList == NULL) {
+ xmlrpc_faultf(envP, "Couldn't get memory for a argument list for "
+ "a method signature with %u arguments", minArgCount);
+ signatureP->argListSpace = 0;
+ }
+ }
+}
+
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
+
+
+static void
+parseArgumentTypeSpecifiers(xmlrpc_env * const envP,
+ const char * const startP,
+ struct xmlrpc_signature * const signatureP,
+ const char ** const nextPP) {
+ const char * cursorP;
+
+ cursorP = startP; /* start at the beginning */
+
+ while (!envP->fault_occurred && *cursorP != ',' && *cursorP != '\0') {
+ const char * typeName;
+
+ translateTypeSpecifierToName(envP, *cursorP, &typeName);
+
+ if (!envP->fault_occurred) {
+ ++cursorP;
+
+ makeRoomInArgList(envP, signatureP, signatureP->argCount + 1);
+
+ signatureP->argList[signatureP->argCount++] = typeName;
+ }
+ }
+ if (!envP->fault_occurred) {
+ if (*cursorP) {
+ XMLRPC_ASSERT(*cursorP == ',');
+ ++cursorP; /* Move past the signature and comma */
+ }
+ }
+ if (envP->fault_occurred)
+ free((void*)signatureP->argList);
+
+ *nextPP = cursorP;
+}
+
+
+
+static void
+parseOneSignature(xmlrpc_env * const envP,
+ const char * const startP,
+ struct xmlrpc_signature ** const signaturePP,
+ const char ** const nextPP) {
+/*----------------------------------------------------------------------------
+ Parse one signature from the signature string that starts at 'startP'.
+
+ Return that signature as a signature object *signaturePP.
+
+ Return as *nextP the location in the signature string of the next
+ signature (i.e. right after the next comma). If there is no next
+ signature (the string ends before any comma), make it point to the
+ terminating NUL.
+-----------------------------------------------------------------------------*/
+ struct xmlrpc_signature * signatureP;
+
+ MALLOCVAR(signatureP);
+ if (signatureP == NULL)
+ xmlrpc_faultf(envP, "Couldn't get memory for signature");
+ else {
+ const char * cursorP;
+
+ signatureP->argListSpace = 0; /* Start with no argument space */
+ signatureP->argList = NULL; /* Nothing allocated yet */
+ signatureP->argCount = 0; /* Start with no arguments */
+
+ cursorP = startP; /* start at the beginning */
+
+ if (*cursorP == ',' || *cursorP == '\0')
+ xmlrpc_faultf(envP, "empty signature (a signature "
+ "must have at least return value type)");
+ else {
+ translateTypeSpecifierToName(envP, *cursorP, &signatureP->retType);
+
+ ++cursorP;
+
+ if (*cursorP != ':')
+ xmlrpc_faultf(envP, "No colon (':') after "
+ "the result type specifier");
+ else {
+ ++cursorP;
+
+ parseArgumentTypeSpecifiers(envP, cursorP, signatureP, nextPP);
+ }
+ }
+ if (envP->fault_occurred)
+ free(signatureP);
+ else
+ *signaturePP = signatureP;
+ }
+}
+
+
+
+static void
+destroySignatures(struct xmlrpc_signature * const firstSignatureP) {
+
+ struct xmlrpc_signature * p;
+ struct xmlrpc_signature * nextP;
+
+ for (p = firstSignatureP; p; p = nextP) {
+ nextP = p->nextP;
+ signatureDestroy(p);
+ }
+}
+
+
+
+static void
+listSignatures(xmlrpc_env * const envP,
+ const char * const sigListString,
+ struct xmlrpc_signature ** const firstSignaturePP) {
+
+ struct xmlrpc_signature ** p;
+ const char * cursorP;
+
+ *firstSignaturePP = NULL; /* Start with empty list */
+
+ p = firstSignaturePP;
+ cursorP = &sigListString[0];
+
+ while (!envP->fault_occurred && *cursorP != '\0') {
+ struct xmlrpc_signature * signatureP;
+
+ parseOneSignature(envP, cursorP, &signatureP, &cursorP);
+
+ /* cursorP now points at next signature in the list or the
+ terminating NUL.
+ */
+
+ if (!envP->fault_occurred) {
+ signatureP->nextP = NULL;
+ *p = signatureP;
+ p = &signatureP->nextP;
+ }
+ }
+ if (envP->fault_occurred)
+ destroySignatures(*firstSignaturePP);
+}
+
+
+
+static void
+signatureListCreate(xmlrpc_env * const envP,
+ const char * const sigListString,
+ xmlrpc_signatureList ** const signatureListPP) {
+
+ xmlrpc_signatureList * signatureListP;
+
+ XMLRPC_ASSERT_ENV_OK(envP);
+
+ MALLOCVAR(signatureListP);
+
+ if (signatureListP == NULL)
+ xmlrpc_faultf(envP, "Could not allocate memory for signature list");
+ else {
+ signatureListP->firstSignatureP = NULL;
+
+ if (sigListString == NULL || xmlrpc_streq(sigListString, "?")) {
+ /* No signatures -- leave the list empty */
+ } else {
+ listSignatures(envP, sigListString,
+ &signatureListP->firstSignatureP);
+
+ if (!envP->fault_occurred) {
+ if (!signatureListP->firstSignatureP)
+ xmlrpc_faultf(envP, "Signature string is empty.");
+
+ if (envP->fault_occurred)
+ destroySignatures(signatureListP->firstSignatureP);
+ }
+ }
+ if (envP->fault_occurred)
+ free(signatureListP);
+
+ *signatureListPP = signatureListP;
+ }
+}
+
+
+
+static void
+signatureListDestroy(xmlrpc_signatureList * const signatureListP) {
+
+ destroySignatures(signatureListP->firstSignatureP);
+
+ free(signatureListP);
+}
+
+
+
+static void
+makeSignatureList(xmlrpc_env * const envP,
+ const char * const signatureString,
+ xmlrpc_signatureList ** const signatureListPP) {
+
+ xmlrpc_env env;
+
+ xmlrpc_env_init(&env);
+
+ signatureListCreate(&env, signatureString, signatureListPP);
+
+ if (env.fault_occurred)
+ xmlrpc_faultf(envP, "Can't interpret signature string '%s'. %s",
+ signatureString, env.fault_string);
+}
+
+
+
+void
+xmlrpc_methodCreate(xmlrpc_env * const envP,
+ xmlrpc_method1 methodFnType1,
+ xmlrpc_method2 methodFnType2,
+ void * const userData,
+ const char * const signatureString,
+ const char * const helpText,
+ xmlrpc_methodInfo ** const methodPP) {
+
+ xmlrpc_methodInfo * methodP;
+
+ XMLRPC_ASSERT_ENV_OK(envP);
+
+ MALLOCVAR(methodP);
+
+ if (methodP == NULL)
+ xmlrpc_faultf(envP, "Unable to allocate storage for a method "
+ "descriptor");
+ else {
+ methodP->methodFnType1 = methodFnType1;
+ methodP->methodFnType2 = methodFnType2;
+ methodP->userData = userData;
+ methodP->helpText = strdup(helpText);
+
+ makeSignatureList(envP, signatureString, &methodP->signatureListP);
+
+ if (envP->fault_occurred)
+ free(methodP);
+
+ *methodPP = methodP;
+ }
+}
+
+
+
+void
+xmlrpc_methodDestroy(xmlrpc_methodInfo * const methodP) {
+
+ signatureListDestroy(methodP->signatureListP);
+
+ xmlrpc_strfree(methodP->helpText);
+
+ free(methodP);
+}
+
+
+
+void
+xmlrpc_methodListCreate(xmlrpc_env * const envP,
+ xmlrpc_methodList ** const methodListPP) {
+
+ xmlrpc_methodList * methodListP;
+
+ XMLRPC_ASSERT_ENV_OK(envP);
+
+ MALLOCVAR(methodListP);
+
+ if (methodListP == NULL)
+ xmlrpc_faultf(envP, "Couldn't allocate method list descriptor");
+ else {
+ methodListP->firstMethodP = NULL;
+ methodListP->lastMethodP = NULL;
+
+ *methodListPP = methodListP;
+ }
+}
+
+
+
+void
+xmlrpc_methodListDestroy(xmlrpc_methodList * methodListP) {
+
+ xmlrpc_methodNode * p;
+ xmlrpc_methodNode * nextP;
+
+ for (p = methodListP->firstMethodP; p; p = nextP) {
+ nextP = p->nextP;
+
+ xmlrpc_methodDestroy(p->methodP);
+ xmlrpc_strfree(p->methodName);
+ free(p);
+ }
+
+ free(methodListP);
+}
+
+
+
+void
+xmlrpc_methodListLookupByName(xmlrpc_methodList * const methodListP,
+ const char * const methodName,
+ xmlrpc_methodInfo ** const methodPP) {
+
+
+ /* We do a simple linear lookup along a linked list.
+ If speed is important, we can make this a binary tree instead.
+ */
+
+ xmlrpc_methodNode * p;
+ xmlrpc_methodInfo * methodP;
+
+ for (p = methodListP->firstMethodP, methodP = NULL;
+ p && !methodP;
+ p = p->nextP) {
+
+ if (xmlrpc_streq(p->methodName, methodName))
+ methodP = p->methodP;
+ }
+ *methodPP = methodP;
+}
+
+
+
+void
+xmlrpc_methodListAdd(xmlrpc_env * const envP,
+ xmlrpc_methodList * const methodListP,
+ const char * const methodName,
+ xmlrpc_methodInfo * const methodP) {
+
+ xmlrpc_methodInfo * existingMethodP;
+
+ XMLRPC_ASSERT_ENV_OK(envP);
+
+ xmlrpc_methodListLookupByName(methodListP, methodName, &existingMethodP);
+
+ if (existingMethodP)
+ xmlrpc_faultf(envP, "Method named '%s' already registered",
+ methodName);
+ else {
+ xmlrpc_methodNode * methodNodeP;
+
+ MALLOCVAR(methodNodeP);
+
+ if (methodNodeP == NULL)
+ xmlrpc_faultf(envP, "Couldn't allocate method node");
+ else {
+ methodNodeP->methodName = strdup(methodName);
+ methodNodeP->methodP = methodP;
+ methodNodeP->nextP = NULL;
+
+ if (!methodListP->firstMethodP)
+ methodListP->firstMethodP = methodNodeP;
+
+ if (methodListP->lastMethodP)
+ methodListP->lastMethodP->nextP = methodNodeP;
+
+ methodListP->lastMethodP = methodNodeP;
+ }
+ }
+}
+
Added: freeswitch/trunk/libs/xmlrpc-c/src/method.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/method.h Fri May 23 16:56:24 2008
@@ -0,0 +1,120 @@
+#ifndef METHOD_H_INCLUDED
+#define METHOD_H_INCLUDED
+
+#include "xmlrpc-c/base.h"
+
+struct xmlrpc_signature {
+ struct xmlrpc_signature * nextP;
+ const char * retType;
+ /* Name of the XML-RPC element that represents the return value
+ type, e.g. "int" or "dateTime.iso8601"
+ */
+ unsigned int argCount;
+ /* Number of arguments method takes */
+ unsigned int argListSpace;
+ /* Number of slots that exist in the argList[] (i.e. memory is
+ allocated)
+ */
+ const char ** argList;
+ /* Array of size 'argCount'. argList[i] is the name of the type
+ of argument i. Like 'retType', e.g. "string".
+
+ The strings are constants, not malloc'ed.
+ */
+};
+
+typedef struct xmlrpc_signatureList {
+ /* A list of signatures for a method. Each signature describes one
+ alternative form of invoking the method (a
+ single method might have multiple forms, e.g. one takes two integer
+ arguments; another takes a single string).
+ */
+ struct xmlrpc_signature * firstSignatureP;
+} xmlrpc_signatureList;
+
+struct xmlrpc_registry {
+ bool introspectionEnabled;
+ struct xmlrpc_methodList * methodListP;
+ xmlrpc_default_method defaultMethodFunction;
+ void * defaultMethodUserData;
+ xmlrpc_preinvoke_method preinvokeFunction;
+ void * preinvokeUserData;
+ xmlrpc_server_shutdown_fn * shutdownServerFn;
+ /* Function that can be called to shut down the server that is
+ using this registry. NULL if none.
+ */
+ void * shutdownContext;
+ /* Context for _shutdown_server_fn -- understood only by
+ that function, passed to it as argument.
+ */
+ xmlrpc_dialect dialect;
+};
+
+typedef struct {
+/*----------------------------------------------------------------------------
+ Everything a registry knows about one XML-RPC method
+-----------------------------------------------------------------------------*/
+ /* One of the methodTypeX fields is NULL and the other isn't.
+ (The reason there are two is backward compatibility. Old
+ programs set up the registry with Type 1; modern ones set it up
+ with Type 2.
+ */
+ xmlrpc_method1 methodFnType1;
+ /* The method function, if it's type 1. Null if it's not */
+ xmlrpc_method2 methodFnType2;
+ /* The method function, if it's type 2. Null if it's not */
+ void * userData;
+ /* Passed to method function */
+ struct xmlrpc_signatureList * signatureListP;
+ /* Stuff returned by system method system.methodSignature.
+ Empty list doesn't mean there are no valid forms of calling the
+ method -- just that the registry declines to state.
+ */
+ const char * helpText;
+ /* Stuff returned by system method system.methodHelp */
+} xmlrpc_methodInfo;
+
+typedef struct xmlrpc_methodNode {
+ struct xmlrpc_methodNode * nextP;
+ const char * methodName;
+ xmlrpc_methodInfo * methodP;
+} xmlrpc_methodNode;
+
+typedef struct xmlrpc_methodList {
+ xmlrpc_methodNode * firstMethodP;
+ xmlrpc_methodNode * lastMethodP;
+} xmlrpc_methodList;
+
+void
+xmlrpc_methodCreate(xmlrpc_env * const envP,
+ xmlrpc_method1 methodFnType1,
+ xmlrpc_method2 methodFnType2,
+ void * const userData,
+ const char * const signatureString,
+ const char * const helpText,
+ xmlrpc_methodInfo ** const methodPP);
+
+void
+xmlrpc_methodDestroy(xmlrpc_methodInfo * const methodP);
+
+void
+xmlrpc_methodListCreate(xmlrpc_env * const envP,
+ xmlrpc_methodList ** const methodListPP);
+
+void
+xmlrpc_methodListDestroy(xmlrpc_methodList * methodListP);
+
+void
+xmlrpc_methodListLookupByName(xmlrpc_methodList * const methodListP,
+ const char * const methodName,
+ xmlrpc_methodInfo ** const methodPP);
+
+void
+xmlrpc_methodListAdd(xmlrpc_env * const envP,
+ xmlrpc_methodList * const methodListP,
+ const char * const methodName,
+ xmlrpc_methodInfo * const methodP);
+
+
+
+#endif
Added: freeswitch/trunk/libs/xmlrpc-c/src/parse_value.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/parse_value.c Fri May 23 16:56:24 2008
@@ -0,0 +1,751 @@
+#include "xmlrpc_config.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <limits.h>
+#include <float.h>
+
+#include "bool.h"
+
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/base_int.h"
+#include "xmlrpc-c/string_int.h"
+#include "xmlrpc-c/util.h"
+#include "xmlrpc-c/xmlparser.h"
+
+#include "parse_value.h"
+
+
+
+static void
+setParseFault(xmlrpc_env * const envP,
+ const char * const format,
+ ...) {
+
+ va_list args;
+ va_start(args, format);
+ xmlrpc_set_fault_formatted_v(envP, XMLRPC_PARSE_ERROR, format, args);
+ va_end(args);
+}
+
+
+
+static void
+parseArrayDataChild(xmlrpc_env * const envP,
+ xml_element * const childP,
+ unsigned int const maxRecursion,
+ xmlrpc_value * const arrayP) {
+
+ const char * const elemName = xml_element_name(childP);
+
+ if (!xmlrpc_streq(elemName, "value"))
+ setParseFault(envP, "<data> element has <%s> child. "
+ "Only <value> makes sense.", elemName);
+ else {
+ xmlrpc_value * itemP;
+
+ xmlrpc_parseValue(envP, maxRecursion-1, childP, &itemP);
+
+ if (!envP->fault_occurred) {
+ xmlrpc_array_append_item(envP, arrayP, itemP);
+
+ xmlrpc_DECREF(itemP);
+ }
+ }
+}
+
+
+
+static void
+parseArray(xmlrpc_env * const envP,
+ unsigned int const maxRecursion,
+ xml_element * const arrayElemP,
+ xmlrpc_value ** const arrayPP) {
+
+ xmlrpc_value * arrayP;
+
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT(arrayElemP != NULL);
+
+ arrayP = xmlrpc_array_new(envP);
+ if (!envP->fault_occurred) {
+ unsigned int const childCount = xml_element_children_size(arrayElemP);
+
+ if (childCount != 1)
+ setParseFault(envP,
+ "<array> element has %u children. Only one <data> "
+ "makes sense.", childCount);
+ else {
+ xml_element * const dataElemP =
+ xml_element_children(arrayElemP)[0];
+ const char * const elemName = xml_element_name(dataElemP);
+
+ if (!xmlrpc_streq(elemName, "data"))
+ setParseFault(envP,
+ "<array> element has <%s> child. Only <data> "
+ "makes sense.", elemName);
+ else {
+ xml_element ** const values = xml_element_children(dataElemP);
+ unsigned int const size = xml_element_children_size(dataElemP);
+
+ unsigned int i;
+
+ for (i = 0; i < size && !envP->fault_occurred; ++i)
+ parseArrayDataChild(envP, values[i], maxRecursion, arrayP);
+ }
+ }
+ if (envP->fault_occurred)
+ xmlrpc_DECREF(arrayP);
+ else
+ *arrayPP = arrayP;
+ }
+}
+
+
+
+static void
+parseName(xmlrpc_env * const envP,
+ xml_element * const nameElemP,
+ xmlrpc_value ** const valuePP) {
+
+ unsigned int const childCount = xml_element_children_size(nameElemP);
+
+ if (childCount > 0)
+ setParseFault(envP, "<name> element has %u children. "
+ "Should have none.", childCount);
+ else {
+ const char * const cdata = xml_element_cdata(nameElemP);
+ size_t const cdataSize = xml_element_cdata_size(nameElemP);
+
+ *valuePP = xmlrpc_string_new_lp(envP, cdataSize, cdata);
+ }
+}
+
+
+
+static void
+getNameChild(xmlrpc_env * const envP,
+ xml_element * const parentP,
+ xml_element * * const childPP) {
+
+ xml_element ** const children = xml_element_children(parentP);
+ size_t const childCount = xml_element_children_size(parentP);
+
+ xml_element * childP;
+ unsigned int i;
+
+ for (i = 0, childP = NULL; i < childCount && !childP; ++i) {
+ if (xmlrpc_streq(xml_element_name(children[i]), "name"))
+ childP = children[i];
+ }
+ if (!childP)
+ xmlrpc_env_set_fault(envP, XMLRPC_PARSE_ERROR,
+ "<member> has no <name> child");
+ else
+ *childPP = childP;
+}
+
+
+
+static void
+getValueChild(xmlrpc_env * const envP,
+ xml_element * const parentP,
+ xml_element * * const childPP) {
+
+ xml_element ** const children = xml_element_children(parentP);
+ size_t const childCount = xml_element_children_size(parentP);
+
+ xml_element * childP;
+ unsigned int i;
+
+ for (i = 0, childP = NULL; i < childCount && !childP; ++i) {
+ if (xmlrpc_streq(xml_element_name(children[i]), "value"))
+ childP = children[i];
+ }
+ if (!childP)
+ xmlrpc_env_set_fault(envP, XMLRPC_PARSE_ERROR,
+ "<member> has no <value> child");
+ else
+ *childPP = childP;
+}
+
+
+
+static void
+parseMember(xmlrpc_env * const envP,
+ xml_element * const memberP,
+ unsigned int const maxRecursion,
+ xmlrpc_value ** const keyPP,
+ xmlrpc_value ** const valuePP) {
+
+ unsigned int const childCount = xml_element_children_size(memberP);
+
+ if (childCount != 2)
+ setParseFault(envP,
+ "<member> element has %u children. Only one <name> and "
+ "one <value> make sense.", childCount);
+ else {
+ xml_element * nameElemP;
+
+ getNameChild(envP, memberP, &nameElemP);
+
+ if (!envP->fault_occurred) {
+ parseName(envP, nameElemP, keyPP);
+
+ if (!envP->fault_occurred) {
+ xml_element * valueElemP;
+
+ getValueChild(envP, memberP, &valueElemP);
+
+ if (!envP->fault_occurred)
+ xmlrpc_parseValue(envP, maxRecursion-1, valueElemP,
+ valuePP);
+
+ if (envP->fault_occurred)
+ xmlrpc_DECREF(*keyPP);
+ }
+ }
+ }
+}
+
+
+
+static void
+parseStruct(xmlrpc_env * const envP,
+ unsigned int const maxRecursion,
+ xml_element * const elemP,
+ xmlrpc_value ** const structPP) {
+/*----------------------------------------------------------------------------
+ Parse the <struct> element 'elemP'.
+-----------------------------------------------------------------------------*/
+ xmlrpc_value * structP;
+
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT(elemP != NULL);
+
+ structP = xmlrpc_struct_new(envP);
+ if (!envP->fault_occurred) {
+ /* Iterate over our children, extracting key/value pairs. */
+
+ xml_element ** const members = xml_element_children(elemP);
+ unsigned int const size = xml_element_children_size(elemP);
+
+ unsigned int i;
+
+ for (i = 0; i < size && !envP->fault_occurred; ++i) {
+ const char * const elemName = xml_element_name(members[i]);
+
+ if (!xmlrpc_streq(elemName, "member"))
+ setParseFault(envP, "<%s> element found where only <member> "
+ "makes sense", elemName);
+ else {
+ xmlrpc_value * keyP;
+ xmlrpc_value * valueP;
+
+ parseMember(envP, members[i], maxRecursion, &keyP, &valueP);
+
+ if (!envP->fault_occurred) {
+ xmlrpc_struct_set_value_v(envP, structP, keyP, valueP);
+
+ xmlrpc_DECREF(keyP);
+ xmlrpc_DECREF(valueP);
+ }
+ }
+ }
+ if (envP->fault_occurred)
+ xmlrpc_DECREF(structP);
+ else
+ *structPP = structP;
+ }
+}
+
+
+
+static void
+parseInt(xmlrpc_env * const envP,
+ const char * const str,
+ xmlrpc_value ** const valuePP) {
+/*----------------------------------------------------------------------------
+ Parse the content of a <int> XML-RPC XML element, e.g. "34".
+
+ 'str' is that content.
+-----------------------------------------------------------------------------*/
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT_PTR_OK(str);
+
+ if (str[0] == '\0')
+ setParseFault(envP, "<int> XML element content is empty");
+ else if (isspace(str[0]))
+ setParseFault(envP, "<int> content '%s' starts with white space",
+ str);
+ else {
+ long i;
+ char * tail;
+
+ errno = 0;
+ i = strtol(str, &tail, 10);
+
+ /* Look for ERANGE. */
+ if (errno == ERANGE)
+ setParseFault(envP, "<int> XML element value '%s' represents a "
+ "number beyond the range that "
+ "XML-RPC allows (%d - %d)", str,
+ XMLRPC_INT32_MIN, XMLRPC_INT32_MAX);
+ else if (errno != 0)
+ setParseFault(envP, "unexpected error parsing <int> XML element "
+ "value '%s'. strtol() failed with errno %d (%s)",
+ str, errno, strerror(errno));
+ else {
+ /* Look for out-of-range errors which didn't produce ERANGE. */
+ if (i < XMLRPC_INT32_MIN)
+ setParseFault(envP,
+ "<int> value %d is below the range allowed "
+ "by XML-RPC (minimum is %d)",
+ i, XMLRPC_INT32_MIN);
+ else if (i > XMLRPC_INT32_MAX)
+ setParseFault(envP,
+ "<int> value %d is above the range allowed "
+ "by XML-RPC (maximum is %d)",
+ i, XMLRPC_INT32_MAX);
+ else {
+ if (tail[0] != '\0')
+ setParseFault(envP,
+ "<int> value '%s' contains non-numerical "
+ "junk: '%s'", str, tail);
+ else
+ *valuePP = xmlrpc_int_new(envP, i);
+ }
+ }
+ }
+}
+
+
+
+static void
+parseBoolean(xmlrpc_env * const envP,
+ const char * const str,
+ xmlrpc_value ** const valuePP) {
+/*----------------------------------------------------------------------------
+ Parse the content of a <boolean> XML-RPC XML element, e.g. "1".
+
+ 'str' is that content.
+-----------------------------------------------------------------------------*/
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT_PTR_OK(str);
+
+ if (xmlrpc_streq(str, "0") || xmlrpc_streq(str, "1"))
+ *valuePP = xmlrpc_bool_new(envP, xmlrpc_streq(str, "1") ? 1 : 0);
+ else
+ setParseFault(envP, "<boolean> XML element content must be either "
+ "'0' or '1' according to XML-RPC. This one has '%s'",
+ str);
+}
+
+
+
+static void
+scanAndValidateDoubleString(xmlrpc_env * const envP,
+ const char * const string,
+ const char ** const mantissaP,
+ const char ** const mantissaEndP,
+ const char ** const fractionP,
+ const char ** const fractionEndP) {
+
+ const char * mantissa;
+ const char * dp;
+ const char * p;
+
+ if (string[0] == '-' || string[0] == '+')
+ mantissa = &string[1];
+ else
+ mantissa = &string[0];
+
+ for (p = mantissa, dp = NULL; *p; ++p) {
+ char const c = *p;
+ if (c == '.') {
+ if (dp) {
+ setParseFault(envP, "Two decimal points");
+ return;
+ } else
+ dp = p;
+ } else if (c < '0' || c > '9') {
+ setParseFault(envP, "Garbage (not sign, digit, or period) "
+ "starting at '%s'", p);
+ return;
+ }
+ }
+ *mantissaP = mantissa;
+ if (dp) {
+ *mantissaEndP = dp;
+ *fractionP = dp+1;
+ *fractionEndP = p;
+ } else {
+ *mantissaEndP = p;
+ *fractionP = p;
+ *fractionEndP = p;
+ }
+}
+
+
+
+static bool
+isInfinite(double const value) {
+
+ return value > DBL_MAX;
+}
+
+
+
+static void
+parseDoubleString(xmlrpc_env * const envP,
+ const char * const string,
+ double * const valueP) {
+/*----------------------------------------------------------------------------
+ Turn e.g. "4.3" into 4.3 .
+-----------------------------------------------------------------------------*/
+ /* strtod() is no good for this because it is designed for human
+ interfaces; it parses according to locale. As a practical
+ matter that sometimes means that it does not recognize "." as a
+ decimal point. In XML-RPC, "." is a decimal point.
+
+ Design note: in my experiments, using strtod() was 10 times
+ slower than using this function.
+ */
+ const char * mantissa;
+ const char * mantissaEnd;
+ const char * fraction;
+ const char * fractionEnd;
+
+ scanAndValidateDoubleString(envP, string, &mantissa, &mantissaEnd,
+ &fraction, &fractionEnd);
+
+ if (!envP->fault_occurred) {
+ double accum;
+
+ accum = 0.0;
+
+ if (mantissa == mantissaEnd && fraction == fractionEnd) {
+ setParseFault(envP, "No digits");
+ return;
+ }
+ {
+ /* Add in the whole part */
+ const char * p;
+
+ for (p = mantissa; p < mantissaEnd; ++p) {
+ accum *= 10;
+ accum += (*p - '0');
+ }
+ }
+ {
+ /* Add in the fractional part */
+ double significance;
+ const char * p;
+ for (significance = 0.1, p = fraction;
+ p < fractionEnd;
+ ++p, significance *= 0.1) {
+
+ accum += (*p - '0') * significance;
+ }
+ }
+ if (isInfinite(accum))
+ setParseFault(envP, "Value exceeds the size allowed by XML-RPC");
+ else
+ *valueP = string[0] == '-' ? (- accum) : accum;
+ }
+}
+
+
+
+static void
+parseDoubleStringStrtod(const char * const str,
+ bool * const failedP,
+ double * const valueP) {
+
+ if (strlen(str) == 0) {
+ /* strtod() happily interprets empty string as 0.0. We don't think
+ the user will appreciate that XML-RPC extension.
+ */
+ *failedP = true;
+ } else {
+ char * tail;
+
+ errno = 0;
+
+ *valueP = strtod(str, &tail);
+
+ if (errno != 0)
+ *failedP = true;
+ else {
+ if (tail[0] != '\0')
+ *failedP = true;
+ else
+ *failedP = false;
+ }
+ }
+}
+
+
+
+static void
+parseDouble(xmlrpc_env * const envP,
+ const char * const str,
+ xmlrpc_value ** const valuePP) {
+/*----------------------------------------------------------------------------
+ Parse the content of a <double> XML-RPC XML element, e.g. "34.5".
+
+ 'str' is that content.
+-----------------------------------------------------------------------------*/
+ xmlrpc_env parseEnv;
+ double valueDouble;
+
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT_PTR_OK(str);
+
+ xmlrpc_env_init(&parseEnv);
+
+ parseDoubleString(&parseEnv, str, &valueDouble);
+
+ if (parseEnv.fault_occurred) {
+ /* As an alternative, try a strtod() parsing. strtod()
+ accepts other forms, e.g. "3.4E6"; "3,4"; " 3.4". These
+ are not permitted by XML-RPC, but an almost-XML-RPC partner
+ might use one. In fact, for many years, Xmlrpc-c generated
+ such alternatives (by mistake).
+ */
+ bool failed;
+ parseDoubleStringStrtod(str, &failed, &valueDouble);
+ if (failed)
+ setParseFault(envP, "<double> element value '%s' is not a valid "
+ "floating point number. %s",
+ str, parseEnv.fault_string);
+ }
+
+ if (!envP->fault_occurred)
+ *valuePP = xmlrpc_double_new(envP, valueDouble);
+
+ xmlrpc_env_clean(&parseEnv);
+}
+
+
+
+static void
+parseBase64(xmlrpc_env * const envP,
+ const char * const str,
+ size_t const strLength,
+ xmlrpc_value ** const valuePP) {
+/*----------------------------------------------------------------------------
+ Parse the content of a <base64> XML-RPC XML element, e.g. "FD32YY".
+
+ 'str' is that content.
+-----------------------------------------------------------------------------*/
+ xmlrpc_mem_block * decoded;
+
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT_PTR_OK(str);
+
+ decoded = xmlrpc_base64_decode(envP, str, strLength);
+ if (!envP->fault_occurred) {
+ unsigned char * const bytes =
+ XMLRPC_MEMBLOCK_CONTENTS(unsigned char, decoded);
+ size_t const byteCount =
+ XMLRPC_MEMBLOCK_SIZE(unsigned char, decoded);
+
+ *valuePP = xmlrpc_base64_new(envP, byteCount, bytes);
+
+ XMLRPC_MEMBLOCK_FREE(unsigned char, decoded);
+ }
+}
+
+
+
+static void
+parseI8(xmlrpc_env * const envP,
+ const char * const str,
+ xmlrpc_value ** const valuePP) {
+/*----------------------------------------------------------------------------
+ Parse the content of a <i8> XML-RPC XML element, e.g. "34".
+
+ 'str' is that content.
+-----------------------------------------------------------------------------*/
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT_PTR_OK(str);
+
+ if (str[0] == '\0')
+ setParseFault(envP, "<i8> XML element content is empty");
+ else if (isspace(str[0]))
+ setParseFault(envP,
+ "<i8> content '%s' starts with white space", str);
+ else {
+ xmlrpc_int64 i;
+ char * tail;
+
+ errno = 0;
+ i = strtoll(str, &tail, 10);
+
+ if (errno == ERANGE)
+ setParseFault(envP, "<i8> XML element value '%s' represents a "
+ "number beyond the range that "
+ "XML-RPC allows (%d - %d)", str,
+ XMLRPC_INT64_MIN, XMLRPC_INT64_MAX);
+ else if (errno != 0)
+ setParseFault(envP, "unexpected error parsing <i8> XML element "
+ "value '%s'. strtoll() failed with errno %d (%s)",
+ str, errno, strerror(errno));
+ else {
+ /* Look for out-of-range errors which didn't produce ERANGE. */
+ if (i < XMLRPC_INT64_MIN)
+ setParseFault(envP, "<i8> value %d is below the range allowed "
+ "by XML-RPC (minimum is %d)",
+ i, XMLRPC_INT64_MIN);
+ else if (i > XMLRPC_INT64_MAX)
+ setParseFault(envP, "<i8> value %d is above the range allowed "
+ "by XML-RPC (maximum is %d)",
+ i, XMLRPC_INT64_MAX);
+ else {
+ if (tail[0] != '\0')
+ setParseFault(envP,
+ "<i8> value '%s' contains non-numerical "
+ "junk: '%s'", str, tail);
+ else
+ *valuePP = xmlrpc_i8_new(envP, i);
+ }
+ }
+ }
+}
+
+
+
+static void
+parseSimpleValueCdata(xmlrpc_env * const envP,
+ const char * const elementName,
+ const char * const cdata,
+ size_t const cdataLength,
+ xmlrpc_value ** const valuePP) {
+/*----------------------------------------------------------------------------
+ Parse an XML element is supposedly a data type element such as
+ <string>. Its name is 'elementName', and it has no children, but
+ contains cdata 'cdata', which is 'dataLength' characters long.
+-----------------------------------------------------------------------------*/
+ /* We need to straighten out the whole character set / encoding thing
+ some day. What is 'cdata', and what should it be? Does it have
+ embedded NUL? Some of the code here assumes it doesn't. Is it
+ text?
+
+ The <string> parser assumes it's UTF 8 with embedded NULs.
+ But the <int> parser will get terribly confused if there are any
+ UTF-8 multibyte sequences or NUL characters. So will most of the
+ others.
+
+ The "ex.XXX" element names are what the Apache XML-RPC facility
+ uses: http://ws.apache.org/xmlrpc/types.html. i1 and i2 are just
+ from my imagination.
+ */
+
+ if (xmlrpc_streq(elementName, "int") ||
+ xmlrpc_streq(elementName, "i4") ||
+ xmlrpc_streq(elementName, "i1") ||
+ xmlrpc_streq(elementName, "i2") ||
+ xmlrpc_streq(elementName, "ex.i1") ||
+ xmlrpc_streq(elementName, "ex.i2"))
+ parseInt(envP, cdata, valuePP);
+ else if (xmlrpc_streq(elementName, "boolean"))
+ parseBoolean(envP, cdata, valuePP);
+ else if (xmlrpc_streq(elementName, "double"))
+ parseDouble(envP, cdata, valuePP);
+ else if (xmlrpc_streq(elementName, "dateTime.iso8601"))
+ *valuePP = xmlrpc_datetime_new_str(envP, cdata);
+ else if (xmlrpc_streq(elementName, "string"))
+ *valuePP = xmlrpc_string_new_lp(envP, cdataLength, cdata);
+ else if (xmlrpc_streq(elementName, "base64"))
+ parseBase64(envP, cdata, cdataLength, valuePP);
+ else if (xmlrpc_streq(elementName, "nil") ||
+ xmlrpc_streq(elementName, "ex.nil"))
+ *valuePP = xmlrpc_nil_new(envP);
+ else if (xmlrpc_streq(elementName, "i8") ||
+ xmlrpc_streq(elementName, "ex.i8"))
+ parseI8(envP, cdata, valuePP);
+ else
+ setParseFault(envP, "Unknown value type -- XML element is named "
+ "<%s>", elementName);
+}
+
+
+
+static void
+parseSimpleValue(xmlrpc_env * const envP,
+ xml_element * const elemP,
+ xmlrpc_value ** const valuePP) {
+
+ unsigned int const childCount = xml_element_children_size(elemP);
+
+ if (childCount > 0)
+ setParseFault(envP, "The child of a <value> element "
+ "is neither <array> nor <struct>, "
+ "but has %u child elements of its own.",
+ childCount);
+ else {
+ const char * const elemName = xml_element_name(elemP);
+ const char * const cdata = xml_element_cdata(elemP);
+ size_t const cdataSize = xml_element_cdata_size(elemP);
+
+ parseSimpleValueCdata(envP, elemName, cdata, cdataSize, valuePP);
+ }
+}
+
+
+
+void
+xmlrpc_parseValue(xmlrpc_env * const envP,
+ unsigned int const maxRecursion,
+ xml_element * const elemP,
+ xmlrpc_value ** const valuePP) {
+/*----------------------------------------------------------------------------
+ Compute the xmlrpc_value represented by the XML <value> element 'elem'.
+ Return that xmlrpc_value.
+
+ We call convert_array() and convert_struct(), which may ultimately
+ call us recursively. Don't recurse any more than 'maxRecursion'
+ times.
+-----------------------------------------------------------------------------*/
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT(elemP != NULL);
+
+ /* Assume we'll need to recurse, make sure we're allowed */
+ if (maxRecursion < 1)
+ xmlrpc_env_set_fault(envP, XMLRPC_PARSE_ERROR,
+ "Nested data structure too deep.");
+ else {
+ if (!xmlrpc_streq(xml_element_name(elemP), "value"))
+ setParseFault(envP,
+ "<%s> element where <value> expected",
+ xml_element_name(elemP));
+ else {
+ unsigned int const childCount = xml_element_children_size(elemP);
+
+ if (childCount == 0) {
+ /* We have no type element, so treat the value as a string. */
+ char * const cdata = xml_element_cdata(elemP);
+ size_t const cdata_size = xml_element_cdata_size(elemP);
+ *valuePP = xmlrpc_string_new_lp(envP, cdata_size, cdata);
+ } else if (childCount > 1)
+ setParseFault(envP, "<value> has %u child elements. "
+ "Only zero or one make sense.", childCount);
+ else {
+ /* We should have a type tag inside our value tag. */
+ xml_element * const childP = xml_element_children(elemP)[0];
+ const char * const childName = xml_element_name(childP);
+
+ if (xmlrpc_streq(childName, "struct"))
+ parseStruct(envP, maxRecursion, childP, valuePP);
+ else if (xmlrpc_streq(childName, "array"))
+ parseArray(envP, maxRecursion, childP, valuePP);
+ else
+ parseSimpleValue(envP, childP, valuePP);
+ }
+ }
+ }
+}
Added: freeswitch/trunk/libs/xmlrpc-c/src/parse_value.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/parse_value.h Fri May 23 16:56:24 2008
@@ -0,0 +1,13 @@
+#ifndef PARSE_VALUE_H_INCLUDED
+#define PARSE_VALUE_H_INCLUDED
+
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/xmlparser.h"
+
+void
+xmlrpc_parseValue(xmlrpc_env * const envP,
+ unsigned int const maxRecursion,
+ xml_element * const elemP,
+ xmlrpc_value ** const valuePP);
+
+#endif
Added: freeswitch/trunk/libs/xmlrpc-c/src/registry.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/registry.c Fri May 23 16:56:24 2008
@@ -0,0 +1,434 @@
+/*=========================================================================
+ XML-RPC Server Method Registry
+===========================================================================
+ These are the functions that implement the XML-RPC method registry.
+
+ A method registry is a list of XML-RPC methods for a server to
+ implement, along with the details of how to implement each -- most
+ notably a function pointer for a function that executes the method.
+
+ To build an XML-RPC server, just add a communication facility.
+
+ Copyright information is at end of file
+
+=========================================================================*/
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "xmlrpc_config.h"
+#include "bool.h"
+#include "mallocvar.h"
+#include "xmlrpc-c/base_int.h"
+#include "xmlrpc-c/string_int.h"
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/server.h"
+#include "method.h"
+#include "system_method.h"
+#include "version.h"
+
+#include "registry.h"
+
+
+unsigned int const xmlrpc_server_version_major = XMLRPC_VERSION_MAJOR;
+unsigned int const xmlrpc_server_version_minor = XMLRPC_VERSION_MINOR;
+unsigned int const xmlrpc_server_version_point = XMLRPC_VERSION_POINT;
+
+
+xmlrpc_registry *
+xmlrpc_registry_new(xmlrpc_env * const envP) {
+
+ xmlrpc_registry * registryP;
+
+ XMLRPC_ASSERT_ENV_OK(envP);
+
+ MALLOCVAR(registryP);
+
+ if (registryP == NULL)
+ xmlrpc_faultf(envP, "Could not allocate memory for registry");
+ else {
+ registryP->introspectionEnabled = true;
+ registryP->defaultMethodFunction = NULL;
+ registryP->preinvokeFunction = NULL;
+ registryP->shutdownServerFn = NULL;
+ registryP->dialect = xmlrpc_dialect_i8;
+
+ xmlrpc_methodListCreate(envP, ®istryP->methodListP);
+ if (!envP->fault_occurred)
+ xmlrpc_installSystemMethods(envP, registryP);
+
+ if (envP->fault_occurred)
+ free(registryP);
+ }
+ return registryP;
+}
+
+
+
+void
+xmlrpc_registry_free(xmlrpc_registry * const registryP) {
+
+ XMLRPC_ASSERT_PTR_OK(registryP);
+
+ xmlrpc_methodListDestroy(registryP->methodListP);
+
+ free(registryP);
+}
+
+
+
+static void
+registryAddMethod(xmlrpc_env * const envP,
+ xmlrpc_registry * const registryP,
+ const char * const methodName,
+ xmlrpc_method1 method1,
+ xmlrpc_method2 method2,
+ const char * const signatureString,
+ const char * const help,
+ void * const userData) {
+
+ const char * const helpString =
+ help ? help : "No help is available for this method.";
+
+ xmlrpc_methodInfo * methodP;
+
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT_PTR_OK(registryP);
+ XMLRPC_ASSERT_PTR_OK(methodName);
+ XMLRPC_ASSERT(method1 != NULL || method2 != NULL);
+
+ xmlrpc_methodCreate(envP, method1, method2, userData,
+ signatureString, helpString, &methodP);
+
+ if (!envP->fault_occurred) {
+ xmlrpc_methodListAdd(envP, registryP->methodListP, methodName,
+ methodP);
+
+ if (envP->fault_occurred)
+ xmlrpc_methodDestroy(methodP);
+ }
+}
+
+
+
+void
+xmlrpc_registry_add_method_w_doc(
+ xmlrpc_env * const envP,
+ xmlrpc_registry * const registryP,
+ const char * const host ATTR_UNUSED,
+ const char * const methodName,
+ xmlrpc_method1 const method,
+ void * const serverInfo,
+ const char * const signatureString,
+ const char * const help) {
+
+ XMLRPC_ASSERT(host == NULL);
+
+ registryAddMethod(envP, registryP, methodName, method, NULL,
+ signatureString, help, serverInfo);
+}
+
+
+
+void
+xmlrpc_registry_add_method(xmlrpc_env * const envP,
+ xmlrpc_registry * const registryP,
+ const char * const host,
+ const char * const methodName,
+ xmlrpc_method1 const method,
+ void * const serverInfoP) {
+
+ xmlrpc_registry_add_method_w_doc(
+ envP, registryP, host, methodName,
+ method, serverInfoP, "?", "No help is available for this method.");
+}
+
+
+
+void
+xmlrpc_registry_add_method2(xmlrpc_env * const envP,
+ xmlrpc_registry * const registryP,
+ const char * const methodName,
+ xmlrpc_method2 method,
+ const char * const signatureString,
+ const char * const help,
+ void * const serverInfo) {
+
+ registryAddMethod(envP, registryP, methodName, NULL, method,
+ signatureString, help, serverInfo);
+}
+
+
+
+void
+xmlrpc_registry_set_default_method(
+ xmlrpc_env * const envP ATTR_UNUSED,
+ xmlrpc_registry * const registryP ATTR_UNUSED,
+ xmlrpc_default_method const function,
+ void * const userData) {
+
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT_PTR_OK(registryP);
+ XMLRPC_ASSERT_PTR_OK(function);
+
+ /* Note: this may be the first default method, or it may be a replacement
+ of the current one.
+ */
+
+ registryP->defaultMethodFunction = function;
+ registryP->defaultMethodUserData = userData;
+}
+
+
+
+
+void
+xmlrpc_registry_set_preinvoke_method(
+ xmlrpc_env * const envP ATTR_UNUSED,
+ xmlrpc_registry * const registryP ATTR_UNUSED,
+ xmlrpc_preinvoke_method const function,
+ void * const userData) {
+
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT_PTR_OK(registryP);
+ XMLRPC_ASSERT_PTR_OK(function);
+
+ registryP->preinvokeFunction = function;
+ registryP->preinvokeUserData = userData;
+}
+
+
+
+void
+xmlrpc_registry_set_shutdown(xmlrpc_registry * const registryP,
+ xmlrpc_server_shutdown_fn * const shutdownFn,
+ void * const context) {
+
+ XMLRPC_ASSERT_PTR_OK(registryP);
+ XMLRPC_ASSERT_PTR_OK(shutdownFn);
+
+ registryP->shutdownServerFn = shutdownFn;
+
+ registryP->shutdownContext = context;
+}
+
+
+
+void
+xmlrpc_registry_set_dialect(xmlrpc_env * const envP,
+ xmlrpc_registry * const registryP,
+ xmlrpc_dialect const dialect) {
+
+ if (dialect != xmlrpc_dialect_i8 &&
+ dialect != xmlrpc_dialect_apache)
+ xmlrpc_faultf(envP, "Invalid dialect argument -- not of type "
+ "xmlrpc_dialect. Numerical value is %u", dialect);
+ else
+ registryP->dialect = dialect;
+}
+
+
+
+static void
+callNamedMethod(xmlrpc_env * const envP,
+ xmlrpc_methodInfo * const methodP,
+ xmlrpc_value * const paramArrayP,
+ void * const callInfoP,
+ xmlrpc_value ** const resultPP) {
+
+ if (methodP->methodFnType2)
+ *resultPP =
+ methodP->methodFnType2(envP, paramArrayP,
+ methodP->userData, callInfoP);
+ else {
+ assert(methodP->methodFnType1);
+ *resultPP =
+ methodP->methodFnType1(envP, paramArrayP, methodP->userData);
+ }
+}
+
+
+
+void
+xmlrpc_dispatchCall(xmlrpc_env * const envP,
+ xmlrpc_registry * const registryP,
+ const char * const methodName,
+ xmlrpc_value * const paramArrayP,
+ void * const callInfoP,
+ xmlrpc_value ** const resultPP) {
+
+ if (registryP->preinvokeFunction)
+ registryP->preinvokeFunction(envP, methodName, paramArrayP,
+ registryP->preinvokeUserData);
+
+ if (!envP->fault_occurred) {
+ xmlrpc_methodInfo * methodP;
+
+ xmlrpc_methodListLookupByName(registryP->methodListP, methodName,
+ &methodP);
+
+ if (methodP)
+ callNamedMethod(envP, methodP, paramArrayP, callInfoP, resultPP);
+ else {
+ if (registryP->defaultMethodFunction)
+ *resultPP = registryP->defaultMethodFunction(
+ envP, callInfoP, methodName, paramArrayP,
+ registryP->defaultMethodUserData);
+ else {
+ /* No matching method, and no default. */
+ xmlrpc_env_set_fault_formatted(
+ envP, XMLRPC_NO_SUCH_METHOD_ERROR,
+ "Method '%s' not defined", methodName);
+ }
+ }
+ }
+ /* For backward compatibility, for sloppy users: */
+ if (envP->fault_occurred)
+ *resultPP = NULL;
+}
+
+
+
+/*=========================================================================
+** xmlrpc_registry_process_call
+**=========================================================================
+**
+*/
+
+static void
+serializeFault(xmlrpc_env * const envP,
+ xmlrpc_env const fault,
+ xmlrpc_mem_block * const responseXmlP) {
+
+ xmlrpc_env env;
+
+ xmlrpc_env_init(&env);
+
+ xmlrpc_serialize_fault(&env, responseXmlP, &fault);
+
+ if (env.fault_occurred)
+ xmlrpc_faultf(envP,
+ "Executed XML-RPC method completely and it "
+ "generated a fault response, but we failed "
+ "to encode that fault response as XML-RPC "
+ "so we could send it to the client. %s",
+ env.fault_string);
+
+ xmlrpc_env_clean(&env);
+}
+
+
+
+void
+xmlrpc_registry_process_call2(xmlrpc_env * const envP,
+ xmlrpc_registry * const registryP,
+ const char * const callXml,
+ size_t const callXmlLen,
+ void * const callInfo,
+ xmlrpc_mem_block ** const responseXmlPP) {
+
+ xmlrpc_mem_block * responseXmlP;
+
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT_PTR_OK(callXml);
+
+ xmlrpc_traceXml("XML-RPC CALL", callXml, callXmlLen);
+
+ /* Allocate our output buffer.
+ ** If this fails, we need to die in a special fashion. */
+ responseXmlP = XMLRPC_MEMBLOCK_NEW(char, envP, 0);
+ if (!envP->fault_occurred) {
+ const char * methodName;
+ xmlrpc_value * paramArrayP;
+ xmlrpc_env fault;
+ xmlrpc_env parseEnv;
+
+ xmlrpc_env_init(&fault);
+ xmlrpc_env_init(&parseEnv);
+
+ xmlrpc_parse_call(&parseEnv, callXml, callXmlLen,
+ &methodName, ¶mArrayP);
+
+ if (parseEnv.fault_occurred)
+ xmlrpc_env_set_fault_formatted(
+ &fault, XMLRPC_PARSE_ERROR,
+ "Call XML not a proper XML-RPC call. %s",
+ parseEnv.fault_string);
+ else {
+ xmlrpc_value * resultP;
+
+ xmlrpc_dispatchCall(&fault, registryP, methodName, paramArrayP,
+ callInfo, &resultP);
+
+ if (!fault.fault_occurred) {
+ xmlrpc_serialize_response2(envP, responseXmlP,
+ resultP, registryP->dialect);
+
+ xmlrpc_DECREF(resultP);
+ }
+ xmlrpc_strfree(methodName);
+ xmlrpc_DECREF(paramArrayP);
+ }
+ if (!envP->fault_occurred && fault.fault_occurred)
+ serializeFault(envP, fault, responseXmlP);
+
+ xmlrpc_env_clean(&parseEnv);
+ xmlrpc_env_clean(&fault);
+
+ if (envP->fault_occurred)
+ XMLRPC_MEMBLOCK_FREE(char, responseXmlP);
+ else {
+ *responseXmlPP = responseXmlP;
+ xmlrpc_traceXml("XML-RPC RESPONSE",
+ XMLRPC_MEMBLOCK_CONTENTS(char, responseXmlP),
+ XMLRPC_MEMBLOCK_SIZE(char, responseXmlP));
+ }
+ }
+}
+
+
+
+xmlrpc_mem_block *
+xmlrpc_registry_process_call(xmlrpc_env * const envP,
+ xmlrpc_registry * const registryP,
+ const char * const host ATTR_UNUSED,
+ const char * const callXml,
+ size_t const callXmlLen) {
+
+ xmlrpc_mem_block * responseXmlP;
+
+ xmlrpc_registry_process_call2(envP, registryP, callXml, callXmlLen, NULL,
+ &responseXmlP);
+
+ return responseXmlP;
+}
+
+
+
+/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
+** Copyright (C) 2001 by Eric Kidd. All rights reserved.
+** Copyright (C) 2001 by Luke Howard. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR 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. */
Added: freeswitch/trunk/libs/xmlrpc-c/src/registry.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/registry.h Fri May 23 16:56:24 2008
@@ -0,0 +1,15 @@
+#ifndef REGISTRY_H_INCLUDED
+#define REGISTRY_H_INCLUDED
+
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/server.h"
+
+void
+xmlrpc_dispatchCall(struct _xmlrpc_env * const envP,
+ struct xmlrpc_registry * const registryP,
+ const char * const methodName,
+ struct _xmlrpc_value * const paramArrayP,
+ void * const callInfoP,
+ struct _xmlrpc_value ** const resultPP);
+
+#endif
Added: freeswitch/trunk/libs/xmlrpc-c/src/resource.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/resource.c Fri May 23 16:56:24 2008
@@ -0,0 +1,31 @@
+#include "xmlrpc_config.h"
+
+#include "xmlrpc-c/base.h"
+
+
+/*=========================================================================
+** Resource Limits
+**=========================================================================
+*/
+
+static size_t limits[XMLRPC_LAST_LIMIT_ID + 1] = {
+ XMLRPC_NESTING_LIMIT_DEFAULT,
+ XMLRPC_XML_SIZE_LIMIT_DEFAULT
+};
+
+void
+xmlrpc_limit_set (int const limit_id,
+ size_t const value) {
+
+ XMLRPC_ASSERT(0 <= limit_id && limit_id <= XMLRPC_LAST_LIMIT_ID);
+ limits[limit_id] = value;
+}
+
+
+
+size_t
+xmlrpc_limit_get(int const limit_id) {
+
+ XMLRPC_ASSERT(0 <= limit_id && limit_id <= XMLRPC_LAST_LIMIT_ID);
+ return limits[limit_id];
+}
Added: freeswitch/trunk/libs/xmlrpc-c/src/system_method.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/system_method.c Fri May 23 16:56:24 2008
@@ -0,0 +1,746 @@
+/* Copyright information is at end of file */
+
+#include "xmlrpc_config.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "xmlrpc-c/base_int.h"
+#include "xmlrpc-c/string_int.h"
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/server.h"
+#include "version.h"
+#include "registry.h"
+#include "method.h"
+
+#include "system_method.h"
+
+
+struct systemMethodReg {
+/*----------------------------------------------------------------------------
+ Information needed to register a system method
+-----------------------------------------------------------------------------*/
+ const char * const methodName;
+ xmlrpc_method2 const methodFunction;
+ const char * const signatureString;
+ const char * const helpText;
+};
+
+
+
+void
+xmlrpc_registry_disable_introspection(xmlrpc_registry * const registryP) {
+
+ XMLRPC_ASSERT_PTR_OK(registryP);
+
+ registryP->introspectionEnabled = false;
+}
+
+
+
+/*=========================================================================
+ system.multicall
+=========================================================================*/
+
+static void
+callOneMethod(xmlrpc_env * const envP,
+ xmlrpc_registry * const registryP,
+ xmlrpc_value * const rpcDescP,
+ void * const callInfo,
+ xmlrpc_value ** const resultPP) {
+
+ const char * methodName;
+ xmlrpc_value * paramArrayP;
+
+ XMLRPC_ASSERT_ENV_OK(envP);
+
+ if (xmlrpc_value_type(rpcDescP) != XMLRPC_TYPE_STRUCT)
+ xmlrpc_env_set_fault_formatted(
+ envP, XMLRPC_TYPE_ERROR,
+ "An element of the multicall array is type %u, but should "
+ "be a struct (with members 'methodName' and 'params')",
+ xmlrpc_value_type(rpcDescP));
+ else {
+ xmlrpc_decompose_value(envP, rpcDescP, "{s:s,s:A,*}",
+ "methodName", &methodName,
+ "params", ¶mArrayP);
+ if (!envP->fault_occurred) {
+ /* Watch out for a deep recursion attack. */
+ if (xmlrpc_streq(methodName, "system.multicall"))
+ xmlrpc_env_set_fault_formatted(
+ envP,
+ XMLRPC_REQUEST_REFUSED_ERROR,
+ "Recursive system.multicall forbidden");
+ else {
+ xmlrpc_env env;
+ xmlrpc_value * resultValP;
+
+ xmlrpc_env_init(&env);
+ xmlrpc_dispatchCall(&env, registryP, methodName, paramArrayP,
+ callInfo,
+ &resultValP);
+ if (env.fault_occurred) {
+ /* Method failed, so result is a fault structure */
+ *resultPP =
+ xmlrpc_build_value(
+ envP, "{s:i,s:s}",
+ "faultCode", (xmlrpc_int32) env.fault_code,
+ "faultString", env.fault_string);
+ } else {
+ *resultPP = xmlrpc_build_value(envP, "(V)", resultValP);
+
+ xmlrpc_DECREF(resultValP);
+ }
+ xmlrpc_env_clean(&env);
+ }
+ xmlrpc_DECREF(paramArrayP);
+ xmlrpc_strfree(methodName);
+ }
+ }
+}
+
+
+
+static void
+getMethListFromMulticallPlist(xmlrpc_env * const envP,
+ xmlrpc_value * const paramArrayP,
+ xmlrpc_value ** const methlistPP) {
+
+ if (xmlrpc_array_size(envP, paramArrayP) != 1)
+ xmlrpc_env_set_fault_formatted(
+ envP, XMLRPC_PARSE_ERROR,
+ "system.multicall takes one parameter, which is an "
+ "array, each element describing one RPC. You "
+ "supplied %u arguments",
+ xmlrpc_array_size(envP, paramArrayP));
+ else {
+ xmlrpc_value * methlistP;
+
+ xmlrpc_array_read_item(envP, paramArrayP, 0, &methlistP);
+
+ XMLRPC_ASSERT_ENV_OK(envP);
+
+ if (xmlrpc_value_type(methlistP) != XMLRPC_TYPE_ARRAY)
+ xmlrpc_env_set_fault_formatted(
+ envP, XMLRPC_TYPE_ERROR,
+ "system.multicall's parameter should be an array, "
+ "each element describing one RPC. But it is type "
+ "%u instead.", xmlrpc_value_type(methlistP));
+ else
+ *methlistPP = methlistP;
+
+ if (envP->fault_occurred)
+ xmlrpc_DECREF(methlistP);
+ }
+}
+
+
+
+static xmlrpc_value *
+system_multicall(xmlrpc_env * const envP,
+ xmlrpc_value * const paramArrayP,
+ void * const serverInfo,
+ void * const callInfo) {
+
+ xmlrpc_registry * registryP;
+ xmlrpc_value * resultsP;
+ xmlrpc_value * methlistP;
+
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT_ARRAY_OK(paramArrayP);
+ XMLRPC_ASSERT_PTR_OK(serverInfo);
+
+ resultsP = NULL; /* defeat compiler warning */
+
+ /* Turn our arguments into something more useful. */
+ registryP = (xmlrpc_registry*) serverInfo;
+
+ getMethListFromMulticallPlist(envP, paramArrayP, &methlistP);
+ if (!envP->fault_occurred) {
+ /* Create an initially empty result list. */
+ resultsP = xmlrpc_array_new(envP);
+ if (!envP->fault_occurred) {
+ /* Loop over our input list, calling each method in turn. */
+ unsigned int const methodCount =
+ xmlrpc_array_size(envP, methlistP);
+ unsigned int i;
+ for (i = 0; i < methodCount && !envP->fault_occurred; ++i) {
+ xmlrpc_value * const methinfoP =
+ xmlrpc_array_get_item(envP, methlistP, i);
+
+ xmlrpc_value * resultP;
+
+ XMLRPC_ASSERT_ENV_OK(envP);
+
+ callOneMethod(envP, registryP, methinfoP, callInfo, &resultP);
+
+ if (!envP->fault_occurred) {
+ /* Append this method result to our master array. */
+ xmlrpc_array_append_item(envP, resultsP, resultP);
+ xmlrpc_DECREF(resultP);
+ }
+ }
+ if (envP->fault_occurred)
+ xmlrpc_DECREF(resultsP);
+ xmlrpc_DECREF(methlistP);
+ }
+ }
+ return resultsP;
+}
+
+
+
+static struct systemMethodReg const methodMulticall = {
+ "system.multicall",
+ &system_multicall,
+ "A:A",
+ "Process an array of calls, and return an array of results. Calls should "
+ "be structs of the form {'methodName': string, 'params': array}. Each "
+ "result will either be a single-item array containg the result value, or "
+ "a struct of the form {'faultCode': int, 'faultString': string}. This "
+ "is useful when you need to make lots of small calls without lots of "
+ "round trips.",
+};
+
+
+/*=========================================================================
+ system.listMethods
+=========================================================================*/
+
+
+static void
+createMethodListArray(xmlrpc_env * const envP,
+ xmlrpc_registry * const registryP,
+ xmlrpc_value ** const methodListPP) {
+/*----------------------------------------------------------------------------
+ Create as an XML-RPC array value a list of names of methods registered
+ in registry 'registryP'.
+
+ This is the type of value that the system.listMethods method is supposed
+ to return.
+-----------------------------------------------------------------------------*/
+ xmlrpc_value * methodListP;
+
+ methodListP = xmlrpc_array_new(envP);
+
+ if (!envP->fault_occurred) {
+ xmlrpc_methodNode * methodNodeP;
+ for (methodNodeP = registryP->methodListP->firstMethodP;
+ methodNodeP && !envP->fault_occurred;
+ methodNodeP = methodNodeP->nextP) {
+
+ xmlrpc_value * methodNameVP;
+
+ methodNameVP = xmlrpc_string_new(envP, methodNodeP->methodName);
+
+ if (!envP->fault_occurred) {
+ xmlrpc_array_append_item(envP, methodListP, methodNameVP);
+
+ xmlrpc_DECREF(methodNameVP);
+ }
+ }
+ if (envP->fault_occurred)
+ xmlrpc_DECREF(methodListP);
+ }
+ *methodListPP = methodListP;
+}
+
+
+
+static xmlrpc_value *
+system_listMethods(xmlrpc_env * const envP,
+ xmlrpc_value * const paramArrayP,
+ void * const serverInfo,
+ void * const callInfo ATTR_UNUSED) {
+
+ xmlrpc_registry * const registryP = serverInfo;
+
+ xmlrpc_value * retvalP;
+
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT_VALUE_OK(paramArrayP);
+ XMLRPC_ASSERT_PTR_OK(serverInfo);
+
+ xmlrpc_decompose_value(envP, paramArrayP, "()");
+ if (!envP->fault_occurred) {
+ if (!registryP->introspectionEnabled)
+ xmlrpc_env_set_fault_formatted(
+ envP, XMLRPC_INTROSPECTION_DISABLED_ERROR,
+ "Introspection is disabled in this server "
+ "for security reasons");
+ else
+ createMethodListArray(envP, registryP, &retvalP);
+ }
+ return retvalP;
+}
+
+
+
+static struct systemMethodReg const methodListMethods = {
+ "system.listMethods",
+ &system_listMethods,
+ "A:",
+ "Return an array of all available XML-RPC methods on this server.",
+};
+
+
+
+/*=========================================================================
+ system.methodHelp
+=========================================================================*/
+
+
+static void
+getHelpString(xmlrpc_env * const envP,
+ const char * const methodName,
+ xmlrpc_registry * const registryP,
+ xmlrpc_value ** const helpStringPP) {
+
+ xmlrpc_methodInfo * methodP;
+
+ xmlrpc_methodListLookupByName(registryP->methodListP, methodName,
+ &methodP);
+
+ if (!methodP)
+ xmlrpc_env_set_fault_formatted(
+ envP, XMLRPC_NO_SUCH_METHOD_ERROR,
+ "Method '%s' does not exist", methodName);
+ else
+ *helpStringPP = xmlrpc_string_new(envP, methodP->helpText);
+}
+
+
+
+static xmlrpc_value *
+system_methodHelp(xmlrpc_env * const envP,
+ xmlrpc_value * const paramArrayP,
+ void * const serverInfo,
+ void * const callInfo ATTR_UNUSED) {
+
+ xmlrpc_registry * const registryP = serverInfo;
+
+ xmlrpc_value * retvalP;
+
+ const char * methodName;
+
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT_VALUE_OK(paramArrayP);
+ XMLRPC_ASSERT_PTR_OK(serverInfo);
+
+ xmlrpc_decompose_value(envP, paramArrayP, "(s)", &methodName);
+
+ if (!envP->fault_occurred) {
+ if (!registryP->introspectionEnabled)
+ xmlrpc_env_set_fault_formatted(
+ envP, XMLRPC_INTROSPECTION_DISABLED_ERROR,
+ "Introspection is disabled in this server "
+ "for security reasons");
+ else
+ getHelpString(envP, methodName, registryP, &retvalP);
+ }
+
+ xmlrpc_strfree(methodName);
+
+ return retvalP;
+}
+
+
+static struct systemMethodReg const methodMethodHelp = {
+ "system.methodHelp",
+ &system_methodHelp,
+ "s:s",
+ "Given the name of a method, return a help string.",
+};
+
+
+
+/*=========================================================================
+ system.methodSignature
+==========================================================================*/
+
+static void
+buildNoSigSuppliedResult(xmlrpc_env * const envP,
+ xmlrpc_value ** const resultPP) {
+
+ xmlrpc_env env;
+
+ xmlrpc_env_init(&env);
+
+ *resultPP = xmlrpc_string_new(&env, "undef");
+ if (env.fault_occurred)
+ xmlrpc_faultf(envP, "Unable to construct 'undef'. %s",
+ env.fault_string);
+
+ xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+buildSignatureValue(xmlrpc_env * const envP,
+ struct xmlrpc_signature * const signatureP,
+ xmlrpc_value ** const sigValuePP) {
+
+ xmlrpc_value * sigValueP;
+ unsigned int i;
+
+ sigValueP = xmlrpc_array_new(envP);
+
+ {
+ xmlrpc_value * retTypeVP;
+
+ retTypeVP = xmlrpc_string_new(envP, signatureP->retType);
+
+ xmlrpc_array_append_item(envP, sigValueP, retTypeVP);
+
+ xmlrpc_DECREF(retTypeVP);
+ }
+ for (i = 0; i < signatureP->argCount && !envP->fault_occurred; ++i) {
+ xmlrpc_value * argTypeVP;
+
+ argTypeVP = xmlrpc_string_new(envP, signatureP->argList[i]);
+ if (!envP->fault_occurred) {
+ xmlrpc_array_append_item(envP, sigValueP, argTypeVP);
+
+ xmlrpc_DECREF(argTypeVP);
+ }
+ }
+
+ if (envP->fault_occurred)
+ xmlrpc_DECREF(sigValueP);
+ else
+ *sigValuePP = sigValueP;
+}
+
+
+
+static void
+getSignatureList(xmlrpc_env * const envP,
+ xmlrpc_registry * const registryP,
+ const char * const methodName,
+ xmlrpc_value ** const signatureListPP) {
+/*----------------------------------------------------------------------------
+ Get the signature list array for method named 'methodName' from registry
+ 'registryP'.
+
+ If there is no signature information for the method in the registry,
+ return *signatureListPP == NULL.
+
+ Nonexistent method is considered a failure.
+-----------------------------------------------------------------------------*/
+ xmlrpc_methodInfo * methodP;
+
+ xmlrpc_methodListLookupByName(registryP->methodListP, methodName,
+ &methodP);
+
+ if (!methodP)
+ xmlrpc_env_set_fault_formatted(
+ envP, XMLRPC_NO_SUCH_METHOD_ERROR,
+ "Method '%s' does not exist", methodName);
+ else {
+ if (!methodP->signatureListP->firstSignatureP)
+ *signatureListPP = NULL;
+ else {
+ xmlrpc_value * signatureListP;
+
+ signatureListP = xmlrpc_array_new(envP);
+
+ if (!envP->fault_occurred) {
+ struct xmlrpc_signature * signatureP;
+ for (signatureP = methodP->signatureListP->firstSignatureP;
+ signatureP && !envP->fault_occurred;
+ signatureP = signatureP->nextP) {
+
+ xmlrpc_value * signatureVP;
+
+ buildSignatureValue(envP, signatureP, &signatureVP);
+
+ xmlrpc_array_append_item(envP,
+ signatureListP, signatureVP);
+
+ xmlrpc_DECREF(signatureVP);
+ }
+ if (envP->fault_occurred)
+ xmlrpc_DECREF(signatureListP);
+ }
+ *signatureListPP = signatureListP;
+ }
+ }
+}
+
+
+
+static xmlrpc_value *
+system_methodSignature(xmlrpc_env * const envP,
+ xmlrpc_value * const paramArrayP,
+ void * const serverInfo,
+ void * const callInfo ATTR_UNUSED) {
+
+ xmlrpc_registry * const registryP = (xmlrpc_registry *) serverInfo;
+
+ xmlrpc_value * retvalP;
+ const char * methodName;
+ xmlrpc_env env;
+
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT_VALUE_OK(paramArrayP);
+ XMLRPC_ASSERT_PTR_OK(serverInfo);
+
+ retvalP = NULL; /* quiet compiler unset variable warning */
+
+ xmlrpc_env_init(&env);
+
+ /* Turn our arguments into something more useful. */
+ xmlrpc_decompose_value(&env, paramArrayP, "(s)", &methodName);
+ if (env.fault_occurred)
+ xmlrpc_env_set_fault_formatted(
+ envP, env.fault_code,
+ "Invalid parameter list. %s", env.fault_string);
+ else {
+ if (!registryP->introspectionEnabled)
+ xmlrpc_env_set_fault(envP, XMLRPC_INTROSPECTION_DISABLED_ERROR,
+ "Introspection disabled on this server");
+ else {
+ xmlrpc_value * signatureListP;
+
+ getSignatureList(envP, registryP, methodName, &signatureListP);
+
+ if (!envP->fault_occurred) {
+ if (signatureListP)
+ retvalP = signatureListP;
+ else
+ buildNoSigSuppliedResult(envP, &retvalP);
+ }
+ }
+ xmlrpc_strfree(methodName);
+ }
+ xmlrpc_env_clean(&env);
+
+ return retvalP;
+}
+
+
+
+static struct systemMethodReg const methodMethodSignature = {
+ "system.methodSignature",
+ &system_methodSignature,
+ "s:s",
+ "Given the name of a method, return an array of legal signatures. "
+ "Each signature is an array of strings. The first item of each signature "
+ "is the return type, and any others items are parameter types.",
+};
+
+
+
+
+/*=========================================================================
+ system.shutdown
+==========================================================================*/
+
+static xmlrpc_value *
+system_shutdown(xmlrpc_env * const envP,
+ xmlrpc_value * const paramArrayP,
+ void * const serverInfo,
+ void * const callInfo) {
+
+ xmlrpc_registry * const registryP = (xmlrpc_registry *) serverInfo;
+
+ xmlrpc_value * retvalP;
+ const char * comment;
+ xmlrpc_env env;
+
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT_VALUE_OK(paramArrayP);
+ XMLRPC_ASSERT_PTR_OK(serverInfo);
+
+ xmlrpc_env_init(&env);
+
+ retvalP = NULL; /* quiet compiler warning */
+
+ /* Turn our arguments into something more useful. */
+ xmlrpc_decompose_value(&env, paramArrayP, "(s)", &comment);
+ if (env.fault_occurred)
+ xmlrpc_env_set_fault_formatted(
+ envP, env.fault_code,
+ "Invalid parameter list. %s", env.fault_string);
+ else {
+ if (!registryP->shutdownServerFn)
+ xmlrpc_env_set_fault(
+ envP, 0, "This server program is not capable of "
+ "shutting down");
+ else {
+ registryP->shutdownServerFn(
+ &env, registryP->shutdownContext, comment, callInfo);
+
+ if (env.fault_occurred)
+ xmlrpc_env_set_fault(envP, env.fault_code, env.fault_string);
+ else {
+ retvalP = xmlrpc_int_new(&env, 0);
+
+ if (env.fault_occurred)
+ xmlrpc_faultf(envP,
+ "Failed to construct return value. %s",
+ env.fault_string);
+ }
+ }
+ xmlrpc_strfree(comment);
+ }
+ xmlrpc_env_clean(&env);
+
+ return retvalP;
+}
+
+
+
+static struct systemMethodReg const methodShutdown = {
+ "system.shutdown",
+ &system_shutdown,
+ "i:s",
+ "Shut down the server. Return code is always zero.",
+};
+
+
+
+/*=========================================================================
+ system.capabilities
+=========================================================================*/
+
+static void
+getCapabilities(xmlrpc_env * const envP,
+ xmlrpc_registry * const registryP ATTR_UNUSED,
+ xmlrpc_value ** const capabilitiesPP) {
+
+ *capabilitiesPP =
+ xmlrpc_build_value(
+ envP, "{s:s,s:i,s:i,s:i,s:i}",
+ "facility", "xmlrpc-c",
+ "version_major", XMLRPC_VERSION_MAJOR,
+ "version_minor", XMLRPC_VERSION_MINOR,
+ "version_point", XMLRPC_VERSION_POINT,
+ "protocol_version", 2
+ );
+
+}
+
+
+
+static xmlrpc_value *
+system_capabilities(xmlrpc_env * const envP,
+ xmlrpc_value * const paramArrayP,
+ void * const serverInfo,
+ void * const callInfo ATTR_UNUSED) {
+
+ xmlrpc_registry * const registryP = serverInfo;
+
+ xmlrpc_value * retvalP;
+
+ unsigned int paramCount;
+
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT_VALUE_OK(paramArrayP);
+ XMLRPC_ASSERT_PTR_OK(serverInfo);
+
+ paramCount = xmlrpc_array_size(envP, paramArrayP);
+
+ if (paramCount > 0)
+ xmlrpc_env_set_fault_formatted(
+ envP, XMLRPC_INDEX_ERROR,
+ "There are no parameters. You supplied %u", paramCount);
+ else
+ getCapabilities(envP, registryP, &retvalP);
+
+ return retvalP;
+}
+
+
+static struct systemMethodReg const methodCapabilities = {
+ "system.capabilities",
+ &system_capabilities,
+ "S:",
+ "Return the capabilities of XML-RPC server. This includes the "
+ "version number of the XML-RPC For C/C++ software"
+};
+
+
+
+/*============================================================================
+ Installer of system methods
+============================================================================*/
+
+static void
+registerSystemMethod(xmlrpc_env * const envP,
+ xmlrpc_registry * const registryP,
+ struct systemMethodReg const methodReg) {
+
+ xmlrpc_env env;
+ xmlrpc_env_init(&env);
+
+ xmlrpc_registry_add_method2(
+ &env, registryP, methodReg.methodName,
+ methodReg.methodFunction,
+ methodReg.signatureString, methodReg.helpText, registryP);
+
+ if (env.fault_occurred)
+ xmlrpc_faultf(envP, "Failed to register '%s' system method. %s",
+ methodReg.methodName, env.fault_string);
+
+ xmlrpc_env_clean(&env);
+}
+
+
+
+void
+xmlrpc_installSystemMethods(xmlrpc_env * const envP,
+ xmlrpc_registry * const registryP) {
+/*----------------------------------------------------------------------------
+ Install the built-in methods (system.*) into registry 'registryP'.
+-----------------------------------------------------------------------------*/
+ if (!envP->fault_occurred)
+ registerSystemMethod(envP, registryP, methodListMethods);
+
+ if (!envP->fault_occurred)
+ registerSystemMethod(envP, registryP, methodMethodSignature);
+
+ if (!envP->fault_occurred)
+ registerSystemMethod(envP, registryP, methodMethodHelp);
+
+ if (!envP->fault_occurred)
+ registerSystemMethod(envP, registryP, methodMulticall);
+
+ if (!envP->fault_occurred)
+ registerSystemMethod(envP, registryP, methodShutdown);
+
+ if (!envP->fault_occurred)
+ registerSystemMethod(envP, registryP, methodCapabilities);
+}
+
+
+
+/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
+** Copyright (C) 2001 by Eric Kidd. All rights reserved.
+** Copyright (C) 2001 by Luke Howard. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR 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. */
+
Added: freeswitch/trunk/libs/xmlrpc-c/src/system_method.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/system_method.h Fri May 23 16:56:24 2008
@@ -0,0 +1,14 @@
+#ifndef SYSTEM_METHOD_H_INCLUDED
+#define SYSTEM_METHOD_H_INCLUDED
+
+
+void
+xmlrpc_installSystemMethods(struct _xmlrpc_env * const envP,
+ struct xmlrpc_registry * const registryP);
+
+void
+xmlrpc_buildSignatureArray(xmlrpc_env * const envP,
+ const char * const sigListString,
+ xmlrpc_value ** const resultPP);
+
+#endif
Added: freeswitch/trunk/libs/xmlrpc-c/src/test/Makefile
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/test/Makefile Fri May 23 16:56:24 2008
@@ -0,0 +1,97 @@
+ifeq ($(SRCDIR),)
+ updir = $(shell echo $(dir $(1)) | sed 's/.$$//')
+ srcDIR := $(call updir,$(CURDIR))
+ SRCDIR := $(call updir,$(srcDIR))
+ BLDDIR := $(SRCDIR)
+endif
+SUBDIR := src/test
+
+include $(BLDDIR)/config.mk
+
+XMLRPC_C_CONFIG = $(BLDDIR)/xmlrpc-c-config.test
+
+LDADD_CLIENT = \
+ $(shell $(XMLRPC_C_CONFIG) client --ldadd)
+LDADD_ABYSS_SERVER = \
+ $(shell $(XMLRPC_C_CONFIG) abyss-server --ldadd)
+LDADD_CGI_SERVER = \
+ $(shell $(XMLRPC_C_CONFIG) cgi-server --ldadd)
+
+default: all
+
+INCLUDES = -I$(BLDDIR) -I $(SRCDIR)/include -I$(SRCDIR)/lib/util/include \
+
+PROGS = test cgitest1
+
+all: $(PROGS)
+
+LDFLAGS = $(LADD)
+
+TEST_OBJS = \
+ test.o \
+ abyss.o \
+ cgi.o \
+ method_registry.o \
+ parse_xml.o \
+ serialize.o \
+ serialize_value.o \
+ server_abyss.o \
+ value.o \
+ xml_data.o \
+
+ifeq ($(MUST_BUILD_CLIENT),yes)
+ TEST_OBJS += client.o
+ LIBXMLRPC_CLIENT_DEP = $(LIBXMLRPC_CLIENT_A)
+else
+ TEST_OBJS += client_dummy.o
+ LIBXMLRPC_CLIENT_DEP =
+endif
+
+include $(SRCDIR)/common.mk
+
+test: \
+ $(XMLRPC_C_CONFIG) \
+ $(TEST_OBJS) $(LIBXMLRPC_A) $(LIBXMLRPC_UTIL_A) \
+ $(LIBXMLRPC_SERVER_A) $(LIBXMLRPC_SERVER_ABYSS_A) $(LIBXMLRPC_XML) \
+ $(LIBXMLRPC_CLIENT_DEP) $(LIBXMLRPC_ABYSS_A) \
+ $(LIBXMLRPC_XMLPARSE_A) $(LIBXMLRPC_XMLTOK_A) \
+ $(CASPRINTF)
+ $(CCLD) -o $@ $(LDFLAGS) \
+ $(TEST_OBJS) $(LDADD_CLIENT) $(LDADD_ABYSS_SERVER) $(CASPRINTF)
+
+cgitest1:%:%.o $(LIBXMLRPC_SERVER_A) $(LIBXMLRPC_SERVER_CGI_A) \
+ $(LIBXMLRPC_A) $(LIBXMLRPC_UTIL_A) $(LIBXMLRPC_XML)
+ $(CCLD) -o $@ $< $(LDFLAGS) $(LDADD_CGI_SERVER)
+
+CFLAGS = $(CFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD)
+
+OBJS = $(TEST_OBJS) cgitest1.o
+
+$(OBJS):%.o:%.c
+ $(CC) -c $(INCLUDES) $(CFLAGS) $<
+
+# Note the difference between 'check' and 'runtests'. 'check' means to check
+# our own correctness. 'runtests' means to run the tests that check our
+# parent's correctness
+
+.PHONY: check
+check:
+
+.PHONY: runtests
+runtests: test cgitest1
+ ./test
+
+.PHONY: install
+install:
+
+.PHONY: clean clean-local distclean
+clean: clean-common clean-local
+clean-local:
+ rm -f $(PROGS)
+
+distclean: clean distclean-common
+
+.PHONY: dep
+dep: dep-common
+
+include Makefile.depend
Added: freeswitch/trunk/libs/xmlrpc-c/src/test/abyss.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/test/abyss.c Fri May 23 16:56:24 2008
@@ -0,0 +1,342 @@
+/* None of the tests in here rely on a client existing, or even a network
+ connection. We should figure out how to create a test client and do
+ such tests.
+*/
+
+#include "unistdx.h"
+#include <stdio.h>
+#ifndef WIN32
+#include <sys/socket.h>
+#include <netinet/in.h>
+#endif
+#include <errno.h>
+#include <string.h>
+
+#include "xmlrpc_config.h"
+
+#include "int.h"
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/server.h"
+#include "xmlrpc-c/abyss.h"
+
+#include "test.h"
+
+#include "abyss.h"
+
+
+
+static void
+bindSocketToPort(int const fd,
+ uint16_t const portNumber) {
+
+ struct sockaddr_in name;
+ int rc;
+
+ name.sin_family = AF_INET;
+ name.sin_port = htons(portNumber);
+ name.sin_addr.s_addr = INADDR_ANY;
+
+ rc = bind(fd, (struct sockaddr *)&name, sizeof(name));
+ if (rc != 0)
+ fprintf(stderr, "bind() of %d failed, errno=%d (%s)",
+ fd, errno, strerror(errno));
+
+ TEST(rc == 0);
+}
+
+
+
+static void
+chanSwitchCreateFd(int const fd,
+ TChanSwitch ** const chanSwitchPP,
+ const char ** const errorP) {
+
+#ifdef WIN32
+ ChanSwitchWinCreateWinsock(fd, chanSwitchPP, errorP);
+#else
+ ChanSwitchUnixCreateFd(fd, chanSwitchPP, errorP);
+#endif
+}
+
+
+
+static void
+closesock(int const fd) {
+#ifdef WIN32
+ closesocket(fd);
+#else
+ close(fd);
+#endif
+}
+
+
+
+static void
+chanSwitchCreate(uint16_t const portNumber,
+ TChanSwitch ** const chanSwitchPP,
+ const char ** const errorP) {
+
+#ifdef WIN32
+ ChanSwitchWinCreate(portNumber, chanSwitchPP, errorP);
+#else
+ ChanSwitchUnixCreate(portNumber, chanSwitchPP, errorP);
+#endif
+}
+
+
+
+static void
+channelCreateFd(int const fd,
+ TChannel ** const channelPP,
+ const char ** const errorP) {
+
+#ifdef WIN32
+ struct abyss_win_chaninfo * channelInfoP;
+ ChannelWinCreateWinsock(fd, channelPP, &channelInfoP, errorP);
+#else
+ struct abyss_unix_chaninfo * channelInfoP;
+ ChannelUnixCreateFd(fd, channelPP, &channelInfoP, errorP);
+#endif
+}
+
+
+
+static void
+testChanSwitchOsSocket(void) {
+
+ int rc;
+
+ rc = socket(AF_INET, SOCK_STREAM, 0);
+ if (rc < 0) {
+ fprintf(stderr, "socket() failed with errno %d (%s)",
+ errno, strerror(errno));
+ abort();
+ } else {
+ int const fd = rc;
+
+ TChanSwitch * chanSwitchP;
+ TServer server;
+ const char * error;
+
+ bindSocketToPort(fd, 8080);
+
+ chanSwitchCreateFd(fd, &chanSwitchP, &error);
+
+ TEST_NULL_STRING(error);
+
+ ServerCreateSwitch(&server, chanSwitchP, &error);
+
+ TEST_NULL_STRING(error);
+
+ ServerFree(&server);
+
+ ChanSwitchDestroy(chanSwitchP);
+
+ closesock(fd);
+ }
+}
+
+
+
+static void
+testChanSwitch(void) {
+
+ TServer server;
+ TChanSwitch * chanSwitchP;
+ const char * error;
+
+ chanSwitchCreate(8080, &chanSwitchP, &error);
+
+ TEST_NULL_STRING(error);
+
+ ServerCreateSwitch(&server, chanSwitchP, &error);
+
+ TEST_NULL_STRING(error);
+
+ ServerFree(&server);
+
+ ChanSwitchDestroy(chanSwitchP);
+
+ testChanSwitchOsSocket();
+}
+
+
+
+static void
+testChannel(void) {
+
+ int rc;
+
+ rc = socket(AF_INET, SOCK_STREAM, 0);
+ if (rc < 0) {
+ fprintf(stderr, "socket() failed with errno %d (%s)",
+ errno, strerror(errno));
+ abort();
+ } else {
+ int const fd = rc;
+
+ TChannel * channelP;
+ const char * error;
+
+ channelCreateFd(fd, &channelP, &error);
+
+ TEST(error);
+
+ TEST(strstr(error, "not in connected"));
+ }
+}
+
+
+
+static void
+testOsSocket(void) {
+
+ int rc;
+
+ rc = socket(AF_INET, SOCK_STREAM, 0);
+ if (rc < 0) {
+ fprintf(stderr, "socket() failed with errno %d (%s)",
+ errno, strerror(errno));
+ abort();
+ } else {
+ int const fd = rc;
+
+ TServer server;
+ abyss_bool success;
+
+ bindSocketToPort(fd, 8080);
+
+ success = ServerCreateSocket(&server, NULL, fd, NULL, NULL);
+
+ TEST(success);
+
+ ServerFree(&server);
+
+ closesock(fd);
+ }
+}
+
+
+
+static void
+testSocket(void) {
+
+#ifndef WIN32
+ int rc;
+
+ rc = socket(AF_INET, SOCK_STREAM, 0);
+ if (rc < 0) {
+ fprintf(stderr, "socket() failed with errno %d (%s)",
+ errno, strerror(errno));
+ abort();
+ } else {
+ int const fd = rc;
+
+ TSocket * socketP;
+ TServer server;
+ const char * error;
+
+ SocketUnixCreateFd(fd, &socketP);
+
+ TEST(socketP != NULL);
+
+ ServerCreateSocket2(&server, socketP, &error);
+
+ TEST(!error);
+
+ ServerFree(&server);
+
+ SocketDestroy(socketP);
+
+ close(fd);
+ }
+#endif
+}
+
+
+
+static void
+testServerCreate(void) {
+
+ TServer server;
+ abyss_bool success;
+
+ success = ServerCreate(&server, NULL, 8080, NULL, NULL);
+ TEST(success);
+ ServerInit(&server);
+ ServerFree(&server);
+
+ success = ServerCreate(&server, "myserver", 8080,
+ "/tmp/docroot", "/tmp/logfile");
+ TEST(success);
+ ServerInit(&server);
+ ServerFree(&server);
+
+ success = ServerCreateNoAccept(&server, NULL, NULL, NULL);
+ TEST(success);
+ ServerFree(&server);
+
+ {
+ TChanSwitch * chanSwitchP;
+ const char * error;
+
+ chanSwitchCreate(8080, &chanSwitchP, &error);
+
+ TEST_NULL_STRING(error);
+
+ ServerCreateSwitch(&server, chanSwitchP, &error);
+
+ TEST_NULL_STRING(error);
+
+ ServerSetName(&server, "/tmp/docroot");
+ ServerSetLogFileName(&server, "/tmp/logfile");
+ ServerSetKeepaliveTimeout(&server, 50);
+ ServerSetKeepaliveMaxConn(&server, 5);
+ ServerSetTimeout(&server, 75);
+ ServerSetAdvertise(&server, 1);
+ ServerSetAdvertise(&server, 0);
+
+ ServerInit(&server);
+
+ ServerFree(&server);
+
+ ChanSwitchDestroy(chanSwitchP);
+ }
+}
+
+
+
+void
+test_abyss(void) {
+
+ const char * error;
+
+ printf("Running Abyss server tests...\n");
+
+ AbyssInit(&error);
+ TEST_NULL_STRING(error);
+
+ ChanSwitchInit(&error);
+ TEST_NULL_STRING(error);
+
+ ChannelInit(&error);
+ TEST_NULL_STRING(error);
+
+ testChanSwitch();
+
+ testChannel();
+
+ testOsSocket();
+
+ testSocket();
+
+ testServerCreate();
+
+ ChannelTerm();
+ ChanSwitchTerm();
+ AbyssTerm();
+
+ printf("\n");
+ printf("Abyss server tests done.\n");
+}
+
Added: freeswitch/trunk/libs/xmlrpc-c/src/test/abyss.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/test/abyss.h Fri May 23 16:56:24 2008
@@ -0,0 +1,2 @@
+void
+test_abyss(void);
Modified: freeswitch/trunk/libs/xmlrpc-c/src/test/cgi.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/src/test/cgi.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/src/test/cgi.c Fri May 23 16:56:24 2008
@@ -21,6 +21,8 @@
"</methodResponse>\r\n";
+#define TESTDATA_DIR "data"
+#define DIRSEP DIRECTORY_SEPARATOR
void
test_server_cgi(void) {
@@ -36,7 +38,8 @@
"CONTENT_TYPE=text/xml "
"CONTENT_LENGTH=211 "
"./cgitest1 "
- "<sample_add_call.xml",
+ "<"
+ TESTDATA_DIR DIRSEP "sample_add_call.xml",
"r");
if (cgiOutputP == NULL)
@@ -51,6 +54,7 @@
TEST(memcmp(cgiResponse, cgiResponse1, bytesRead) == 0);
}
+ fclose(cgiOutputP);
printf("\n");
printf("CGI tests done.\n");
}
Modified: freeswitch/trunk/libs/xmlrpc-c/src/test/client.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/src/test/client.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/src/test/client.c Fri May 23 16:56:24 2008
@@ -4,17 +4,285 @@
#include <errno.h>
#include "xmlrpc_config.h"
+#include "transport_config.h"
#include "xmlrpc-c/base.h"
#include "xmlrpc-c/client.h"
+#include "xmlrpc-c/transport.h"
#include "test.h"
#include "client.h"
+static void
+testGlobalConst(void) {
+
+ xmlrpc_env env;
+ xmlrpc_env_init(&env);
+
+ xmlrpc_client_setup_global_const(&env);
+ TEST_NO_FAULT(&env);
+
+ xmlrpc_client_teardown_global_const();
+
+ xmlrpc_client_setup_global_const(&env);
+ TEST_NO_FAULT(&env);
+ xmlrpc_client_setup_global_const(&env);
+ TEST_NO_FAULT(&env);
+
+ xmlrpc_client_teardown_global_const();
+ xmlrpc_client_teardown_global_const();
+
+ xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+testCreateCurlParms(void) {
+
+#if MUST_BUILD_CURL_CLIENT
+
+ xmlrpc_env env;
+ xmlrpc_client * clientP;
+ struct xmlrpc_clientparms clientParms1;
+ struct xmlrpc_curl_xportparms curlTransportParms1;
+
+ xmlrpc_env_init(&env);
+
+ clientParms1.transport = "curl";
+ clientParms1.transportparmsP = &curlTransportParms1;
+
+ curlTransportParms1.network_interface = "eth0";
+ clientParms1.transportparm_size = XMLRPC_CXPSIZE(network_interface);
+ xmlrpc_client_create(&env, 0, "testprog", "1.0",
+ &clientParms1, XMLRPC_CPSIZE(transportparm_size),
+ &clientP);
+ TEST_NO_FAULT(&env);
+ xmlrpc_client_destroy(clientP);
+
+ curlTransportParms1.no_ssl_verifypeer = 1;
+ curlTransportParms1.no_ssl_verifyhost = 1;
+ clientParms1.transportparm_size = XMLRPC_CXPSIZE(no_ssl_verifyhost);
+ xmlrpc_client_create(&env, 0, "testprog", "1.0",
+ &clientParms1, XMLRPC_CPSIZE(transportparm_size),
+ &clientP);
+ TEST_NO_FAULT(&env);
+ xmlrpc_client_destroy(clientP);
+
+ curlTransportParms1.user_agent = "testprog/1.0";
+ clientParms1.transportparm_size = XMLRPC_CXPSIZE(user_agent);
+ xmlrpc_client_create(&env, 0, "testprog", "1.0",
+ &clientParms1, XMLRPC_CPSIZE(transportparm_size),
+ &clientP);
+ TEST_NO_FAULT(&env);
+ xmlrpc_client_destroy(clientP);
+
+ xmlrpc_env_clean(&env);
+#endif /* MUST_BUILD_CURL_CLIENT */
+}
+
+
+
+static void
+testCreateSeparateXport(void) {
+
+#if MUST_BUILD_CURL_CLIENT
+ xmlrpc_env env;
+ xmlrpc_client * clientP;
+ struct xmlrpc_clientparms clientParms1;
+ struct xmlrpc_curl_xportparms curlTransportParms1;
+ struct xmlrpc_client_transport * transportP;
+
+ xmlrpc_env_init(&env);
+
+ xmlrpc_curl_transport_ops.create(
+ &env, 0, "", "", &curlTransportParms1, 0,
+ &transportP);
+
+ TEST_NO_FAULT(&env);
+
+ clientParms1.transport = NULL;
+ clientParms1.transportparmsP = NULL;
+ clientParms1.transportparm_size = 0;
+ clientParms1.transportOpsP = NULL;
+ clientParms1.transportP = NULL;
+
+ xmlrpc_client_create(&env, 0, "", "",
+ &clientParms1, XMLRPC_CPSIZE(transportP),
+ &clientP);
+ TEST_NO_FAULT(&env);
+
+ clientParms1.transport = "curl";
+ clientParms1.transportparmsP = &curlTransportParms1;
+ clientParms1.transportparm_size = 0;
+ clientParms1.transportOpsP = NULL;
+ clientParms1.transportP = NULL;
+
+ xmlrpc_client_create(&env, 0, "", "",
+ &clientParms1, XMLRPC_CPSIZE(transportP),
+ &clientP);
+ TEST_NO_FAULT(&env);
+
+ clientParms1.transportP = transportP;
+ xmlrpc_client_create(&env, 0, "", "",
+ &clientParms1, XMLRPC_CPSIZE(transportP),
+ &clientP);
+ TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+ /* Both transportP and transport specified */
+
+ clientParms1.transport = NULL;
+ clientParms1.transportparmsP = NULL;
+ clientParms1.transportparm_size = 0;
+ clientParms1.transportOpsP = &xmlrpc_curl_transport_ops;
+ clientParms1.transportP = transportP;
+
+ xmlrpc_client_create(&env, 0, "", "",
+ &clientParms1, XMLRPC_CPSIZE(transportOpsP),
+ &clientP);
+
+ TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+ /* transportOpsP but no transportP */
+
+ xmlrpc_client_create(&env, 0, "", "",
+ &clientParms1, XMLRPC_CPSIZE(transportP),
+ &clientP);
+
+ TEST_NO_FAULT(&env);
+
+ xmlrpc_curl_transport_ops.destroy(transportP);
+
+ xmlrpc_env_clean(&env);
+
+#endif /* MUST_BUILD_CURL_CLIENT */
+}
+
+
+
+static void
+testCreateDestroy(void) {
+
+ xmlrpc_env env;
+ xmlrpc_client * clientP;
+ struct xmlrpc_clientparms clientParms1;
+ struct xmlrpc_curl_xportparms curlTransportParms1;
+ int interrupt;
+
+ xmlrpc_env_init(&env);
+
+ xmlrpc_client_create(&env, 0, "testprog", "1.0", NULL, 0, &clientP);
+ TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+ /* Didn't set up global const */
+
+ xmlrpc_client_setup_global_const(&env);
+ TEST_NO_FAULT(&env);
+
+ xmlrpc_client_create(&env, 0, "testprog", "1.0", NULL, 0, &clientP);
+ TEST_NO_FAULT(&env);
+ xmlrpc_client_destroy(clientP);
+
+ xmlrpc_client_create(&env, 0, "testprog", "1.0", &clientParms1, 0,
+ &clientP);
+ TEST_NO_FAULT(&env);
+ xmlrpc_client_destroy(clientP);
+
+ clientParms1.transport = "curl";
+ xmlrpc_client_create(&env, 0, "testprog", "1.0",
+ &clientParms1, XMLRPC_CPSIZE(transport), &clientP);
+ TEST_NO_FAULT(&env);
+ xmlrpc_client_destroy(clientP);
+
+ clientParms1.transportparmsP = NULL;
+ xmlrpc_client_create(&env, 0, "testprog", "1.0",
+ &clientParms1, XMLRPC_CPSIZE(transportparmsP),
+ &clientP);
+ TEST_NO_FAULT(&env);
+ xmlrpc_client_destroy(clientP);
+
+ clientParms1.transportOpsP = NULL;
+ clientParms1.transportP = NULL;
+ clientParms1.dialect = xmlrpc_dialect_apache;
+ xmlrpc_client_create(&env, 0, "testprog", "1.0",
+ &clientParms1, XMLRPC_CPSIZE(dialect),
+ &clientP);
+ TEST_NO_FAULT(&env);
+ xmlrpc_client_destroy(clientP);
+
+ clientParms1.transportparmsP = &curlTransportParms1;
+
+ xmlrpc_client_create(&env, 0, "testprog", "1.0",
+ &clientParms1, XMLRPC_CPSIZE(transportparmsP),
+ &clientP);
+ TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+
+ clientParms1.transportparm_size = 0;
+ xmlrpc_client_create(&env, 0, "testprog", "1.0",
+ &clientParms1, XMLRPC_CPSIZE(transportparm_size),
+ &clientP);
+ TEST_NO_FAULT(&env);
+
+ xmlrpc_client_set_interrupt(clientP, &interrupt);
+ xmlrpc_client_set_interrupt(clientP, NULL);
+
+ xmlrpc_client_destroy(clientP);
+
+ testCreateCurlParms();
+
+ testCreateSeparateXport();
+
+ xmlrpc_client_teardown_global_const();
+
+ xmlrpc_env_clean(&env);
+}
+
+
static void
-test_init_cleanup(void) {
+testSynchCall(void) {
+
+ xmlrpc_env env;
+ xmlrpc_client * clientP;
+ xmlrpc_value * resultP;
+ xmlrpc_value * emptyArrayP;
+ xmlrpc_server_info * noSuchServerInfoP;
+
+ xmlrpc_env_init(&env);
+
+ emptyArrayP = xmlrpc_array_new(&env);
+ TEST_NO_FAULT(&env);
+
+ xmlrpc_client_setup_global_const(&env);
+ TEST_NO_FAULT(&env);
+
+ xmlrpc_client_create(&env, 0, "testprog", "1.0", NULL, 0, &clientP);
+ TEST_NO_FAULT(&env);
+
+ noSuchServerInfoP = xmlrpc_server_info_new(&env, "nosuchserver");
+ TEST_NO_FAULT(&env);
+
+ xmlrpc_client_call2(&env, clientP, noSuchServerInfoP, "nosuchmethod",
+ emptyArrayP, &resultP);
+ TEST_FAULT(&env, XMLRPC_NETWORK_ERROR); /* No such server */
+
+ xmlrpc_client_call2f(&env, clientP, "nosuchserver", "nosuchmethod",
+ &resultP, "(i)", 7);
+ TEST_FAULT(&env, XMLRPC_NETWORK_ERROR); /* No such server */
+
+ xmlrpc_server_info_free(noSuchServerInfoP);
+
+ xmlrpc_client_destroy(clientP);
+
+ xmlrpc_DECREF(emptyArrayP);
+
+ xmlrpc_client_teardown_global_const();
+
+ xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+testInitCleanup(void) {
xmlrpc_env env;
struct xmlrpc_clientparms clientParms1;
@@ -42,15 +310,13 @@
TEST_NO_FAULT(&env);
xmlrpc_client_cleanup();
- clientParms1.transportparmsP = (struct xmlrpc_xportparms *)
- &curlTransportParms1;
- {
- xmlrpc_env env2;
- xmlrpc_env_init(&env2);
- xmlrpc_client_init2(&env2, 0, "testprog", "1.0",
- &clientParms1, XMLRPC_CPSIZE(transportparmsP));
- TEST_FAULT(&env2, XMLRPC_INTERNAL_ERROR);
- }
+ clientParms1.transportparmsP = &curlTransportParms1;
+
+ /* Fails because we didn't include transportparm_size: */
+ xmlrpc_client_init2(&env, 0, "testprog", "1.0",
+ &clientParms1, XMLRPC_CPSIZE(transportparmsP));
+ TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+
clientParms1.transportparm_size = 0;
xmlrpc_client_init2(&env, 0, "testprog", "1.0",
&clientParms1, XMLRPC_CPSIZE(transportparm_size));
@@ -82,6 +348,69 @@
xmlrpc_client_init(0, "testprog", "1.0");
TEST_NO_FAULT(&env);
xmlrpc_client_cleanup();
+
+ xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+testServerInfo(void) {
+
+ xmlrpc_env env;
+ xmlrpc_server_info * serverInfoP;
+ xmlrpc_server_info * serverInfo2P;
+
+ printf(" Running serverInfo tests...\n");
+
+ xmlrpc_env_init(&env);
+
+ serverInfoP = xmlrpc_server_info_new(&env, "testurl");
+ TEST_NO_FAULT(&env);
+
+ serverInfo2P = xmlrpc_server_info_copy(&env, serverInfoP);
+ TEST_NO_FAULT(&env);
+
+ xmlrpc_server_info_free(serverInfo2P);
+
+ /* Fails because we haven't set user/password yet: */
+ xmlrpc_server_info_allow_auth_basic(&env, serverInfoP);
+ TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+
+ xmlrpc_server_info_set_basic_auth(&env, serverInfoP,
+ "username", "password");
+ TEST_NO_FAULT(&env);
+
+ xmlrpc_server_info_set_user(&env, serverInfoP, "username", "password");
+ TEST_NO_FAULT(&env);
+
+ xmlrpc_server_info_allow_auth_basic(&env, serverInfoP);
+ TEST_NO_FAULT(&env);
+
+ xmlrpc_server_info_disallow_auth_basic(&env, serverInfoP);
+ TEST_NO_FAULT(&env);
+
+ xmlrpc_server_info_allow_auth_digest(&env, serverInfoP);
+ TEST_NO_FAULT(&env);
+
+ xmlrpc_server_info_disallow_auth_digest(&env, serverInfoP);
+ TEST_NO_FAULT(&env);
+
+ xmlrpc_server_info_allow_auth_negotiate(&env, serverInfoP);
+ TEST_NO_FAULT(&env);
+
+ xmlrpc_server_info_disallow_auth_negotiate(&env, serverInfoP);
+ TEST_NO_FAULT(&env);
+
+ xmlrpc_server_info_allow_auth_ntlm(&env, serverInfoP);
+ TEST_NO_FAULT(&env);
+
+ xmlrpc_server_info_disallow_auth_ntlm(&env, serverInfoP);
+ TEST_NO_FAULT(&env);
+
+ xmlrpc_server_info_free(serverInfoP);
+
+ xmlrpc_env_clean(&env);
}
@@ -91,7 +420,11 @@
printf("Running client tests.");
- test_init_cleanup();
+ testGlobalConst();
+ testCreateDestroy();
+ testInitCleanup();
+ testServerInfo();
+ testSynchCall();
printf("\n");
printf("Client tests done.\n");
Added: freeswitch/trunk/libs/xmlrpc-c/src/test/client_dummy.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/test/client_dummy.c Fri May 23 16:56:24 2008
@@ -0,0 +1,14 @@
+#include <stdio.h>
+
+#include "client.h"
+
+
+
+void
+test_client(void) {
+
+ printf("Running dummy client test.");
+
+ printf("\n");
+ printf("Client tests done.\n");
+}
Added: freeswitch/trunk/libs/xmlrpc-c/src/test/data/req_no_params.xml
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/test/data/req_no_params.xml Fri May 23 16:56:24 2008
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- This may or may not be legal XML-RPC, but some old clients (including
+Ruby and xmlrpc-epi) send it. This should be interpreted as a call with no
+parameters. -->
+
+<methodCall>
+ <methodName>foo</methodName>
+</methodCall>
Added: freeswitch/trunk/libs/xmlrpc-c/src/test/data/req_out_of_order.xml
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/test/data/req_out_of_order.xml Fri May 23 16:56:24 2008
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<methodCall>
+ <params>
+ <param>
+ <value><int>2</int></value>
+ </param>
+ <param>
+ <value><int>2</int></value>
+ </param>
+ </params>
+ <methodName>add</methodName>
+</methodCall>
Added: freeswitch/trunk/libs/xmlrpc-c/src/test/data/req_value_name.xml
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/test/data/req_value_name.xml Fri May 23 16:56:24 2008
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<methodCall>
+ <methodName>foo</methodName>
+ <params>
+ <param>
+ <value><struct>
+ <member>
+ <value><i4>0</i4></value>
+ <name>child elements reversed!</name>
+ </member>
+ </struct></value>
+ </param>
+ </params>
+</methodCall>
Added: freeswitch/trunk/libs/xmlrpc-c/src/test/data/sample_add_call.xml
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/test/data/sample_add_call.xml Fri May 23 16:56:24 2008
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<methodCall>
+<methodName>sample.add</methodName>
+<params>
+<param><value><i4>5</i4></value></param>
+<param><value><i4>7</i4></value></param>
+</params>
+</methodCall>
Added: freeswitch/trunk/libs/xmlrpc-c/src/test/method_registry.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/test/method_registry.c Fri May 23 16:56:24 2008
@@ -0,0 +1,951 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include "int.h"
+#include "casprintf.h"
+#include "girstring.h"
+
+#include "xmlrpc_config.h"
+
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/server.h"
+
+#include "test.h"
+#include "xml_data.h"
+#include "method_registry.h"
+
+
+#define FOO_SERVERINFO ((void*) 0xF00)
+#define FOO_CALLINFO ((void*) 0xFC0)
+#define BAR_SERVERINFO ((void*) 0xBAF)
+#define BAR_CALLINFO ((void*) 0xBAC)
+#define MULTI_CALLINFO ((void*) 0xFFF)
+#define DEFAULT_SERVERINFO ((void*) 0xD00)
+#define DEFAULT_CALLINFO ((void*) 0xDC0)
+
+static const char * const barHelp = "This is the help for Method test.bar.";
+
+
+static xmlrpc_value *
+test_foo(xmlrpc_env * const envP,
+ xmlrpc_value * const paramArrayP,
+ void * const serverInfo,
+ void * const callInfo) {
+
+ xmlrpc_int32 x, y;
+
+ TEST_NO_FAULT(envP);
+ TEST(paramArrayP != NULL);
+ TEST(serverInfo == FOO_SERVERINFO);
+ TEST(callInfo == FOO_CALLINFO || callInfo == MULTI_CALLINFO);
+
+ xmlrpc_decompose_value(envP, paramArrayP, "(ii)", &x, &y);
+ TEST_NO_FAULT(envP);
+ TEST(x == 25);
+ TEST(y == 17);
+
+ return xmlrpc_build_value(envP, "i", (xmlrpc_int32) x + y);
+}
+
+
+
+static xmlrpc_value *
+test_foo_type1(xmlrpc_env * const envP,
+ xmlrpc_value * const paramArrayP,
+ void * const serverInfo) {
+
+ xmlrpc_int32 x, y;
+
+ TEST_NO_FAULT(envP);
+ TEST(paramArrayP != NULL);
+ TEST(serverInfo == FOO_SERVERINFO);
+
+ xmlrpc_decompose_value(envP, paramArrayP, "(ii)", &x, &y);
+ TEST_NO_FAULT(envP);
+ TEST(x == 25);
+ TEST(y == 17);
+
+ return xmlrpc_build_value(envP, "i", (xmlrpc_int32) x + y);
+}
+
+
+
+static xmlrpc_value *
+test_bar(xmlrpc_env * const envP,
+ xmlrpc_value * const paramArrayP,
+ void * const serverInfo,
+ void * const callInfo) {
+
+ xmlrpc_int32 x, y;
+
+ TEST_NO_FAULT(envP);
+ TEST(paramArrayP != NULL);
+ TEST(serverInfo == BAR_SERVERINFO);
+ TEST(callInfo == BAR_CALLINFO || callInfo == MULTI_CALLINFO);
+
+ xmlrpc_decompose_value(envP, paramArrayP, "(ii)", &x, &y);
+ TEST_NO_FAULT(envP);
+ TEST(x == 25);
+ TEST(y == 17);
+
+ xmlrpc_env_set_fault(envP, 123, "Test fault");
+
+ return NULL;
+}
+
+
+
+static xmlrpc_value *
+test_default(xmlrpc_env * const envP,
+ const char * const callInfo,
+ const char * const methodName,
+ xmlrpc_value * const paramArrayP,
+ void * const serverInfo) {
+
+ xmlrpc_int32 x, y;
+
+ TEST_NO_FAULT(envP);
+ TEST(paramArrayP != NULL);
+ TEST(serverInfo == DEFAULT_SERVERINFO);
+
+ TEST(streq(methodName, "test.nosuch") ||
+ streq(methodName, "test.nosuch.old"));
+
+ if (streq(methodName, "nosuch.method"))
+ TEST(callInfo == DEFAULT_CALLINFO);
+ else if (streq(methodName, "nosuch.method.old"))
+ TEST(callInfo == NULL);
+
+ xmlrpc_decompose_value(envP, paramArrayP, "(ii)", &x, &y);
+ TEST_NO_FAULT(envP);
+ TEST(x == 25);
+ TEST(y == 17);
+
+ return xmlrpc_build_value(envP, "i", 2 * (x + y));
+}
+
+
+
+static xmlrpc_value *
+test_exttype(xmlrpc_env * const envP,
+ xmlrpc_value * const paramArrayP ATTR_UNUSED,
+ void * const serverInfo ATTR_UNUSED,
+ void * const callInfo ATTR_UNUSED) {
+
+ return xmlrpc_build_value(envP, "(In)", (xmlrpc_int64)8);
+}
+
+
+
+static void
+doRpc(xmlrpc_env * const envP,
+ xmlrpc_registry * const registryP,
+ const char * const methodName,
+ xmlrpc_value * const argArrayP,
+ void * const callInfo,
+ xmlrpc_value ** const resultPP) {
+/*----------------------------------------------------------------------------
+ Do what an XML-RPC server would do -- pass an XML call to the registry
+ and get XML back.
+
+ Actually to our caller, we look more like an Xmlrpc-c client. We're
+ both the client and the server all bound together.
+-----------------------------------------------------------------------------*/
+ xmlrpc_mem_block * callP;
+ xmlrpc_mem_block * responseP;
+
+ /* Build a call, and tell the registry to handle it. */
+ callP = xmlrpc_mem_block_new(envP, 0);
+ TEST_NO_FAULT(envP);
+ xmlrpc_serialize_call(envP, callP, methodName, argArrayP);
+ TEST_NO_FAULT(envP);
+
+ if (callInfo)
+ xmlrpc_registry_process_call2(
+ envP, registryP,
+ xmlrpc_mem_block_contents(callP),
+ xmlrpc_mem_block_size(callP),
+ callInfo, &responseP);
+ else
+ responseP = xmlrpc_registry_process_call(
+ envP, registryP, NULL,
+ xmlrpc_mem_block_contents(callP),
+ xmlrpc_mem_block_size(callP));
+
+ TEST_NO_FAULT(envP);
+ TEST(responseP != NULL);
+
+ /* Parse the response. */
+ *resultPP = xmlrpc_parse_response(envP,
+ xmlrpc_mem_block_contents(responseP),
+ xmlrpc_mem_block_size(responseP));
+
+ xmlrpc_mem_block_free(callP);
+ xmlrpc_mem_block_free(responseP);
+}
+
+
+
+static const char * const validSigString[] = {
+ "i:",
+ "s:d",
+ "i:bds86SA",
+ "i:,i:",
+ "i:dd,s:,A:A",
+ "i:,",
+ "b:i,",
+ "b:i,b:,",
+ NULL
+};
+
+static const char * const invalidSigString[] = {
+ "",
+ "i",
+ "q",
+ "i:q",
+ "i:ddq",
+ ",",
+ ",i:",
+ "i,",
+ "b:i,,b:i",
+ "ii:",
+ "ii:ii",
+ NULL
+};
+
+
+
+static void
+test_system_methodSignature(xmlrpc_registry * const registryP) {
+/*----------------------------------------------------------------------------
+ Test system.methodSignature system method.
+-----------------------------------------------------------------------------*/
+ xmlrpc_env env;
+ xmlrpc_value * argArrayP;
+ xmlrpc_value * resultP;
+ const char * type0;
+ const char * type1;
+ const char * type2;
+ const char * type3;
+ const char * type4;
+ const char * type5;
+ const char * type6;
+ const char * type7;
+ const char * nosigstring;
+
+ xmlrpc_env_init(&env);
+
+ argArrayP = xmlrpc_build_value(&env, "(s)", "test.nosuchmethod");
+ doRpc(&env, registryP, "system.methodSignature", argArrayP, NULL,
+ &resultP);
+ TEST_FAULT(&env, XMLRPC_NO_SUCH_METHOD_ERROR);
+ xmlrpc_DECREF(argArrayP);
+
+ argArrayP = xmlrpc_build_value(&env, "(s)", "test.nosig0");
+
+ doRpc(&env, registryP, "system.methodSignature", argArrayP, NULL,
+ &resultP);
+ TEST_NO_FAULT(&env);
+
+ xmlrpc_read_string(&env, resultP, &nosigstring);
+ TEST_NO_FAULT(&env);
+
+ TEST(streq(nosigstring, "undef"));
+ strfree(nosigstring);
+ xmlrpc_DECREF(resultP);
+ xmlrpc_DECREF(argArrayP);
+
+ argArrayP = xmlrpc_build_value(&env, "(s)", "test.validsig0");
+ doRpc(&env, registryP, "system.methodSignature", argArrayP, NULL,
+ &resultP);
+ TEST_NO_FAULT(&env);
+
+ xmlrpc_decompose_value(&env, resultP, "((s))", &type0);
+ TEST_NO_FAULT(&env);
+ TEST(streq(type0, "int"));
+ strfree(type0);
+ xmlrpc_DECREF(resultP);
+ xmlrpc_DECREF(argArrayP);
+
+ argArrayP = xmlrpc_build_value(&env, "(s)", "test.validsig2");
+ doRpc(&env, registryP, "system.methodSignature", argArrayP, NULL,
+ &resultP);
+ TEST_NO_FAULT(&env);
+ xmlrpc_decompose_value(&env, resultP, "((ssssssss))",
+ &type0, &type1, &type2, &type3,
+ &type4, &type5, &type6, &type7);
+ TEST_NO_FAULT(&env);
+ TEST(streq(type0, "int"));
+ TEST(streq(type1, "boolean"));
+ TEST(streq(type2, "double"));
+ TEST(streq(type3, "string"));
+ TEST(streq(type4, "dateTime.iso8601"));
+ TEST(streq(type5, "base64"));
+ TEST(streq(type6, "struct"));
+ TEST(streq(type7, "array"));
+ strfree(type0); strfree(type1); strfree(type2); strfree(type3);
+ strfree(type4); strfree(type5); strfree(type6); strfree(type7);
+ xmlrpc_DECREF(resultP);
+ xmlrpc_DECREF(argArrayP);
+
+ argArrayP = xmlrpc_build_value(&env, "(s)", "test.validsig3");
+ doRpc(&env, registryP, "system.methodSignature", argArrayP, NULL,
+ &resultP);
+ TEST_NO_FAULT(&env);
+ xmlrpc_decompose_value(&env, resultP, "((s)(s))", &type0, &type1);
+
+ TEST_NO_FAULT(&env);
+ TEST(streq(type0, "int"));
+ TEST(streq(type1, "int"));
+ xmlrpc_DECREF(resultP);
+ xmlrpc_DECREF(argArrayP);
+
+ xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+test_signature(void) {
+
+ xmlrpc_env env;
+ xmlrpc_registry * registryP;
+ uint i;
+
+ xmlrpc_env_init(&env);
+
+ printf(" Running signature tests.");
+
+ registryP = xmlrpc_registry_new(&env);
+ TEST_NO_FAULT(&env);
+
+ xmlrpc_registry_add_method2(&env, registryP, "test.nosig0",
+ test_foo, NULL, NULL, FOO_SERVERINFO);
+ TEST_NO_FAULT(&env);
+
+ xmlrpc_registry_add_method2(&env, registryP, "test.nosig1",
+ test_foo, "?", NULL, FOO_SERVERINFO);
+ TEST_NO_FAULT(&env);
+
+ for (i = 0; validSigString[i]; ++i) {
+ const char * methodName;
+ casprintf(&methodName, "test.validsig%u", i);
+ xmlrpc_registry_add_method2(&env, registryP, methodName,
+ test_foo,
+ validSigString[i], NULL, FOO_SERVERINFO);
+ TEST_NO_FAULT(&env);
+ strfree(methodName);
+ }
+
+ for (i = 0; invalidSigString[i]; ++i) {
+ const char * methodName;
+ casprintf(&methodName, "test.invalidsig%u", i);
+ xmlrpc_registry_add_method2(&env, registryP, methodName,
+ test_foo,
+ invalidSigString[i], NULL, FOO_SERVERINFO);
+ TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+ strfree(methodName);
+ }
+
+ xmlrpc_registry_add_method_w_doc(&env, registryP, NULL, "test.old",
+ test_foo_type1, FOO_SERVERINFO,
+ NULL, NULL);
+ TEST_NO_FAULT(&env);
+
+ xmlrpc_registry_add_method_w_doc(&env, registryP, NULL, "test.old.invalid",
+ test_foo_type1, FOO_SERVERINFO,
+ invalidSigString[0], NULL);
+ TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+
+ test_system_methodSignature(registryP);
+
+ xmlrpc_registry_free(registryP);
+
+ xmlrpc_env_clean(&env);
+
+ printf("\n");
+}
+
+
+
+static void
+test_disable_introspection(void) {
+
+ xmlrpc_env env;
+ xmlrpc_registry * registryP;
+ xmlrpc_value * argArrayP;
+ xmlrpc_value * resultP;
+
+ xmlrpc_env_init(&env);
+
+ printf(" Running disable introspection tests.");
+
+ registryP = xmlrpc_registry_new(&env);
+ TEST_NO_FAULT(&env);
+
+ xmlrpc_registry_add_method2(&env, registryP, "test.nosig0",
+ test_foo, NULL, NULL, FOO_SERVERINFO);
+ TEST_NO_FAULT(&env);
+
+ xmlrpc_registry_disable_introspection(registryP);
+
+ argArrayP = xmlrpc_build_value(&env, "(s)", "test.nosig0");
+ doRpc(&env, registryP, "system.methodSignature", argArrayP, NULL,
+ &resultP);
+ TEST_FAULT(&env, XMLRPC_INTROSPECTION_DISABLED_ERROR);
+ xmlrpc_DECREF(argArrayP);
+
+ xmlrpc_registry_free(registryP);
+
+ xmlrpc_env_clean(&env);
+
+ printf("\n");
+}
+
+
+
+static const char * const expectedMethodName[] = {
+/*----------------------------------------------------------------------------
+ The list we expect back from system.listMethods.
+-----------------------------------------------------------------------------*/
+ "system.listMethods",
+ "system.methodSignature",
+ "system.methodHelp",
+ "system.multicall",
+ "system.shutdown",
+ "system.capabilities",
+ "test.foo",
+ "test.bar"
+};
+
+
+static void
+test_system_listMethods(xmlrpc_registry * const registryP) {
+/*----------------------------------------------------------------------------
+ Test system.listMethods
+-----------------------------------------------------------------------------*/
+ xmlrpc_env env;
+ xmlrpc_value * resultP;
+ xmlrpc_value * argArrayP;
+ const char * methodName[8];
+ unsigned int size;
+ unsigned int i;
+
+ xmlrpc_env_init(&env);
+
+ printf(" Running system.listMethods tests.");
+
+ argArrayP = xmlrpc_array_new(&env);
+ TEST_NO_FAULT(&env);
+
+ doRpc(&env, registryP, "system.listMethods", argArrayP, NULL, &resultP);
+ TEST_NO_FAULT(&env);
+
+ TEST(xmlrpc_value_type(resultP) == XMLRPC_TYPE_ARRAY);
+
+ size = xmlrpc_array_size(&env, resultP);
+
+ TEST_NO_FAULT(&env);
+
+ TEST(size == ARRAY_SIZE(expectedMethodName));
+
+ xmlrpc_decompose_value(&env, resultP, "(ssssssss)",
+ &methodName[0], &methodName[1],
+ &methodName[2], &methodName[3],
+ &methodName[4], &methodName[5],
+ &methodName[6], &methodName[7]);
+
+ for (i = 0; i < ARRAY_SIZE(methodName); ++i) {
+ TEST(streq(methodName[i], expectedMethodName[i]));
+ strfree(methodName[i]);
+ }
+
+ xmlrpc_DECREF(resultP);
+
+ xmlrpc_DECREF(argArrayP);
+
+ xmlrpc_env_clean(&env);
+
+ printf("\n");
+}
+
+
+
+static void
+test_system_methodHelp(xmlrpc_registry * const registryP) {
+/*----------------------------------------------------------------------------
+ Test system.methodHelp
+-----------------------------------------------------------------------------*/
+ xmlrpc_env env;
+ xmlrpc_value * resultP;
+ xmlrpc_value * argArrayP;
+ const char * helpString;
+
+ xmlrpc_env_init(&env);
+
+ printf(" Running system.methodHelp tests.");
+
+ argArrayP = xmlrpc_build_value(&env, "(s)", "test.foo");
+ TEST_NO_FAULT(&env);
+
+ doRpc(&env, registryP, "system.methodHelp", argArrayP, NULL, &resultP);
+ TEST_NO_FAULT(&env);
+
+ TEST(xmlrpc_value_type(resultP) == XMLRPC_TYPE_STRING);
+
+ xmlrpc_read_string(&env, resultP, &helpString);
+ TEST_NO_FAULT(&env);
+
+ TEST(streq(helpString, "No help is available for this method."));
+
+ xmlrpc_DECREF(resultP);
+
+ xmlrpc_DECREF(argArrayP);
+
+
+ argArrayP = xmlrpc_build_value(&env, "(s)", "test.bar");
+ TEST_NO_FAULT(&env);
+
+ doRpc(&env, registryP, "system.methodHelp", argArrayP, NULL, &resultP);
+ TEST_NO_FAULT(&env);
+
+ TEST(xmlrpc_value_type(resultP) == XMLRPC_TYPE_STRING);
+
+ xmlrpc_read_string(&env, resultP, &helpString);
+ TEST_NO_FAULT(&env);
+
+ TEST(streq(helpString, barHelp));
+
+ xmlrpc_DECREF(resultP);
+
+ xmlrpc_DECREF(argArrayP);
+
+ xmlrpc_env_clean(&env);
+
+ printf("\n");
+}
+
+
+
+static void
+test_system_capabilities(xmlrpc_registry * const registryP) {
+/*----------------------------------------------------------------------------
+ Test system.capabilities
+-----------------------------------------------------------------------------*/
+ xmlrpc_env env;
+ xmlrpc_value * resultP;
+ xmlrpc_value * argArrayP;
+ const char * facility;
+ xmlrpc_int version_major, version_minor, version_point;
+ xmlrpc_int protocol_version;
+
+ xmlrpc_env_init(&env);
+
+ printf(" Running system.capabilities tests.");
+
+ argArrayP = xmlrpc_array_new(&env);
+ TEST_NO_FAULT(&env);
+
+ doRpc(&env, registryP, "system.capabilities", argArrayP, NULL, &resultP);
+ TEST_NO_FAULT(&env);
+
+ xmlrpc_decompose_value(&env, resultP, "{s:s,s:i,s:i,s:i,s:i,*}",
+ "facility", &facility,
+ "version_major", &version_major,
+ "version_minor", &version_minor,
+ "version_point", &version_point,
+ "protocol_version", &protocol_version);
+ TEST_NO_FAULT(&env);
+
+ TEST(streq(facility, "xmlrpc-c"));
+ TEST(protocol_version == 2);
+
+ xmlrpc_DECREF(resultP);
+
+ xmlrpc_DECREF(argArrayP);
+
+ xmlrpc_env_clean(&env);
+
+ printf("\n");
+}
+
+
+
+static void
+test_system_multicall(xmlrpc_registry * const registryP) {
+/*----------------------------------------------------------------------------
+ Test system.multicall
+-----------------------------------------------------------------------------*/
+ xmlrpc_env env;
+ xmlrpc_value * multiP;
+ xmlrpc_int32 foo1_result, foo2_result;
+ xmlrpc_int32 bar_code, nosuch_code;
+ char *bar_string, *nosuch_string;
+ xmlrpc_value * valueP;
+ xmlrpc_value * argArrayP;
+
+ xmlrpc_env_init(&env);
+
+ printf(" Running multicall tests.");
+
+ /* Build an argument array for our calls. */
+ argArrayP = xmlrpc_build_value(&env, "(ii)",
+ (xmlrpc_int32) 25, (xmlrpc_int32) 17);
+ TEST_NO_FAULT(&env);
+
+ multiP = xmlrpc_build_value(&env,
+ "(("
+ "{s:s,s:A}" /* test.foo */
+ "{s:s,s:A}" /* test.bar */
+ "{s:s,s:A}" /* test.nosuch */
+ "{s:s,s:A}" /* test.foo */
+ "))",
+ "methodName", "test.foo",
+ "params", argArrayP,
+ "methodName", "test.bar",
+ "params", argArrayP,
+ "methodName", "test.nosuch",
+ "params", argArrayP,
+ "methodName", "test.foo",
+ "params", argArrayP);
+ TEST_NO_FAULT(&env);
+ doRpc(&env, registryP, "system.multicall", multiP, MULTI_CALLINFO,
+ &valueP);
+ TEST_NO_FAULT(&env);
+ xmlrpc_decompose_value(&env, valueP,
+ "("
+ "(i)" /* result of test.foo */
+ "{s:i,s:s,*}" /* result of test.bar */
+ "{s:i,s:s,*}" /* result of test.nosuch */
+ "(i)" /* result of test.foo #2 */
+ ")",
+ &foo1_result,
+ "faultCode", &bar_code,
+ "faultString", &bar_string,
+ "faultCode", &nosuch_code,
+ "faultString", &nosuch_string,
+ &foo2_result);
+ xmlrpc_DECREF(valueP);
+ TEST_NO_FAULT(&env);
+ TEST(foo1_result == 42);
+ TEST(bar_code == 123);
+ TEST(strcmp(bar_string, "Test fault") == 0);
+ TEST(nosuch_code == XMLRPC_NO_SUCH_METHOD_ERROR);
+ TEST(foo2_result == 42);
+ xmlrpc_DECREF(multiP);
+ free(bar_string);
+
+
+ /* Now for some invalid multi calls */
+
+ multiP = xmlrpc_build_value(&env,
+ "(({s:s,s:V}{s:s,s:()}{s:s,s:V}))",
+ "methodName", "test.foo",
+ "params", argArrayP,
+ "methodName", "system.multicall",
+ "params",
+ "methodName", "test.foo",
+ "params", argArrayP);
+ TEST_NO_FAULT(&env);
+ doRpc(&env, registryP, "system.multicall", multiP, MULTI_CALLINFO,
+ &valueP);
+ TEST_FAULT(&env, XMLRPC_REQUEST_REFUSED_ERROR);
+
+ xmlrpc_DECREF(multiP);
+
+ multiP = xmlrpc_build_value(&env,
+ "(({s:s,s:V}d))",
+ "methodName", "test.foo",
+ "params", argArrayP,
+ 5.0);
+
+ TEST_NO_FAULT(&env);
+ doRpc(&env, registryP, "system.multicall", multiP, MULTI_CALLINFO,
+ &valueP);
+ TEST_FAULT(&env, XMLRPC_TYPE_ERROR);
+
+ xmlrpc_DECREF(multiP);
+
+ multiP = xmlrpc_build_value(&env,
+ "({s:s,s:V})",
+ "methodName", "test.foo",
+ "params", argArrayP);
+
+ TEST_NO_FAULT(&env);
+ doRpc(&env, registryP, "system.multicall", multiP, MULTI_CALLINFO,
+ &valueP);
+ TEST_FAULT(&env, XMLRPC_TYPE_ERROR);
+
+ xmlrpc_DECREF(multiP);
+
+ multiP = xmlrpc_build_value(&env, "(({}))");
+ TEST_NO_FAULT(&env);
+ doRpc(&env, registryP, "system.multicall", multiP, MULTI_CALLINFO,
+ &valueP);
+ TEST_FAULT(&env, XMLRPC_INDEX_ERROR);
+
+ xmlrpc_DECREF(multiP);
+
+ multiP = xmlrpc_build_value(&env, "(({s:s}))",
+ "methodName", "test.foo");
+ TEST_NO_FAULT(&env);
+ doRpc(&env, registryP, "system.multicall", multiP, MULTI_CALLINFO,
+ &valueP);
+ TEST_FAULT(&env, XMLRPC_INDEX_ERROR);
+
+ xmlrpc_DECREF(multiP);
+
+
+ xmlrpc_DECREF(argArrayP);
+
+ xmlrpc_env_clean(&env);
+
+ printf("\n");
+}
+
+
+
+static void
+testCall(xmlrpc_registry * const registryP) {
+
+ xmlrpc_env env;
+ xmlrpc_env env2;
+ xmlrpc_value * argArrayP;
+ xmlrpc_value * valueP;
+ xmlrpc_int32 i;
+
+ printf(" Running call tests.");
+
+ xmlrpc_env_init(&env);
+
+ /* Build an argument array for our calls. */
+ argArrayP = xmlrpc_build_value(&env, "(ii)",
+ (xmlrpc_int32) 25, (xmlrpc_int32) 17);
+ TEST_NO_FAULT(&env);
+
+ /* Call test.foo and check the result. */
+ doRpc(&env, registryP, "test.foo", argArrayP, FOO_CALLINFO, &valueP);
+ TEST_NO_FAULT(&env);
+ TEST(valueP != NULL);
+ xmlrpc_decompose_value(&env, valueP, "i", &i);
+ xmlrpc_DECREF(valueP);
+ TEST_NO_FAULT(&env);
+ TEST(i == 42);
+
+ /* Call test.bar and check the result. */
+ xmlrpc_env_init(&env2);
+ doRpc(&env2, registryP, "test.bar", argArrayP, BAR_CALLINFO, &valueP);
+ TEST(env2.fault_occurred);
+ TEST(env2.fault_code == 123);
+ TEST(env2.fault_string && strcmp(env2.fault_string, "Test fault") == 0);
+ xmlrpc_env_clean(&env2);
+
+ /* Call a non-existant method and check the result. */
+ xmlrpc_env_init(&env2);
+ doRpc(&env2, registryP, "test.nosuch", argArrayP, FOO_CALLINFO, &valueP);
+ TEST(valueP == NULL);
+ TEST_FAULT(&env2, XMLRPC_NO_SUCH_METHOD_ERROR);
+ xmlrpc_env_clean(&env2);
+
+ xmlrpc_DECREF(argArrayP);
+
+ xmlrpc_env_clean(&env);
+
+ printf("\n");
+}
+
+
+
+static void
+testDefaultMethod(xmlrpc_registry * const registryP) {
+
+ xmlrpc_env env;
+ xmlrpc_value * argArrayP;
+ xmlrpc_value * valueP;
+ xmlrpc_int32 i;
+
+ xmlrpc_env_init(&env);
+
+ printf(" Running default method tests.");
+
+ /* Build an argument array for our calls. */
+ argArrayP = xmlrpc_build_value(&env, "(ii)",
+ (xmlrpc_int32) 25, (xmlrpc_int32) 17);
+
+ xmlrpc_registry_set_default_method(&env, registryP, &test_default,
+ DEFAULT_SERVERINFO);
+ TEST_NO_FAULT(&env);
+ doRpc(&env, registryP, "test.nosuch", argArrayP, DEFAULT_CALLINFO,
+ &valueP);
+ TEST_NO_FAULT(&env);
+ TEST(valueP != NULL);
+ xmlrpc_decompose_value(&env, valueP, "i", &i);
+ xmlrpc_DECREF(valueP);
+ TEST_NO_FAULT(&env);
+ TEST(i == 84);
+
+ /* Now try it with old method interface */
+
+ doRpc(&env, registryP, "test.nosuch.old", argArrayP, NULL, &valueP);
+ TEST_NO_FAULT(&env);
+ TEST(valueP != NULL);
+ xmlrpc_read_int(&env, valueP, &i);
+ TEST_NO_FAULT(&env);
+ xmlrpc_DECREF(valueP);
+ TEST(i == 84);
+
+ /* Change the default method. */
+ xmlrpc_registry_set_default_method(&env, registryP, &test_default,
+ BAR_SERVERINFO);
+ TEST_NO_FAULT(&env);
+
+ xmlrpc_DECREF(argArrayP);
+
+ xmlrpc_env_clean(&env);
+
+ printf("\n");
+}
+
+
+
+static void
+test_apache_dialect(void) {
+
+ char const expectedResp[] =
+ XML_PROLOGUE
+ "<methodResponse>\r\n"
+ "<params>\r\n"
+ "<param><value><array><data>\r\n"
+ "<value><ex.i8>8</ex.i8></value>\r\n"
+ "<value><ex.nil/></value>\r\n"
+ "</data></array></value></param>\r\n"
+ "</params>\r\n"
+ "</methodResponse>\r\n";
+
+ xmlrpc_env env;
+ xmlrpc_registry * registryP;
+ xmlrpc_value * argArrayP;
+ xmlrpc_mem_block * callP;
+ xmlrpc_mem_block * responseP;
+
+ xmlrpc_env_init(&env);
+
+ printf(" Running apache dialect tests.");
+
+ registryP = xmlrpc_registry_new(&env);
+ TEST_NO_FAULT(&env);
+
+ xmlrpc_registry_set_dialect(&env, registryP, xmlrpc_dialect_i8);
+ TEST_NO_FAULT(&env);
+
+ xmlrpc_registry_set_dialect(&env, registryP, 100);
+ TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+
+ xmlrpc_registry_set_dialect(&env, registryP, xmlrpc_dialect_apache);
+ TEST_NO_FAULT(&env);
+
+ xmlrpc_registry_add_method2(&env, registryP, "test_exttype",
+ test_exttype, NULL, NULL, FOO_SERVERINFO);
+ TEST_NO_FAULT(&env);
+
+ argArrayP = xmlrpc_array_new(&env);
+ TEST_NO_FAULT(&env);
+
+ callP = xmlrpc_mem_block_new(&env, 0);
+ TEST_NO_FAULT(&env);
+ xmlrpc_serialize_call(&env, callP, "test_exttype", argArrayP);
+ TEST_NO_FAULT(&env);
+
+ xmlrpc_registry_process_call2(
+ &env, registryP,
+ xmlrpc_mem_block_contents(callP),
+ xmlrpc_mem_block_size(callP),
+ NULL, &responseP);
+
+ TEST_NO_FAULT(&env);
+
+ TEST(XMLRPC_MEMBLOCK_SIZE(char, responseP) == strlen(expectedResp));
+ TEST(memeq(XMLRPC_MEMBLOCK_CONTENTS(char, responseP),
+ expectedResp,
+ XMLRPC_MEMBLOCK_SIZE(char, responseP)));
+
+ xmlrpc_DECREF(argArrayP);
+ xmlrpc_mem_block_free(callP);
+ xmlrpc_mem_block_free(responseP);
+ xmlrpc_registry_free(registryP);
+
+ xmlrpc_env_clean(&env);
+
+ printf("\n");
+}
+
+
+
+void
+test_method_registry(void) {
+
+ xmlrpc_env env, env2;
+ xmlrpc_value * valueP;
+ xmlrpc_registry * registryP;
+ xmlrpc_mem_block * responseP;
+
+ xmlrpc_env_init(&env);
+
+ printf("Running method registry tests.");
+
+ /* Create a new registry. */
+ registryP = xmlrpc_registry_new(&env);
+ TEST_NO_FAULT(&env);
+ TEST(registryP != NULL);
+
+ /* Add some test methods. */
+ xmlrpc_registry_add_method(&env, registryP, NULL, "test.foo",
+ test_foo_type1, FOO_SERVERINFO);
+ TEST_NO_FAULT(&env);
+ xmlrpc_registry_add_method2(&env, registryP, "test.bar",
+ test_bar, NULL, barHelp, BAR_SERVERINFO);
+ TEST_NO_FAULT(&env);
+
+ printf("\n");
+ testCall(registryP);
+
+ test_system_multicall(registryP);
+
+ xmlrpc_env_init(&env2);
+ xmlrpc_registry_process_call2(&env, registryP,
+ expat_error_data,
+ strlen(expat_error_data),
+ NULL,
+ &responseP);
+ TEST_NO_FAULT(&env);
+ TEST(responseP != NULL);
+ valueP = xmlrpc_parse_response(&env2, xmlrpc_mem_block_contents(responseP),
+ xmlrpc_mem_block_size(responseP));
+ TEST(valueP == NULL);
+ TEST_FAULT(&env2, XMLRPC_PARSE_ERROR);
+ xmlrpc_mem_block_free(responseP);
+ xmlrpc_env_clean(&env2);
+
+ printf("\n");
+
+ testDefaultMethod(registryP);
+
+ test_system_listMethods(registryP);
+
+ test_system_methodHelp(registryP);
+
+ test_system_capabilities(registryP);
+
+ test_signature();
+
+ test_disable_introspection();
+
+ test_apache_dialect();
+
+ /* Test cleanup code (w/memprof). */
+ xmlrpc_registry_free(registryP);
+
+ printf("\n");
+
+ xmlrpc_env_clean(&env);
+}
Added: freeswitch/trunk/libs/xmlrpc-c/src/test/method_registry.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/test/method_registry.h Fri May 23 16:56:24 2008
@@ -0,0 +1,7 @@
+#ifndef TEST_METHOD_REGISTRY_H_INCLUDED
+#define TEST_METHOD_REGISTRY_H_INCLUDED
+
+void
+test_method_registry(void);
+
+#endif
Modified: freeswitch/trunk/libs/xmlrpc-c/src/test/parse_xml.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/src/test/parse_xml.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/src/test/parse_xml.c Fri May 23 16:56:24 2008
@@ -3,6 +3,8 @@
#include "xmlrpc_config.h"
+#include "girstring.h"
+#include "casprintf.h"
#include "xmlrpc-c/base.h"
#include "xmlrpc-c/xmlparser.h"
@@ -22,24 +24,24 @@
xmlrpc_env_init(&env);
/* Parse a moderately complex XML document. */
- elem = xml_parse(&env, expat_data, strlen(expat_data));
+ xml_parse(&env, expat_data, strlen(expat_data), &elem);
TEST_NO_FAULT(&env);
TEST(elem != NULL);
/* Verify our results. */
- TEST(strcmp(xml_element_name(elem), "value") == 0);
+ TEST(streq(xml_element_name(elem), "value"));
TEST(xml_element_children_size(elem) == 1);
array = xml_element_children(elem)[0];
- TEST(strcmp(xml_element_name(array), "array") == 0);
+ TEST(streq(xml_element_name(array), "array"));
TEST(xml_element_children_size(array) == 1);
data = xml_element_children(array)[0];
- TEST(strcmp(xml_element_name(data), "data") == 0);
+ TEST(streq(xml_element_name(data), "data"));
TEST(xml_element_children_size(data) > 1);
value1 = xml_element_children(data)[0];
- TEST(strcmp(xml_element_name(value1), "value") == 0);
+ TEST(streq(xml_element_name(value1), "value"));
TEST(xml_element_children_size(value1) == 1);
i4 = xml_element_children(value1)[0];
- TEST(strcmp(xml_element_name(i4), "i4") == 0);
+ TEST(streq(xml_element_name(i4), "i4"));
TEST(xml_element_children_size(i4) == 0);
cdata = xml_element_cdata(i4);
size = xml_element_cdata_size(i4);
@@ -49,11 +51,9 @@
/* Test cleanup code (w/memprof). */
xml_element_free(elem);
- /* Try to parse broken XML. We want to know that a proper error occurs,
- ** AND that we don't leak any memory (w/memprof). */
- elem = xml_parse(&env, expat_error_data, strlen(expat_error_data));
+ /* Test broken XML */
+ xml_parse(&env, expat_error_data, strlen(expat_error_data), &elem);
TEST(env.fault_occurred);
- TEST(elem == NULL);
xmlrpc_env_clean(&env);
}
@@ -61,180 +61,444 @@
static void
-test_parse_xml_value(void) {
+testParseNumberValue(void) {
- xmlrpc_env env, env2;
- xmlrpc_value *s, *sval;
- xmlrpc_int32 int_max, int_min, int_one;
- xmlrpc_bool bool_false, bool_true;
- char *str_hello, *str_untagged, *datetime;
- unsigned char *b64_data;
- size_t b64_len;
- double negone, zero, one;
- int size, sval_int;
- const char **bad_value;
+char const xmldata[] =
+ XML_PROLOGUE
+ "<methodCall>\r\n"
+ "<methodName>test</methodName>\r\n"
+ "<params>\r\n"
+ "<param><value><int>2147483647</int></value></param>\r\n" \
+ "<param><value><int>-2147483648</int></value></param>\r\n" \
+ "<param><value><i1>10</i1></value></param>\r\n"
+ "<param><value><i2>10</i2></value></param>\r\n"
+ "<param><value><i4>10</i4></value></param>\r\n"
+ "<param><value><i8>10</i8></value></param>\r\n"
+ "<param><value><ex.i8>10</ex.i8></value></param>\r\n"
+ "<param><value><double>10</double></value></param>\r\n"
+ "<param><value><double>10.1</double></value></param>\r\n"
+ "<param><value><double>-10.1</double></value></param>\r\n"
+ "<param><value><double>+10.1</double></value></param>\r\n"
+ "<param><value><double>0</double></value></param>\r\n"
+ "<param><value><double>.01</double></value></param>\r\n"
+ "<param><value><double>5.</double></value></param>\r\n"
+ "<param><value><double>5.3E6</double></value></param>\r\n"
+ "<param><value><double> 1</double></value></param>\r\n"
+ "</params>\r\n"
+ "</methodCall>\r\n";
+ xmlrpc_env env;
+ xmlrpc_value * paramArrayP;
+ const char * methodName;
+ int arraySize;
+ xmlrpc_int int_max, int_min;
+ xmlrpc_int32 i_i1, i_i2, i_i4;
+ xmlrpc_int64 i_i8, i_ex_i8;
+ double d1, d2, d3, d4, d5, d6, d7, d8, d9;
+
xmlrpc_env_init(&env);
+
+ xmlrpc_parse_call(&env, xmldata, strlen(xmldata),
+ &methodName, ¶mArrayP);
+ TEST_NO_FAULT(&env);
+
+ arraySize = xmlrpc_array_size(&env, paramArrayP);
+ TEST_NO_FAULT(&env);
+
+ TEST(arraySize == 16);
+
+ xmlrpc_decompose_value(
+ &env, paramArrayP, "(iiiiiIIddddddddd)",
+ &int_max, &int_min, &i_i1, &i_i2, &i_i4, &i_i8, &i_ex_i8,
+ &d1, &d2, &d3, &d4, &d5, &d6, &d7, &d8, &d9);
+
+ TEST_NO_FAULT(&env);
+
+ TEST(int_max == INT_MAX);
+ TEST(int_min == INT_MIN);
+ TEST(i_i1 == 10);
+ TEST(i_i2 == 10);
+ TEST(i_i4 == 10);
+ TEST(i_i8 == 10);
+ TEST(i_ex_i8 == 10);
+ TESTFLOATEQUAL(d1, 10.0);
+ TESTFLOATEQUAL(d2, 10.1);
+ TESTFLOATEQUAL(d3, -10.1);
+ TESTFLOATEQUAL(d4, +10.1);
+ TESTFLOATEQUAL(d5, 0.0);
+ TESTFLOATEQUAL(d6, 0.01);
+ TESTFLOATEQUAL(d7, 5.0);
+ TESTFLOATEQUAL(d8, 5.3E6);
+ TESTFLOATEQUAL(d9, 1.0);
+
+ xmlrpc_DECREF(paramArrayP);
+ strfree(methodName);
+
+ xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+testParseMiscSimpleValue(void) {
+
+char const xmldata[] =
+ XML_PROLOGUE
+ "<methodCall>\r\n"
+ "<methodName>test</methodName>\r\n"
+ "<params>\r\n"
+ "<param><value><string>hello</string></value></param>\r\n"
+ "<param><value><boolean>0</boolean></value></param>\r\n"
+ "<param><value><boolean>1</boolean></value></param>\r\n"
+ "<param><value><dateTime.iso8601>19980717T14:08:55</dateTime.iso8601>"
+ "</value></param>\r\n"
+ "<param><value><base64>YmFzZTY0IGRhdGE=</base64></value></param>\r\n"
+ "<param><value><nil/></value></param>\r\n"
+ "<param><value><ex.nil/></value></param>\r\n"
+ "</params>\r\n"
+ "</methodCall>\r\n";
- {
- xmlrpc_value * valueP;
+ xmlrpc_env env;
+ xmlrpc_value * paramArrayP;
+ const char * methodName;
+ int arraySize;
+ const char * str_hello;
+ xmlrpc_bool b_false, b_true;
+ const char * datetime;
+ unsigned char * b64_data;
+ size_t b64_len;
- /* Parse a correctly-formed response. */
- valueP = xmlrpc_parse_response(&env, correct_value,
- strlen(correct_value));
- TEST_NO_FAULT(&env);
- TEST(valueP != NULL);
-
- /* Analyze it and make sure it contains the correct values. */
- xmlrpc_decompose_value(
- &env, valueP, "((iibbs68())idddSs)",
- &int_max, &int_min,
- &bool_false, &bool_true, &str_hello,
- &b64_data, &b64_len, &datetime,
- &int_one, &negone, &zero, &one, &s, &str_untagged);
+ xmlrpc_env_init(&env);
+
+ xmlrpc_parse_call(&env, xmldata, strlen(xmldata),
+ &methodName, ¶mArrayP);
+ TEST_NO_FAULT(&env);
+
+ arraySize = xmlrpc_array_size(&env, paramArrayP);
+ TEST_NO_FAULT(&env);
+
+ TEST(arraySize == 7);
+
+ xmlrpc_decompose_value(
+ &env, paramArrayP, "(sbb86nn)",
+ &str_hello, &b_false, &b_true, &datetime, &b64_data, &b64_len);
+
+ TEST_NO_FAULT(&env);
+
+ TEST(streq(str_hello, "hello"));
+ TEST(!b_false);
+ TEST(b_true);
+ TEST(streq(datetime, "19980717T14:08:55"));
+ TEST(b64_len == 11);
+ TEST(memcmp(b64_data, "base64 data", b64_len) == 0);
+
+ free(b64_data);
+ strfree(str_hello);
+ strfree(datetime);
+ xmlrpc_DECREF(paramArrayP);
+ strfree(methodName);
+
+ xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+validateParseResponseResult(xmlrpc_value * const valueP) {
+
+ xmlrpc_env env;
+
+ xmlrpc_value * s;
+ xmlrpc_int32 int_max;
+ xmlrpc_int32 int_min;
+ xmlrpc_int32 int_one;
+ xmlrpc_bool bool_false;
+ xmlrpc_bool bool_true;
+ char * str_hello;
+ char * str_untagged;
+ char * datetime;
+ unsigned char * b64_data;
+ size_t b64_len;
+ double negone;
+ double zero;
+ double one;
+
+ xmlrpc_env_init(&env);
+
+ xmlrpc_decompose_value(
+ &env, valueP, "((iibbs68())idddSs)",
+ &int_max, &int_min,
+ &bool_false, &bool_true, &str_hello,
+ &b64_data, &b64_len, &datetime,
+ &int_one, &negone, &zero, &one, &s, &str_untagged);
- xmlrpc_DECREF(valueP);
- }
TEST_NO_FAULT(&env);
TEST(int_max == INT_MAX);
TEST(int_min == INT_MIN);
TEST(!bool_false);
TEST(bool_true);
TEST(strlen(str_hello) == strlen("Hello, world! <&>"));
- TEST(strcmp(str_hello, "Hello, world! <&>") == 0);
+ TEST(streq(str_hello, "Hello, world! <&>"));
TEST(b64_len == 11);
TEST(memcmp(b64_data, "base64 data", b64_len) == 0);
- TEST(strcmp(datetime, "19980717T14:08:55") == 0);
+ TEST(streq(datetime, "19980717T14:08:55"));
TEST(int_one == 1);
TEST(negone == -1.0);
TEST(zero == 0.0);
TEST(one == 1.0);
- TEST(strcmp(str_untagged, "Untagged string") == 0);
+ TEST(streq(str_untagged, "Untagged string"));
free(str_hello);
free(b64_data);
free(datetime);
free(str_untagged);
-
- /* Analyze the contents of our struct. */
- TEST(s != NULL);
- size = xmlrpc_struct_size(&env, s);
- TEST_NO_FAULT(&env);
- TEST(size == 2);
- sval = xmlrpc_struct_get_value(&env, s, "ten <&>");
- TEST_NO_FAULT(&env);
- xmlrpc_decompose_value(&env, sval, "i", &sval_int);
- TEST_NO_FAULT(&env);
- TEST(sval_int == 10);
- sval = xmlrpc_struct_get_value(&env, s, "twenty");
+
+ {
+ /* Analyze the contents of our struct. */
+
+ xmlrpc_value * sval;
+ int size, sval_int;
+
+ TEST(s != NULL);
+ size = xmlrpc_struct_size(&env, s);
+ TEST_NO_FAULT(&env);
+ TEST(size == 2);
+ sval = xmlrpc_struct_get_value(&env, s, "ten <&>");
+ TEST_NO_FAULT(&env);
+ xmlrpc_decompose_value(&env, sval, "i", &sval_int);
+ TEST_NO_FAULT(&env);
+ TEST(sval_int == 10);
+ sval = xmlrpc_struct_get_value(&env, s, "twenty");
+ TEST_NO_FAULT(&env);
+ xmlrpc_decompose_value(&env, sval, "i", &sval_int);
+ TEST_NO_FAULT(&env);
+ TEST(sval_int == 20);
+ xmlrpc_DECREF(s);
+ }
+
+ xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+testParseGoodResponse(void) {
+
+ xmlrpc_env env;
+ xmlrpc_value * valueP;
+ int faultCode;
+ const char * faultString;
+
+ xmlrpc_env_init(&env);
+
+ xmlrpc_parse_response2(&env, good_response_xml, strlen(good_response_xml),
+ &valueP, &faultCode, &faultString);
+
TEST_NO_FAULT(&env);
- xmlrpc_decompose_value(&env, sval, "i", &sval_int);
+ TEST(faultString == NULL);
+
+ validateParseResponseResult(valueP);
+
+ xmlrpc_DECREF(valueP);
+
+ /* Try it again with old interface */
+
+ valueP = xmlrpc_parse_response(&env,
+ good_response_xml,
+ strlen(good_response_xml));
TEST_NO_FAULT(&env);
- TEST(sval_int == 20);
- xmlrpc_DECREF(s);
+ TEST(valueP != NULL);
+
+ validateParseResponseResult(valueP);
+
+ xmlrpc_DECREF(valueP);
+
+ xmlrpc_env_clean(&env);
+
+}
+
+
+
+static void
+testParseBadResponseXml(void) {
+/*----------------------------------------------------------------------------
+ Test parsing of data that is supposed to be a response, but in not
+ even valid XML.
+-----------------------------------------------------------------------------*/
+ xmlrpc_env env;
+ xmlrpc_value * valueP;
+ int faultCode;
+ const char * faultString;
+
+ xmlrpc_env_init(&env);
+
+ xmlrpc_parse_response2(&env,
+ unparseable_value, strlen(unparseable_value),
+ &valueP, &faultCode, &faultString);
+
+ TEST_FAULT(&env, XMLRPC_PARSE_ERROR);
+ xmlrpc_env_clean(&env);
+
+ xmlrpc_env_init(&env);
+
+ /* And again with the old interface */
+ valueP = xmlrpc_parse_response(&env, unparseable_value,
+ strlen(unparseable_value));
+ TEST_FAULT(&env, XMLRPC_PARSE_ERROR);
+ xmlrpc_env_clean(&env);
+ TEST(valueP == NULL);
+}
+
+
+
+static void
+testParseBadResponseXmlRpc(void) {
+/*----------------------------------------------------------------------------
+ Test parsing of data that is supposed to be a response, and is valid
+ XML, but is not valid XML-RPC.
+-----------------------------------------------------------------------------*/
+ unsigned int i;
+
+ /* For this test, we test up to but not including the <value> in a
+ successful RPC response.
+ */
+
+ /* Next, check for bogus responses. These are all well-formed XML, but
+ ** they aren't legal XML-RPC. */
+ for (i = 15; bad_responses[i] != NULL; ++i) {
+ const char * const bad_resp = bad_responses[i];
+ xmlrpc_env env;
+ xmlrpc_value * v;
+ xml_element *elem;
+
+ xmlrpc_env_init(&env);
- /* Test our error-checking code. This is exposed to potentially-malicious
- ** network data, so we need to handle evil data gracefully, without
- ** barfing or leaking memory. (w/memprof) */
+ /* First, check to make sure that our test case is well-formed XML.
+ ** (It's easy to make mistakes when writing the test cases!) */
+ xml_parse(&env, bad_resp, strlen(bad_resp), &elem);
+ TEST_NO_FAULT(&env);
+ xml_element_free(elem);
- {
- xmlrpc_value * valueP;
-
- /* First, test some poorly-formed XML data. */
- xmlrpc_env_init(&env2);
- valueP = xmlrpc_parse_response(&env2, unparseable_value,
- strlen(unparseable_value));
- TEST_FAULT(&env2, XMLRPC_PARSE_ERROR);
- TEST(valueP == NULL);
- xmlrpc_env_clean(&env2);
+ /* Now, make sure the higher-level routine barfs appropriately. */
+ v = xmlrpc_parse_response(&env, bad_resp, strlen(bad_resp));
+ TEST(env.fault_occurred);
+ TEST(env.fault_code != 0); /* We use 0 as a code in our bad faults. */
+ TEST(v == NULL);
+ xmlrpc_env_clean(&env);
}
- /* Next, check for bogus values. These are all well-formed XML, but
- ** they aren't legal XML-RPC. */
- for (bad_value = bad_values; *bad_value != NULL; bad_value++) {
+}
+
+
+
+static void
+testParseBadResult(void) {
+/*----------------------------------------------------------------------------
+ Test parsing of data that is supposed to be a response, but is not
+ valid. It looks like a valid success response, but the result value
+ is not valid XML-RPC.
+-----------------------------------------------------------------------------*/
+ unsigned int i;
+
+ for (i = 0; bad_values[i] != NULL; ++i) {
+ const char * const bad_resp = bad_values[i];
+ xmlrpc_env env;
xmlrpc_value * valueP;
xml_element *elem;
+ int faultCode;
+ const char * faultString;
+ xmlrpc_env_init(&env);
+
/* First, check to make sure that our test case is well-formed XML.
** (It's easy to make mistakes when writing the test cases!) */
- elem = xml_parse(&env, *bad_value, strlen(*bad_value));
+ xml_parse(&env, bad_resp, strlen(bad_resp), &elem);
TEST_NO_FAULT(&env);
xml_element_free(elem);
/* Now, make sure the higher-level routine barfs appropriately. */
- xmlrpc_env_init(&env2);
- valueP = xmlrpc_parse_response(&env2, *bad_value, strlen(*bad_value));
- TEST_FAULT(&env2, XMLRPC_PARSE_ERROR);
+
+ xmlrpc_parse_response2(&env, bad_resp, strlen(bad_resp),
+ &valueP, &faultCode, &faultString);
+
+ TEST_FAULT(&env, XMLRPC_PARSE_ERROR);
+ xmlrpc_env_clean(&env);
+
+ xmlrpc_env_init(&env);
+
+ /* And again with the old interface */
+
+ valueP = xmlrpc_parse_response(&env, bad_resp, strlen(bad_resp));
+ TEST_FAULT(&env, XMLRPC_PARSE_ERROR);
TEST(valueP == NULL);
- xmlrpc_env_clean(&env2);
+ xmlrpc_env_clean(&env);
}
-
- xmlrpc_env_clean(&env);
}
-static void test_parse_xml_response (void)
-{
- xmlrpc_env env, env2;
- int i1;
- const char **bad_resp;
+
+
+static void
+testParseBadResponse(void) {
+/*----------------------------------------------------------------------------
+ Test parsing of data that is supposed to be a response, but is not
+ valid. Either not valid XML or not valid XML-RPC.
+-----------------------------------------------------------------------------*/
+ testParseBadResponseXml();
+
+ testParseBadResponseXmlRpc();
+
+ testParseBadResult();
+}
+
+
+
+static void
+testParseFaultResponse(void) {
+/*----------------------------------------------------------------------------
+ Test parsing of a valid response that indicates the RPC failed.
+-----------------------------------------------------------------------------*/
+ xmlrpc_env env;
xmlrpc_env_init(&env);
{
- xmlrpc_value * v;
- /* Parse a valid response. */
- v = xmlrpc_parse_response(&env, serialized_response,
- strlen(serialized_response));
+ xmlrpc_value * resultP;
+ int faultCode;
+ const char * faultString;
+
+ xmlrpc_parse_response2(&env,
+ serialized_fault, strlen(serialized_fault),
+ &resultP, &faultCode, &faultString);
+
TEST_NO_FAULT(&env);
- TEST(v != NULL);
- xmlrpc_decompose_value(&env, v, "i", &i1);
- xmlrpc_DECREF(v);
+ TEST(faultString != NULL);
+ TEST(faultCode == 6);
+ TEST(streq(faultString, "A fault occurred"));
+ strfree(faultString);
}
- TEST_NO_FAULT(&env);
- TEST(i1 == 30);
-
+ /* Now with the old interface */
{
- xmlrpc_value * v;
+ xmlrpc_value * valueP;
xmlrpc_env fault;
/* Parse a valid fault. */
xmlrpc_env_init(&fault);
- v = xmlrpc_parse_response(&fault, serialized_fault,
- strlen(serialized_fault));
+ valueP = xmlrpc_parse_response(&fault, serialized_fault,
+ strlen(serialized_fault));
TEST(fault.fault_occurred);
TEST(fault.fault_code == 6);
- TEST(strcmp(fault.fault_string, "A fault occurred") == 0);
+ TEST(streq(fault.fault_string, "A fault occurred"));
xmlrpc_env_clean(&fault);
}
- /* We don't need to test our handling of poorly formatted XML here,
- ** because we already did that in test_parse_xml_value. */
- /* Next, check for bogus responses. These are all well-formed XML, but
- ** they aren't legal XML-RPC. */
- for (bad_resp = bad_responses; *bad_resp != NULL; bad_resp++) {
- xmlrpc_value * v;
- xml_element *elem;
-
- /* First, check to make sure that our test case is well-formed XML.
- ** (It's easy to make mistakes when writing the test cases!) */
- elem = xml_parse(&env, *bad_resp, strlen(*bad_resp));
- TEST_NO_FAULT(&env);
- xml_element_free(elem);
-
- /* Now, make sure the higher-level routine barfs appropriately. */
- xmlrpc_env_init(&env2);
- v = xmlrpc_parse_response(&env2, *bad_resp, strlen(*bad_resp));
- TEST(env2.fault_occurred);
- TEST(env2.fault_code != 0); /* We use 0 as a code in our bad faults. */
- TEST(v == NULL);
- xmlrpc_env_clean(&env2);
- }
-
xmlrpc_env_clean(&env);
}
-static void test_parse_xml_call (void)
-{
- xmlrpc_env env, env2;
+
+
+static void
+test_parse_xml_call(void) {
+
+ xmlrpc_env env;
const char *method_name;
xmlrpc_value *params;
int i1, i2;
@@ -251,37 +515,33 @@
xmlrpc_decompose_value(&env, params, "(ii)", &i1, &i2);
xmlrpc_DECREF(params);
TEST_NO_FAULT(&env);
- TEST(strcmp(method_name, "gloom&doom") == 0);
+ TEST(streq(method_name, "gloom&doom"));
TEST(i1 == 10 && i2 == 20);
strfree(method_name);
/* Test some poorly-formed XML data. */
- xmlrpc_env_init(&env2);
- xmlrpc_parse_call(&env2, unparseable_value, strlen(unparseable_value),
+ xmlrpc_parse_call(&env, unparseable_value, strlen(unparseable_value),
&method_name, ¶ms);
- TEST_FAULT(&env2, XMLRPC_PARSE_ERROR);
+ TEST_FAULT(&env, XMLRPC_PARSE_ERROR);
TEST(method_name == NULL && params == NULL);
- xmlrpc_env_clean(&env2);
/* Next, check for bogus values. These are all well-formed XML, but
- ** they aren't legal XML-RPC. */
- for (bad_call = bad_calls; *bad_call != NULL; bad_call++) {
+ they aren't legal XML-RPC.
+ */
+ for (bad_call = bad_calls; *bad_call != NULL; ++bad_call) {
/* First, check to make sure that our test case is well-formed XML.
** (It's easy to make mistakes when writing the test cases!) */
- elem = xml_parse(&env, *bad_call, strlen(*bad_call));
+ xml_parse(&env, *bad_call, strlen(*bad_call), &elem);
TEST_NO_FAULT(&env);
xml_element_free(elem);
/* Now, make sure the higher-level routine barfs appropriately. */
- xmlrpc_env_init(&env2);
- xmlrpc_parse_call(&env2, *bad_call, strlen(*bad_call),
+ xmlrpc_parse_call(&env, *bad_call, strlen(*bad_call),
&method_name, ¶ms);
- TEST_FAULT(&env2, XMLRPC_PARSE_ERROR);
+ TEST_FAULT(&env, XMLRPC_PARSE_ERROR);
TEST(method_name == NULL && params == NULL);
- xmlrpc_env_clean(&env2);
}
-
xmlrpc_env_clean(&env);
}
@@ -290,8 +550,14 @@
void
test_parse_xml(void) {
+ printf("Running XML parsing tests.\n");
test_expat();
- test_parse_xml_value();
- test_parse_xml_response();
+ testParseNumberValue();
+ testParseMiscSimpleValue();
+ testParseGoodResponse();
+ testParseFaultResponse();
+ testParseBadResponse();
test_parse_xml_call();
+ printf("\n");
+ printf("XML parsing tests done.\n");
}
Modified: freeswitch/trunk/libs/xmlrpc-c/src/test/serialize.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/src/test/serialize.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/src/test/serialize.c Fri May 23 16:56:24 2008
@@ -8,8 +8,10 @@
#include "test.h"
#include "xml_data.h"
-#include "serialize.h"
+#include "girstring.h"
+#include "serialize_value.h"
+#include "serialize.h"
static void
@@ -60,57 +62,41 @@
static void
-test_serialize_double(void) {
+test_serialize_methodResponse(void) {
+
+ /* Serialize a methodResponse. */
- /* Test serialize of a double. */
+ char const serialized_response[] =
+ XML_PROLOGUE
+ "<methodResponse>\r\n"
+ "<params>\r\n"
+ "<param><value><i4>30</i4></value></param>\r\n"
+ "</params>\r\n"
+ "</methodResponse>\r\n";
xmlrpc_env env;
xmlrpc_value * v;
xmlrpc_mem_block *output;
- char * result;
- /* serialized result, as asciiz string */
- size_t resultLength;
- /* Length in characters of the serialized result */
- float serializedValue;
- char nextChar;
- int itemsMatched;
+ size_t size;
xmlrpc_env_init(&env);
- /* Build a double to serialize */
- v = xmlrpc_build_value(&env, "d", 3.14159);
- TEST_NO_FAULT(&env);
-
- /* Serialize the value. */
output = XMLRPC_TYPED_MEM_BLOCK_NEW(char, &env, 0);
TEST_NO_FAULT(&env);
- xmlrpc_serialize_value(&env, output, v);
+ v = xmlrpc_build_value(&env, "i", (xmlrpc_int32) 30);
+ TEST_NO_FAULT(&env);
+ xmlrpc_serialize_response(&env, output, v);
TEST_NO_FAULT(&env);
- /* Make sure we serialized the correct value. Note that because
- doubles aren't precise, this might serialize as 3.1415899999
- or something like that. So we check it arithmetically.
- */
- resultLength = XMLRPC_TYPED_MEM_BLOCK_SIZE(char, output);
- result = malloc(resultLength + 1);
-
- memcpy(result, XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, output),
- resultLength);
- result[resultLength] = '\0';
-
- itemsMatched = sscanf(result,
- "<value><double>%f</double></value>\r\n%c",
- &serializedValue, &nextChar);
-
- TEST(itemsMatched == 1);
- TEST(serializedValue - 3.14159 < .000001);
- /* We'd like to test more precision, but sscanf doesn't do doubles */
+ /* Make sure we serialized the correct value. */
+ size = XMLRPC_TYPED_MEM_BLOCK_SIZE(char, output);
+ TEST(size == strlen(serialized_response));
+ TEST(memcmp(XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, output),
+ serialized_response, size) == 0);
- free(result);
-
- /* Clean up our value. */
- XMLRPC_TYPED_MEM_BLOCK_FREE(char, output);
+ /* Clean up our methodResponse. */
xmlrpc_DECREF(v);
+ XMLRPC_TYPED_MEM_BLOCK_FREE(char, output);
xmlrpc_env_clean(&env);
}
@@ -118,16 +104,10 @@
static void
-test_serialize_struct(void) {
+test_serialize_methodCall(void) {
- /* Serialize a simple struct. */
+ /* Serialize a methodCall. */
- char const serialized_struct[] =
- "<value><struct>\r\n" \
- "<member><name><&></name>\r\n" \
- "<value><i4>10</i4></value></member>\r\n" \
- "</struct></value>";
-
xmlrpc_env env;
xmlrpc_value * v;
xmlrpc_mem_block *output;
@@ -135,22 +115,22 @@
xmlrpc_env_init(&env);
- v = xmlrpc_build_value(&env, "{s:i}", "<&>", (xmlrpc_int32) 10);
- TEST_NO_FAULT(&env);
output = XMLRPC_TYPED_MEM_BLOCK_NEW(char, &env, 0);
TEST_NO_FAULT(&env);
- xmlrpc_serialize_value(&env, output, v);
+ v = xmlrpc_build_value(&env, "(ii)", (xmlrpc_int32) 10, (xmlrpc_int32) 20);
+ TEST_NO_FAULT(&env);
+ xmlrpc_serialize_call(&env, output, "gloom&doom", v);
TEST_NO_FAULT(&env);
/* Make sure we serialized the correct value. */
size = XMLRPC_TYPED_MEM_BLOCK_SIZE(char, output);
- TEST(size == strlen(serialized_struct));
+ TEST(size == strlen(serialized_call));
TEST(memcmp(XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, output),
- serialized_struct, size) == 0);
-
- /* Clean up our struct. */
- XMLRPC_TYPED_MEM_BLOCK_FREE(char, output);
+ serialized_call, size) == 0);
+
+ /* Clean up our methodCall. */
xmlrpc_DECREF(v);
+ XMLRPC_TYPED_MEM_BLOCK_FREE(char, output);
xmlrpc_env_clean(&env);
}
@@ -158,12 +138,11 @@
static void
-test_serialize_methodResponse(void) {
-
- /* Serialize a methodResponse. */
+test_serialize_fault(void) {
+ /* Serialize a fault. */
xmlrpc_env env;
- xmlrpc_value * v;
+ xmlrpc_env fault;
xmlrpc_mem_block *output;
size_t size;
@@ -171,19 +150,19 @@
output = XMLRPC_TYPED_MEM_BLOCK_NEW(char, &env, 0);
TEST_NO_FAULT(&env);
- v = xmlrpc_build_value(&env, "i", (xmlrpc_int32) 30);
- TEST_NO_FAULT(&env);
- xmlrpc_serialize_response(&env, output, v);
+ xmlrpc_env_init(&fault);
+ xmlrpc_env_set_fault(&fault, 6, "A fault occurred");
+ xmlrpc_serialize_fault(&env, output, &fault);
TEST_NO_FAULT(&env);
/* Make sure we serialized the correct value. */
size = XMLRPC_TYPED_MEM_BLOCK_SIZE(char, output);
- TEST(size == strlen(serialized_response));
+ TEST(size == strlen(serialized_fault));
TEST(memcmp(XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, output),
- serialized_response, size) == 0);
+ serialized_fault, size) == 0);
- /* Clean up our methodResponse. */
- xmlrpc_DECREF(v);
+ /* Clean up our fault. */
+ xmlrpc_env_clean(&fault);
XMLRPC_TYPED_MEM_BLOCK_FREE(char, output);
xmlrpc_env_clean(&env);
@@ -192,33 +171,37 @@
static void
-test_serialize_methodCall(void) {
+test_serialize_apache_value(void) {
- /* Serialize a methodCall. */
+ char const serializedData[] =
+ "<value><array><data>\r\n"
+ "<value><i4>7</i4></value>\r\n"
+ "<value><ex.i8>8</ex.i8></value>\r\n"
+ "<value><ex.nil/></value>\r\n"
+ "</data></array></value>";
xmlrpc_env env;
- xmlrpc_value * v;
- xmlrpc_mem_block *output;
+ xmlrpc_value * valueP;
+ xmlrpc_mem_block * outputP;
size_t size;
-
+
xmlrpc_env_init(&env);
- output = XMLRPC_TYPED_MEM_BLOCK_NEW(char, &env, 0);
+ valueP = xmlrpc_build_value(&env, "(iIn)", 7, (xmlrpc_int64)8);
TEST_NO_FAULT(&env);
- v = xmlrpc_build_value(&env, "(ii)", (xmlrpc_int32) 10, (xmlrpc_int32) 20);
+
+ outputP = XMLRPC_MEMBLOCK_NEW(char, &env, 0);
TEST_NO_FAULT(&env);
- xmlrpc_serialize_call(&env, output, "gloom&doom", v);
+ xmlrpc_serialize_value2(&env, outputP, valueP, xmlrpc_dialect_apache);
TEST_NO_FAULT(&env);
- /* Make sure we serialized the correct value. */
- size = XMLRPC_TYPED_MEM_BLOCK_SIZE(char, output);
- TEST(size == strlen(serialized_call));
- TEST(memcmp(XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, output),
- serialized_call, size) == 0);
+ size = XMLRPC_MEMBLOCK_SIZE(char, outputP);
- /* Clean up our methodCall. */
- xmlrpc_DECREF(v);
- XMLRPC_TYPED_MEM_BLOCK_FREE(char, output);
+ TEST(size == strlen(serializedData));
+ TEST(memeq(XMLRPC_MEMBLOCK_CONTENTS(char, outputP), serializedData, size));
+
+ XMLRPC_MEMBLOCK_FREE(char, outputP);
+ xmlrpc_DECREF(valueP);
xmlrpc_env_clean(&env);
}
@@ -226,49 +209,107 @@
static void
-test_serialize_fault(void) {
- /* Serialize a fault. */
+test_serialize_apache_params(void) {
+
+ char const serializedData[] =
+ "<params>\r\n"
+ "<param><value><i4>7</i4></value></param>\r\n"
+ "<param><value><ex.i8>8</ex.i8></value></param>\r\n"
+ "</params>\r\n";
xmlrpc_env env;
- xmlrpc_env fault;
- xmlrpc_mem_block *output;
+ xmlrpc_value * paramArrayP;
+ xmlrpc_mem_block * outputP;
size_t size;
+
+ xmlrpc_env_init(&env);
+
+ paramArrayP = xmlrpc_build_value(&env, "(iI)", 7, (xmlrpc_int64)8);
+ TEST_NO_FAULT(&env);
+
+ outputP = XMLRPC_MEMBLOCK_NEW(char, &env, 0);
+ TEST_NO_FAULT(&env);
+ xmlrpc_serialize_params2(&env, outputP, paramArrayP,
+ xmlrpc_dialect_apache);
+ TEST_NO_FAULT(&env);
+
+ size = XMLRPC_MEMBLOCK_SIZE(char, outputP);
+
+ TEST(size == strlen(serializedData));
+ TEST(memeq(XMLRPC_MEMBLOCK_CONTENTS(char, outputP), serializedData, size));
+ XMLRPC_MEMBLOCK_FREE(char, outputP);
+ xmlrpc_DECREF(paramArrayP);
+
+ xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+test_serialize_apache_response(void) {
+
+ char const serializedData[] =
+ XML_PROLOGUE
+ "<methodResponse>\r\n"
+ "<params>\r\n"
+ "<param><value><ex.i8>8</ex.i8></value></param>\r\n"
+ "</params>\r\n"
+ "</methodResponse>\r\n";
+
+ xmlrpc_env env;
+ xmlrpc_value * resultP;
+ xmlrpc_mem_block * outputP;
+ size_t size;
+
xmlrpc_env_init(&env);
- output = XMLRPC_TYPED_MEM_BLOCK_NEW(char, &env, 0);
+ resultP = xmlrpc_i8_new(&env, 8);
TEST_NO_FAULT(&env);
- xmlrpc_env_init(&fault);
- xmlrpc_env_set_fault(&fault, 6, "A fault occurred");
- xmlrpc_serialize_fault(&env, output, &fault);
+
+ outputP = XMLRPC_MEMBLOCK_NEW(char, &env, 0);
+ TEST_NO_FAULT(&env);
+ xmlrpc_serialize_response2(&env, outputP, resultP,
+ xmlrpc_dialect_apache);
TEST_NO_FAULT(&env);
- /* Make sure we serialized the correct value. */
- size = XMLRPC_TYPED_MEM_BLOCK_SIZE(char, output);
- TEST(size == strlen(serialized_fault));
- TEST(memcmp(XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, output),
- serialized_fault, size) == 0);
+ size = XMLRPC_MEMBLOCK_SIZE(char, outputP);
- /* Clean up our fault. */
- xmlrpc_env_clean(&fault);
- XMLRPC_TYPED_MEM_BLOCK_FREE(char, output);
+ TEST(size == strlen(serializedData));
+ TEST(memeq(XMLRPC_MEMBLOCK_CONTENTS(char, outputP), serializedData, size));
+
+ XMLRPC_MEMBLOCK_FREE(char, outputP);
+ xmlrpc_DECREF(resultP);
xmlrpc_env_clean(&env);
}
+static void
+test_serialize_apache(void) {
+
+ /* Serialize various things using the Apache dialect of XML-RPC */
+
+ test_serialize_apache_value();
+ test_serialize_apache_params();
+ test_serialize_apache_response();
+}
+
+
+
void
test_serialize(void) {
printf("Running serialize tests.");
test_serialize_basic();
- test_serialize_double();
- test_serialize_struct();
+ printf("\n");
+ test_serialize_value();
test_serialize_methodResponse();
test_serialize_methodCall();
test_serialize_fault();
+ test_serialize_apache();
printf("\n");
printf("Serialize tests done.\n");
Added: freeswitch/trunk/libs/xmlrpc-c/src/test/serialize_value.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/test/serialize_value.c Fri May 23 16:56:24 2008
@@ -0,0 +1,240 @@
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#include "xmlrpc_config.h"
+
+#include "xmlrpc-c/base.h"
+
+#include "test.h"
+#include "girstring.h"
+
+#include "serialize_value.h"
+
+
+static void
+test_serialize_string(void) {
+
+ /* Test serialize of a string, including all the line ending
+ complexity.
+ */
+
+ xmlrpc_env env;
+ xmlrpc_value * v;
+ xmlrpc_mem_block * xmlP; /* Serialized result */
+
+ xmlrpc_env_init(&env);
+
+ TEST_NO_FAULT(&env);
+
+ v = xmlrpc_string_new(&env, "hello world");
+ TEST_NO_FAULT(&env);
+
+ xmlP = XMLRPC_MEMBLOCK_NEW(char, &env, 0);
+ xmlrpc_serialize_value(&env, xmlP, v);
+ TEST_NO_FAULT(&env);
+ TEST(memeq(XMLRPC_MEMBLOCK_CONTENTS(char, xmlP),
+ "<value><string>hello world</string></value>",
+ XMLRPC_MEMBLOCK_SIZE(char, xmlP)));
+ XMLRPC_MEMBLOCK_FREE(char, xmlP);
+ xmlrpc_DECREF(v);
+
+ v = xmlrpc_string_new(&env, "");
+ TEST_NO_FAULT(&env);
+ xmlP = XMLRPC_MEMBLOCK_NEW(char, &env, 0);
+ xmlrpc_serialize_value(&env, xmlP, v);
+ TEST_NO_FAULT(&env);
+ TEST(memeq(XMLRPC_MEMBLOCK_CONTENTS(char, xmlP),
+ "<value><string></string></value>",
+ XMLRPC_MEMBLOCK_SIZE(char, xmlP)));
+ XMLRPC_MEMBLOCK_FREE(char, xmlP);
+ xmlrpc_DECREF(v);
+
+ v = xmlrpc_string_new_lp(&env, 7, "foo\0bar");
+ TEST_NO_FAULT(&env);
+ xmlP = XMLRPC_MEMBLOCK_NEW(char, &env, 0);
+ xmlrpc_serialize_value(&env, xmlP, v);
+ TEST_NO_FAULT(&env);
+ TEST(memeq(XMLRPC_MEMBLOCK_CONTENTS(char, xmlP),
+ "<value><string>foo\0bar</string></value>",
+ XMLRPC_MEMBLOCK_SIZE(char, xmlP)));
+ XMLRPC_MEMBLOCK_FREE(char, xmlP);
+ xmlrpc_DECREF(v);
+
+ v = xmlrpc_string_new_lp(&env, 7, "foo\nbar");
+ TEST_NO_FAULT(&env);
+ xmlP = XMLRPC_MEMBLOCK_NEW(char, &env, 0);
+ xmlrpc_serialize_value(&env, xmlP, v);
+ TEST_NO_FAULT(&env);
+ TEST(memeq(XMLRPC_MEMBLOCK_CONTENTS(char, xmlP),
+ "<value><string>foo\nbar</string></value>",
+ XMLRPC_MEMBLOCK_SIZE(char, xmlP)));
+ XMLRPC_MEMBLOCK_FREE(char, xmlP);
+ xmlrpc_DECREF(v);
+
+ v = xmlrpc_string_new_lp(&env, 8, "foo\r\nbar");
+ TEST_NO_FAULT(&env);
+ xmlP = XMLRPC_MEMBLOCK_NEW(char, &env, 0);
+ xmlrpc_serialize_value(&env, xmlP, v);
+ TEST_NO_FAULT(&env);
+ TEST(memeq(XMLRPC_MEMBLOCK_CONTENTS(char, xmlP),
+ "<value><string>foo\nbar</string></value>",
+ XMLRPC_MEMBLOCK_SIZE(char, xmlP)));
+ XMLRPC_MEMBLOCK_FREE(char, xmlP);
+ xmlrpc_DECREF(v);
+
+ v = xmlrpc_string_new_lp(&env, 7, "foo\rbar");
+ TEST_NO_FAULT(&env);
+ xmlP = XMLRPC_MEMBLOCK_NEW(char, &env, 0);
+ xmlrpc_serialize_value(&env, xmlP, v);
+ TEST_NO_FAULT(&env);
+ TEST(memeq(XMLRPC_MEMBLOCK_CONTENTS(char, xmlP),
+ "<value><string>foo\nbar</string></value>",
+ XMLRPC_MEMBLOCK_SIZE(char, xmlP)));
+ XMLRPC_MEMBLOCK_FREE(char, xmlP);
+ xmlrpc_DECREF(v);
+
+ v = xmlrpc_string_new_lp_cr(&env, 7, "foo\rbar");
+ TEST_NO_FAULT(&env);
+ xmlP = XMLRPC_MEMBLOCK_NEW(char, &env, 0);
+ xmlrpc_serialize_value(&env, xmlP, v);
+ TEST_NO_FAULT(&env);
+ TEST(memeq(XMLRPC_MEMBLOCK_CONTENTS(char, xmlP),
+ "<value><string>foo
bar</string></value>",
+ XMLRPC_MEMBLOCK_SIZE(char, xmlP)));
+ XMLRPC_MEMBLOCK_FREE(char, xmlP);
+ xmlrpc_DECREF(v);
+
+ xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+testOneDouble(double const value) {
+
+ /* Test serialize of a double. */
+
+ xmlrpc_env env;
+ xmlrpc_value * valueP;
+ xmlrpc_mem_block * serializedP;
+ char * result;
+ /* serialized result, as asciiz string */
+ size_t resultLength;
+ /* Length in characters of the serialized result */
+ double serializedValue;
+ char nextChar;
+ int itemsMatched;
+
+ xmlrpc_env_init(&env);
+
+ /* Build a double to serialize */
+ valueP = xmlrpc_double_new(&env, value);
+ TEST_NO_FAULT(&env);
+
+ /* Serialize the value. */
+ serializedP = XMLRPC_MEMBLOCK_NEW(char, &env, 0);
+ TEST_NO_FAULT(&env);
+ xmlrpc_serialize_value(&env, serializedP, valueP);
+ TEST_NO_FAULT(&env);
+
+ /* Make sure we serialized the correct value. Note that because
+ doubles aren't precise, this might serialize as 3.1415899999
+ or something like that. So we check it arithmetically.
+ */
+ resultLength = XMLRPC_MEMBLOCK_SIZE(char, serializedP);
+ result = malloc(resultLength + 1);
+
+ memcpy(result, XMLRPC_MEMBLOCK_CONTENTS(char, serializedP), resultLength);
+ result[resultLength] = '\0';
+
+ itemsMatched = sscanf(result,
+ "<value><double>%lf</double></value>\r\n%c",
+ &serializedValue, &nextChar);
+
+ TEST(itemsMatched == 1);
+ TESTFLOATEQUAL(serializedValue, value);
+
+ free(result);
+
+ /* Clean up our value. */
+ XMLRPC_TYPED_MEM_BLOCK_FREE(char, serializedP);
+ xmlrpc_DECREF(valueP);
+
+ xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+test_serialize_double(void) {
+
+ testOneDouble(0);
+ testOneDouble(1);
+ testOneDouble(0.3);
+ testOneDouble(4.9);
+ testOneDouble(-8);
+ testOneDouble(-.7);
+ testOneDouble(-2.5);
+ testOneDouble(3.14159);
+ testOneDouble(1.2E37);
+ testOneDouble(1.2E-37);
+ testOneDouble(-5E200);
+}
+
+
+
+static void
+test_serialize_struct(void) {
+
+ /* Serialize a simple struct. */
+
+ char const serialized_struct[] =
+ "<value><struct>\r\n" \
+ "<member><name><&></name>\r\n" \
+ "<value><i4>10</i4></value></member>\r\n" \
+ "</struct></value>";
+
+ xmlrpc_env env;
+ xmlrpc_value * v;
+ xmlrpc_mem_block *output;
+ size_t size;
+
+ xmlrpc_env_init(&env);
+
+ v = xmlrpc_build_value(&env, "{s:i}", "<&>", (xmlrpc_int32) 10);
+ TEST_NO_FAULT(&env);
+ output = XMLRPC_TYPED_MEM_BLOCK_NEW(char, &env, 0);
+ TEST_NO_FAULT(&env);
+ xmlrpc_serialize_value(&env, output, v);
+ TEST_NO_FAULT(&env);
+
+ /* Make sure we serialized the correct value. */
+ size = XMLRPC_TYPED_MEM_BLOCK_SIZE(char, output);
+ TEST(size == strlen(serialized_struct));
+ TEST(memcmp(XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, output),
+ serialized_struct, size) == 0);
+
+ /* Clean up our struct. */
+ XMLRPC_TYPED_MEM_BLOCK_FREE(char, output);
+ xmlrpc_DECREF(v);
+
+ xmlrpc_env_clean(&env);
+}
+
+
+
+void
+test_serialize_value(void) {
+
+ printf(" Running serialize value tests.");
+
+ test_serialize_string();
+
+ test_serialize_double();
+
+ test_serialize_struct();
+
+ printf("\n");
+ printf(" Serialize value tests done.\n");
+}
Added: freeswitch/trunk/libs/xmlrpc-c/src/test/serialize_value.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/test/serialize_value.h Fri May 23 16:56:24 2008
@@ -0,0 +1,7 @@
+#ifndef SERIALIZE_VALUE_H_INCLUDED
+#define SERIALIZE_VALUE_H_INCLUDED
+
+void
+test_serialize_value(void);
+
+#endif
Modified: freeswitch/trunk/libs/xmlrpc-c/src/test/server_abyss.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/src/test/server_abyss.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/src/test/server_abyss.c Fri May 23 16:56:24 2008
@@ -1,3 +1,4 @@
+#include "unistdx.h"
#include <stdio.h>
#include "xmlrpc_config.h"
@@ -12,33 +13,137 @@
#include "server_abyss.h"
-void
-test_server_abyss(void) {
-
+static void
+testSetHandlers(TServer * const abyssServerP) {
xmlrpc_env env;
xmlrpc_registry * registryP;
- TServer abyssServer;
- printf("Running Abyss server tests...\n");
+ xmlrpc_env_init(&env);
+
+ registryP = xmlrpc_registry_new(&env);
+ TEST_NO_FAULT(&env);
+ TEST(registryP != NULL);
+
+ xmlrpc_server_abyss_set_handler(&env, abyssServerP, "/RPC3", registryP);
+ TEST_NO_FAULT(&env);
+
+ xmlrpc_server_abyss_set_handlers2(abyssServerP, "/RPC4", registryP);
+
+ xmlrpc_registry_free(registryP);
+
+ {
+ xmlrpc_registry * registryP;
+ registryP = xmlrpc_registry_new(&env);
+ xmlrpc_server_abyss_set_handlers(abyssServerP, registryP);
+ xmlrpc_registry_free(registryP);
+ }
+ xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+testServerParms(void) {
+ xmlrpc_server_abyss_parms parms;
+
+ parms.config_file_name = NULL;
+ parms.registryP = NULL;
+ parms.port_number = 1000;
+ parms.log_file_name = "/tmp/xmlrpc_logfile";
+ parms.keepalive_timeout = 5;
+ parms.keepalive_max_conn = 4;
+ parms.timeout = 50;
+ parms.dont_advertise = TRUE;
+ parms.uri_path = "/RPC9";
+ parms.chunk_response = TRUE;
+};
+
+
+
+static void
+testObject(void) {
+
+ xmlrpc_env env;
+ xmlrpc_server_abyss_parms parms;
+ xmlrpc_server_abyss_t * serverP;
+ xmlrpc_registry * registryP;
+ xmlrpc_server_abyss_sig * oldHandlersP;
xmlrpc_env_init(&env);
registryP = xmlrpc_registry_new(&env);
+ TEST_NO_FAULT(&env);
+
+ parms.config_file_name = NULL;
+ parms.registryP = registryP;
+
+ serverP = NULL;
+
+ xmlrpc_server_abyss_create(&env, &parms, XMLRPC_APSIZE(registryP),
+ &serverP);
+
+ TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR); /* Global init not done */
+
+ xmlrpc_server_abyss_global_init(&env);
+ TEST_NO_FAULT(&env);
+
+ xmlrpc_server_abyss_create(&env, &parms, XMLRPC_APSIZE(registryP),
+ &serverP);
+
+ TEST_NO_FAULT(&env);
+ TEST(serverP != NULL);
+
+ xmlrpc_server_abyss_terminate(&env, serverP);
+ TEST_NO_FAULT(&env);
+
+ xmlrpc_server_abyss_reset_terminate(&env, serverP);
+ TEST_NO_FAULT(&env);
+
+ xmlrpc_server_abyss_setup_sig(&env, serverP, &oldHandlersP);
+ TEST_NO_FAULT(&env);
+
+ xmlrpc_server_abyss_use_sigchld(serverP);
- TEST(registryP != NULL);
+ xmlrpc_server_abyss_restore_sig(oldHandlersP);
TEST_NO_FAULT(&env);
- ServerCreate(&abyssServer, "testserver", 8080, NULL, NULL);
+ xmlrpc_server_abyss_destroy(serverP);
- xmlrpc_server_abyss_set_handlers(&abyssServer, registryP);
+ xmlrpc_registry_free(registryP);
- xmlrpc_server_abyss_set_handler(&env, &abyssServer, "/RPC3", registryP);
+ xmlrpc_server_abyss_global_term();
- TEST_NO_FAULT(&env);
+ xmlrpc_server_abyss_setup_sig(&env, serverP, &oldHandlersP);
+ TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR); /* Not globally initialized */
+
+ xmlrpc_env_clean(&env);
+}
+
+
+
+void
+test_server_abyss(void) {
+
+ TServer abyssServer;
+
+ printf("Running Abyss XML-RPC server tests...\n");
+
+ ServerCreate(&abyssServer, "testserver", 8080, NULL, NULL);
+
+ testSetHandlers(&abyssServer);
+
+ ServerSetKeepaliveTimeout(&abyssServer, 60);
+ ServerSetKeepaliveMaxConn(&abyssServer, 10);
+ ServerSetTimeout(&abyssServer, 0);
+ ServerSetAdvertise(&abyssServer, FALSE);
ServerFree(&abyssServer);
+ testServerParms();
+
+ testObject();
+
printf("\n");
- printf("Abyss server tests done.\n");
+ printf("Abyss XML-RPC server tests done.\n");
}
Modified: freeswitch/trunk/libs/xmlrpc-c/src/test/test.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/src/test/test.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/src/test/test.c Fri May 23 16:56:24 2008
@@ -1,16 +1,24 @@
/* Copyright information is at the end of the file. */
+#ifdef WIN32
+#include <direct.h>
+#else
+#include <unistd.h>
+#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
+#include "casprintf.h"
+
#include "xmlrpc_config.h"
#include "xmlrpc-c/base.h"
#include "xmlrpc-c/server.h"
+#include "bool.h"
#include "test.h"
#include "value.h"
#include "serialize.h"
@@ -18,7 +26,9 @@
#include "cgi.h"
#include "xml_data.h"
#include "client.h"
+#include "abyss.h"
#include "server_abyss.h"
+#include "method_registry.h"
/*=========================================================================
** Test Harness
@@ -40,6 +50,13 @@
int total_tests = 0;
int total_failures = 0;
+bool const runningUnderWindows =
+#ifdef WIN32
+ true;
+#else
+ false;
+#endif
+
/*=========================================================================
** Test Data
@@ -62,7 +79,6 @@
static void test_env(void)
{
xmlrpc_env env, env2;
- char *s;
/* Test xmlrpc_env_init. */
xmlrpc_env_init(&env);
@@ -89,13 +105,6 @@
TEST(env.fault_code == 3);
TEST(strcmp(env.fault_string, "abar9") == 0);
- /* Set a fault with an oversized string. */
- s = "12345678901234567890123456789012345678901234567890";
- xmlrpc_env_set_fault_formatted(&env, 4, "%s%s%s%s%s%s", s, s, s, s, s, s);
- TEST(env.fault_occurred);
- TEST(env.fault_code == 4);
- TEST(strlen(env.fault_string) == 255);
-
/* Test cleanup code (with help from memprof). */
xmlrpc_env_clean(&env);
@@ -195,15 +204,19 @@
"ZmdoaWprbG1ub3BxcnN0dXZ3eHl6QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo=\r\n",
NULL};
-static void test_base64_conversion (void)
-{
- xmlrpc_env env, env2;
- char **triplet, *bin_data, *nocrlf_ascii_data, *ascii_data;
- xmlrpc_mem_block *output;
+static void
+test_base64_conversion(void) {
+ xmlrpc_env env;
+ char ** triplet;
xmlrpc_env_init(&env);
for (triplet = base64_triplets; *triplet != NULL; triplet += 3) {
+ char * bin_data;
+ char * nocrlf_ascii_data;
+ char * ascii_data;
+ xmlrpc_mem_block * output;
+
bin_data = *triplet;
nocrlf_ascii_data = *(triplet + 1);
ascii_data = *(triplet + 2);
@@ -242,19 +255,26 @@
}
/* Now for something broken... */
- xmlrpc_env_init(&env2);
- output = xmlrpc_base64_decode(&env2, "====", 4);
- TEST(output == NULL);
- TEST_FAULT(&env2, XMLRPC_PARSE_ERROR);
- xmlrpc_env_clean(&env2);
+ {
+ xmlrpc_env env2;
+ xmlrpc_mem_block * output;
+ xmlrpc_env_init(&env2);
+ output = xmlrpc_base64_decode(&env2, "====", 4);
+ TEST(output == NULL);
+ TEST_FAULT(&env2, XMLRPC_PARSE_ERROR);
+ xmlrpc_env_clean(&env2);
+ }
/* Now for something broken in a really sneaky way... */
- xmlrpc_env_init(&env2);
- output = xmlrpc_base64_decode(&env2, "a==", 4);
- TEST(output == NULL);
- TEST_FAULT(&env2, XMLRPC_PARSE_ERROR);
- xmlrpc_env_clean(&env2);
-
+ {
+ xmlrpc_env env2;
+ xmlrpc_mem_block * output;
+ xmlrpc_env_init(&env2);
+ output = xmlrpc_base64_decode(&env2, "a==", 4);
+ TEST(output == NULL);
+ TEST_FAULT(&env2, XMLRPC_PARSE_ERROR);
+ xmlrpc_env_clean(&env2);
+ }
xmlrpc_env_clean(&env);
}
@@ -290,249 +310,6 @@
-/*=========================================================================
-** test_method_registry
-**=========================================================================
-** We need to define some static callbacks to test this code.
-*/
-
-#define FOO_USER_DATA ((void*) 0xF00)
-#define BAR_USER_DATA ((void*) 0xBAF)
-
-static xmlrpc_value *test_foo (xmlrpc_env *env,
- xmlrpc_value *param_array,
- void *user_data)
-{
- xmlrpc_int32 x, y;
-
- TEST_NO_FAULT(env);
- TEST(param_array != NULL);
- TEST(user_data == FOO_USER_DATA);
-
- xmlrpc_decompose_value(env, param_array, "(ii)", &x, &y);
- TEST_NO_FAULT(env);
- TEST(x == 25);
- TEST(y == 17);
-
- return xmlrpc_build_value(env, "i", (xmlrpc_int32) x + y);
-}
-
-static xmlrpc_value *test_bar (xmlrpc_env *env,
- xmlrpc_value *param_array,
- void *user_data)
-{
- xmlrpc_int32 x, y;
-
- TEST_NO_FAULT(env);
- TEST(param_array != NULL);
- TEST(user_data == BAR_USER_DATA);
-
- xmlrpc_decompose_value(env, param_array, "(ii)", &x, &y);
- TEST_NO_FAULT(env);
- TEST(x == 25);
- TEST(y == 17);
-
- xmlrpc_env_set_fault(env, 123, "Test fault");
- return NULL;
-}
-
-static xmlrpc_value *
-test_default(xmlrpc_env * const env,
- const char * const host ATTR_UNUSED,
- const char * const method_name ATTR_UNUSED,
- xmlrpc_value * const param_array,
- void * const user_data) {
-
- xmlrpc_int32 x, y;
-
- TEST_NO_FAULT(env);
- TEST(param_array != NULL);
- TEST(user_data == FOO_USER_DATA);
-
- xmlrpc_decompose_value(env, param_array, "(ii)", &x, &y);
- TEST_NO_FAULT(env);
- TEST(x == 25);
- TEST(y == 17);
-
- return xmlrpc_build_value(env, "i", 2 * (x + y));
-}
-
-static xmlrpc_value *
-process_call_helper (xmlrpc_env *env,
- xmlrpc_registry *registry,
- const char *method_name,
- xmlrpc_value *arg_array)
-{
- xmlrpc_mem_block *call, *response;
- xmlrpc_value *value;
-
- /* Build a call, and tell the registry to handle it. */
- call = xmlrpc_mem_block_new(env, 0);
- TEST_NO_FAULT(env);
- xmlrpc_serialize_call(env, call, method_name, arg_array);
- TEST_NO_FAULT(env);
- response = xmlrpc_registry_process_call(env, registry, NULL,
- xmlrpc_mem_block_contents(call),
- xmlrpc_mem_block_size(call));
- TEST_NO_FAULT(env);
- TEST(response != NULL);
-
- /* Parse the response. */
- value = xmlrpc_parse_response(env, xmlrpc_mem_block_contents(response),
- xmlrpc_mem_block_size(response));
-
- xmlrpc_mem_block_free(call);
- xmlrpc_mem_block_free(response);
- return value;
-}
-
-
-
-static void
-test_method_registry(void) {
-
- xmlrpc_env env, env2;
- xmlrpc_value *arg_array, *value;
- xmlrpc_registry *registry;
- xmlrpc_mem_block *response;
- xmlrpc_int32 i;
-
- xmlrpc_value *multi;
- xmlrpc_int32 foo1_result, foo2_result;
- xmlrpc_int32 bar_code, nosuch_code, multi_code, bogus1_code, bogus2_code;
- char *bar_string, *nosuch_string, *multi_string;
- char *bogus1_string, *bogus2_string;
-
- xmlrpc_env_init(&env);
-
- /* Create a new registry. */
- registry = xmlrpc_registry_new(&env);
- TEST(registry != NULL);
- TEST_NO_FAULT(&env);
-
- /* Add some test methods. */
- xmlrpc_registry_add_method(&env, registry, NULL, "test.foo",
- test_foo, FOO_USER_DATA);
- TEST_NO_FAULT(&env);
- xmlrpc_registry_add_method(&env, registry, NULL, "test.bar",
- test_bar, BAR_USER_DATA);
- TEST_NO_FAULT(&env);
-
- /* Build an argument array for our calls. */
- arg_array = xmlrpc_build_value(&env, "(ii)",
- (xmlrpc_int32) 25, (xmlrpc_int32) 17);
- TEST_NO_FAULT(&env);
-
- /* Call test.foo and check the result. */
- value = process_call_helper(&env, registry, "test.foo", arg_array);
- TEST_NO_FAULT(&env);
- TEST(value != NULL);
- xmlrpc_decompose_value(&env, value, "i", &i);
- xmlrpc_DECREF(value);
- TEST_NO_FAULT(&env);
- TEST(i == 42);
-
- /* Call test.bar and check the result. */
- xmlrpc_env_init(&env2);
- value = process_call_helper(&env2, registry, "test.bar", arg_array);
- TEST_FAULT(&env2, 123);
- TEST(env2.fault_string && strcmp(env2.fault_string, "Test fault") == 0);
- xmlrpc_env_clean(&env2);
-
- /* Call a non-existant method and check the result. */
- xmlrpc_env_init(&env2);
- value = process_call_helper(&env2, registry, "test.nosuch", arg_array);
- TEST(value == NULL);
- TEST_FAULT(&env2, XMLRPC_NO_SUCH_METHOD_ERROR);
- xmlrpc_env_clean(&env2);
-
- /* Test system.multicall. */
- multi = xmlrpc_build_value(&env,
- "(({s:s,s:V}{s:s,s:V}{s:s,s:V}"
- "{s:s,s:()}s{}{s:s,s:V}))",
- "methodName", "test.foo",
- "params", arg_array,
- "methodName", "test.bar",
- "params", arg_array,
- "methodName", "test.nosuch",
- "params", arg_array,
- "methodName", "system.multicall",
- "params",
- "bogus_entry",
- "methodName", "test.foo",
- "params", arg_array);
- TEST_NO_FAULT(&env);
- value = process_call_helper(&env, registry, "system.multicall", multi);
- TEST_NO_FAULT(&env);
- xmlrpc_decompose_value(&env, value,
- "((i){s:i,s:s,*}{s:i,s:s,*}"
- "{s:i,s:s,*}{s:i,s:s,*}{s:i,s:s,*}(i))",
- &foo1_result,
- "faultCode", &bar_code,
- "faultString", &bar_string,
- "faultCode", &nosuch_code,
- "faultString", &nosuch_string,
- "faultCode", &multi_code,
- "faultString", &multi_string,
- "faultCode", &bogus1_code,
- "faultString", &bogus1_string,
- "faultCode", &bogus2_code,
- "faultString", &bogus2_string,
- &foo2_result);
- xmlrpc_DECREF(value);
- TEST_NO_FAULT(&env);
- TEST(foo1_result == 42);
- TEST(bar_code == 123);
- TEST(strcmp(bar_string, "Test fault") == 0);
- TEST(nosuch_code == XMLRPC_NO_SUCH_METHOD_ERROR);
- TEST(multi_code == XMLRPC_REQUEST_REFUSED_ERROR);
- TEST(foo2_result == 42);
- xmlrpc_DECREF(multi);
- free(bar_string);
- free(nosuch_string);
- free(multi_string);
- free(bogus1_string);
- free(bogus2_string);
-
- /* PASS bogus XML data and make sure our parser pukes gracefully.
- ** (Because of the way the code is laid out, and the presence of other
- ** test suites, this lets us skip tests for invalid XML-RPC data.) */
- xmlrpc_env_init(&env2);
- response = xmlrpc_registry_process_call(&env, registry, NULL,
- expat_error_data,
- strlen(expat_error_data));
- TEST_NO_FAULT(&env);
- TEST(response != NULL);
- value = xmlrpc_parse_response(&env2, xmlrpc_mem_block_contents(response),
- xmlrpc_mem_block_size(response));
- TEST(value == NULL);
- TEST_FAULT(&env2, XMLRPC_PARSE_ERROR);
- xmlrpc_mem_block_free(response);
- xmlrpc_env_clean(&env2);
-
- xmlrpc_registry_set_default_method(&env, registry, &test_default,
- FOO_USER_DATA);
- TEST_NO_FAULT(&env);
- value = process_call_helper(&env, registry, "test.nosuch", arg_array);
- TEST_NO_FAULT(&env);
- TEST(value != NULL);
- xmlrpc_decompose_value(&env, value, "i", &i);
- xmlrpc_DECREF(value);
- TEST_NO_FAULT(&env);
- TEST(i == 84);
-
- /* Change the default method. */
- xmlrpc_registry_set_default_method(&env, registry, &test_default,
- BAR_USER_DATA);
- TEST_NO_FAULT(&env);
-
- /* Test cleanup code (w/memprof). */
- xmlrpc_registry_free(registry);
- xmlrpc_DECREF(arg_array);
-
- xmlrpc_env_clean(&env);
-}
-
static void test_nesting_limit (void)
{
xmlrpc_env env;
@@ -540,16 +317,21 @@
xmlrpc_env_init(&env);
- /* Test with an adequate limit for (...(...()...)...). */
- xmlrpc_limit_set(XMLRPC_NESTING_LIMIT_ID, 2);
- val = xmlrpc_parse_response(&env, correct_value, strlen(correct_value));
+ /* Test with an adequate limit for a result value which is an
+ array which contains an element which is a struct, whose values
+ are simple: 3.
+ */
+ xmlrpc_limit_set(XMLRPC_NESTING_LIMIT_ID, 3);
+ val = xmlrpc_parse_response(&env,
+ good_response_xml, strlen(good_response_xml));
TEST_NO_FAULT(&env);
TEST(val != NULL);
xmlrpc_DECREF(val);
/* Test with an inadequate limit. */
- xmlrpc_limit_set(XMLRPC_NESTING_LIMIT_ID, 1);
- val = xmlrpc_parse_response(&env, correct_value, strlen(correct_value));
+ xmlrpc_limit_set(XMLRPC_NESTING_LIMIT_ID, 2);
+ val = xmlrpc_parse_response(&env,
+ good_response_xml, strlen(good_response_xml));
TEST_FAULT(&env, XMLRPC_PARSE_ERROR); /* BREAKME - Will change. */
TEST(val == NULL);
@@ -561,16 +343,19 @@
xmlrpc_env_clean(&env);
}
-static void test_xml_size_limit (void)
-{
+
+
+static void
+test_xml_size_limit(void) {
+
xmlrpc_env env;
- const char *method_name;
- xmlrpc_value *params, *val;
+ const char * methodName;
+ xmlrpc_value * paramsP;
-
/* NOTE - This test suite only verifies the last-ditch size-checking
- ** code. There should also be matching code in all server (and
- ** preferably all client) modules as well. */
+ code. There should also be matching code in all server (and
+ preferably all client) modules as well.
+ */
/* Set our XML size limit to something ridiculous. */
xmlrpc_limit_set(XMLRPC_XML_SIZE_LIMIT_ID, 6);
@@ -578,23 +363,29 @@
/* Attempt to parse a call. */
xmlrpc_env_init(&env);
xmlrpc_parse_call(&env, serialized_call, strlen(serialized_call),
- &method_name, ¶ms);
+ &methodName, ¶msP);
TEST_FAULT(&env, XMLRPC_LIMIT_EXCEEDED_ERROR);
- TEST(method_name == NULL);
- TEST(params == NULL);
- xmlrpc_env_clean(&env);
-
- /* Attempt to parse a response. */
- xmlrpc_env_init(&env);
- val = xmlrpc_parse_response(&env, correct_value, strlen(correct_value));
- TEST_FAULT(&env, XMLRPC_LIMIT_EXCEEDED_ERROR);
- TEST(val == NULL);
xmlrpc_env_clean(&env);
+ {
+ xmlrpc_value * resultP;
+ int faultCode;
+ const char * faultString;
+
+ /* Attempt to parse a response. */
+ xmlrpc_env_init(&env);
+ xmlrpc_parse_response2(&env,
+ good_response_xml, strlen(good_response_xml),
+ &resultP, &faultCode, &faultString);
+ TEST_FAULT(&env, XMLRPC_LIMIT_EXCEEDED_ERROR);
+ xmlrpc_env_clean(&env);
+ }
/* Reset the default limit. */
xmlrpc_limit_set(XMLRPC_XML_SIZE_LIMIT_ID, XMLRPC_XML_SIZE_LIMIT_DEFAULT);
}
+
+
/*=========================================================================
** test_sample_files
**=========================================================================
@@ -602,67 +393,105 @@
** results.
**
** We use these files to test strange-but-legal encodings, illegal-but-
-** supported encodings, etc.
+** allowed-by-Xmlrpc-c encodings, etc.
*/
+#ifdef WIN32
+/* usually compiled in 'Windows' folder */
+#define TESTDATA_DIR ".." DIRECTORY_SEPARATOR "bin" DIRECTORY_SEPARATOR "data"
+#else
+#define TESTDATA_DIR "data"
+#endif
-static char *good_requests[] = {
- "req_out_of_order.xml",
- "req_no_params.xml",
- "req_value_name.xml",
+static const char * goodRequests[] = {
+ TESTDATA_DIR DIRECTORY_SEPARATOR "req_out_of_order.xml",
+ TESTDATA_DIR DIRECTORY_SEPARATOR "req_no_params.xml",
+ TESTDATA_DIR DIRECTORY_SEPARATOR "req_value_name.xml",
NULL
};
#define MAX_SAMPLE_FILE_LEN (16 * 1024)
-static char file_buff [MAX_SAMPLE_FILE_LEN];
+
static void
-read_file (char *path, char **out_data, size_t *out_size)
-{
- FILE *f;
- size_t bytes_read;
+reportFileOpenError(const char * const path,
+ int const openErrno) {
+
+ if (runningUnderWindows) {
+ char cwdname[1024];
+ char * succeeded;
+
+ succeeded = getcwd(cwdname, sizeof(cwdname));
+ if (succeeded)
+ fprintf(stderr, "Running in current work directory '%s'\n",
+ cwdname);
+ }
+ fprintf(stderr, "Could not open file '%s'. errno=%d (%s)\n",
+ path, openErrno, strerror(openErrno));
+}
+
+
- /* Open the file. */
- f = fopen(path, "r");
- if (f == NULL) {
+static void
+readFile(const char * const path,
+ const char ** const outDataP,
+ size_t * const outSizeP) {
+
+ static char fileBuff[MAX_SAMPLE_FILE_LEN];
+
+ FILE * fileP;
+ size_t bytesRead;
+
+ fileP = fopen(path, "r");
+
+ if (fileP == NULL) {
/* Since this error is fairly likely to happen, give an
- ** informative error message... */
- fflush(stdout);
- fprintf(stderr, "Could not open file '%s'. errno=%d (%s)\n",
- path, errno, strerror(errno));
- abort();
+ informative error message...
+ */
+ reportFileOpenError(path, errno);
+ exit(1);
}
/* Read in one buffer full of data, and make sure that everything
- ** fit. (We perform a lazy error/no-eof/zero-length-file test using
- ** bytes_read.) */
- bytes_read = fread(file_buff, sizeof(char), MAX_SAMPLE_FILE_LEN, f);
- TEST(0 < bytes_read && bytes_read < MAX_SAMPLE_FILE_LEN);
-
- /* Close the file and return our data. */
- fclose(f);
- *out_data = file_buff;
- *out_size = bytes_read;
+ fit. (We perform a lazy error/no-eof/zero-length-file test using
+ 'bytesRead'.)
+ */
+ bytesRead = fread(fileBuff, sizeof(char), MAX_SAMPLE_FILE_LEN, fileP);
+ TEST(0 < bytesRead && bytesRead < MAX_SAMPLE_FILE_LEN);
+
+ fclose(fileP);
+
+ *outDataP = fileBuff;
+ *outSizeP = bytesRead;
}
-static void test_sample_files (void)
-{
+
+
+static void
+testSampleFiles(void) {
+
xmlrpc_env env;
- char **paths, *path;
- char *data;
- size_t data_len;
- const char *method_name;
- xmlrpc_value *params;
+ const char ** pathP;
xmlrpc_env_init(&env);
/* Test our good requests. */
- for (paths = good_requests; *paths != NULL; paths++) {
- path = *paths;
- read_file(path, &data, &data_len);
- xmlrpc_parse_call(&env, data, data_len, &method_name, ¶ms);
+
+ for (pathP = goodRequests; *pathP != NULL; ++pathP) {
+ const char * const path = *pathP;
+
+ const char * data;
+ size_t dataLen;
+ const char * methodName;
+ xmlrpc_value * params;
+
+ readFile(path, &data, &dataLen);
+
+ xmlrpc_parse_call(&env, data, dataLen, &methodName, ¶ms);
+
TEST_NO_FAULT(&env);
- strfree(method_name);
+
+ strfree(methodName);
xmlrpc_DECREF(params);
}
@@ -679,7 +508,7 @@
** http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
*/
-#ifdef HAVE_UNICODE_WCHAR
+#if HAVE_UNICODE_WCHAR
typedef struct {
char *utf8;
@@ -760,6 +589,7 @@
NULL
};
+#endif /* HAVE_UNICODE_WCHAR */
/* This routine is missing on certain platforms. This implementation
** *appears* to be correct. */
@@ -782,8 +612,10 @@
#endif /* HAVE_WCSNCMP */
#endif
-static void test_utf8_coding (void)
-{
+static void
+test_utf8_coding(void) {
+
+#if HAVE_UNICODE_WCHAR
xmlrpc_env env, env2;
utf8_and_wcs *good_data;
char **bad_data;
@@ -841,72 +673,87 @@
TEST(output == NULL);
xmlrpc_env_clean(&env2);
}
-
xmlrpc_env_clean(&env);
+#endif /* HAVE_UNICODE_WCHAR */
}
-#endif /* HAVE_UNICODE_WCHAR */
-
-
-/*=========================================================================
-** Test Driver
-**=========================================================================
-*/
-int
-main(int argc,
- char ** argv ATTR_UNUSED) {
- if (argc-1 > 0) {
- fprintf(stderr, "There are no arguments.");
- exit(1);
- }
+static void
+test_server_cgi_maybe(void) {
- /* Add your test suites here. */
- test_env();
- test_mem_block();
- test_base64_conversion();
- printf("\n");
- test_value();
- test_bounds_checks();
- printf("\n");
- test_serialize();
- test_parse_xml();
-
- test_method_registry();
- test_nesting_limit();
- test_xml_size_limit();
- test_sample_files();
- printf("\n");
+#ifndef WIN32
-#ifndef WIN32 /* CGI unsupported in Windows */
test_server_cgi();
+
#endif
- test_server_abyss();
+}
+
-#ifdef HAVE_UNICODE_WCHAR
- test_utf8_coding();
-#endif /* HAVE_UNICODE_WCHAR */
- printf("\n");
+static void
+test_client_maybe(void) {
+
+#ifndef WIN32 /* Must get Windows Curl transport working for this to work */
-#ifndef WIN32 /* TODO: Client test uses curl... */
test_client();
+
#endif
+}
- /* Summarize our test run. */
- printf("\nRan %d tests, %d failed, %.1f%% passed\n",
- total_tests, total_failures,
- 100.0 - (100.0 * total_failures) / total_tests);
-
- /* Print the final result. */
- if (total_failures == 0) {
- printf("OK\n");
- return 0;
- }
- printf("FAILED\n");
- return 1;
+
+int
+main(int argc,
+ char ** argv ATTR_UNUSED) {
+
+ int retval;
+
+ if (argc-1 > 0) {
+ fprintf(stderr, "There are no arguments.\n");
+ retval = 1;
+ } else {
+ test_env();
+ test_mem_block();
+ test_base64_conversion();
+ printf("\n");
+ test_value();
+ test_bounds_checks();
+ printf("\n");
+ test_serialize();
+ test_parse_xml();
+ test_method_registry();
+ test_nesting_limit();
+ test_xml_size_limit();
+ testSampleFiles();
+ printf("\n");
+ test_server_cgi_maybe();
+ test_abyss();
+ test_server_abyss();
+
+ test_utf8_coding();
+
+ printf("\n");
+
+ test_client_maybe();
+
+ printf("\n");
+
+ /* Summarize our test run. */
+ printf("Ran %d tests, %d failed, %.1f%% passed\n",
+ total_tests, total_failures,
+ 100.0 - (100.0 * total_failures) / total_tests);
+
+ /* Print the final result. */
+ if (total_failures == 0) {
+ printf("OK\n");
+ retval = 0;
+ } else {
+ retval = 1;
+ printf("FAILED\n");
+ }
+ }
+ return retval;
}
Modified: freeswitch/trunk/libs/xmlrpc-c/src/test/test.h
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/src/test/test.h (original)
+++ freeswitch/trunk/libs/xmlrpc-c/src/test/test.h Fri May 23 16:56:24 2008
@@ -1,19 +1,17 @@
#include <stdlib.h>
#include <stdio.h>
+#include <math.h>
+
+#include "xmlrpc_config.h"
+#include "xmlrpc-c/util.h"
+#include "xmlrpc-c/util_int.h"
extern int total_tests;
extern int total_failures;
-static __inline void
-strfree(const char * const string) {
- free((char*)string);
-}
-
-
-
/* This is a good place to set a breakpoint. */
-static __inline void
+static __inline__ void
test_failure(const char * const file,
unsigned int const line,
const char * const label,
@@ -47,21 +45,65 @@
} \
} while (0)
-#define TEST_FAULT(env, code) \
-do { \
- ++total_tests; \
- if ((env)->fault_occurred && (env)->fault_code == (code)) { \
- printf("."); \
- } else { \
- test_failure(__FILE__, __LINE__, "wrong/no fault occurred", \
- (env)->fault_string); \
- } \
- } while (0)
+#define TEST_EPSILON 1E-5
+
+#define FORCENONZERO(x) (MAX(fabs(x), TEST_EPSILON))
+#define FLOATEQUAL(comparand, comparator) \
+ ((fabs((comparand)-(comparator)))/FORCENONZERO(comparand) < TEST_EPSILON)
+#define TESTFLOATEQUAL(comparand, comparator) \
+ TEST(FLOATEQUAL(comparand, comparator))
+
+static __inline__ void
+test_fault(xmlrpc_env * const envP,
+ int const expectedCode,
+ const char * const fileName,
+ unsigned int const lineNumber) {
+
+ ++total_tests;
+
+ if (!envP->fault_occurred)
+ test_failure(fileName, lineNumber, "no fault occurred", "");
+ else if (envP->fault_code != expectedCode)
+ test_failure(fileName, lineNumber, "wrong fault occurred",
+ envP->fault_string);
+ else
+ printf(".");
+ xmlrpc_env_clean(envP);
+ xmlrpc_env_init(envP);
+}
+
+
+#define TEST_FAULT(envP, code) \
+ do { test_fault(envP, code, __FILE__, __LINE__); } while(0)
+
+;
+
+
+static __inline__ void
+test_null_string(const char * const string,
+ const char * const fileName,
+ unsigned int const lineNumber) {
+
+ ++total_tests;
+
+ if (string != NULL)
+ test_failure(fileName, lineNumber, "string not null", string);
+ else
+ printf(".");
+}
+
+
+#define TEST_NULL_STRING(string) \
+ do { test_null_string(string, __FILE__, __LINE__); } while(0)
+
+;
#define TEST_ERROR(reason) \
do { \
printf("Unable to test at %s/%u. %s", __FILE__, __LINE__, reason); \
abort(); \
} while (0)
+
+;
Modified: freeswitch/trunk/libs/xmlrpc-c/src/test/value.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/src/test/value.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/src/test/value.c Fri May 23 16:56:24 2008
@@ -5,24 +5,29 @@
#include <string.h>
#include <errno.h>
+#include "casprintf.h"
+#include "girstring.h"
+
#include "xmlrpc_config.h"
#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/string_int.h"
#include "test.h"
#include "value.h"
+#if HAVE_UNICODE_WCHAR
-/*=========================================================================
-** Test Data
-**=========================================================================
-** Some common test data which need to be allocated at a fixed address,
-** or which are inconvenient to allocate inline.
-*/
-static char* test_string_1 = "foo";
+static bool
+wcsneq(const wchar_t * const comparand,
+ const wchar_t * const comparator,
+ size_t const length) {
+ return(wcsncmp(comparand, comparator, length) == 0);
+}
+#endif /* HAVE_UNICODE_WCHAR */
static void
test_value_alloc_dealloc(void) {
@@ -45,7 +50,7 @@
static void
-test_value_integer(void) {
+test_value_int(void) {
xmlrpc_value * v;
xmlrpc_env env;
@@ -53,18 +58,28 @@
xmlrpc_env_init(&env);
+ TEST(streq(xmlrpc_type_name(XMLRPC_TYPE_INT), "INT"));
+
v = xmlrpc_int_new(&env, (xmlrpc_int32) 25);
TEST_NO_FAULT(&env);
- TEST(XMLRPC_TYPE_INT == xmlrpc_value_type(v));
+ TEST(xmlrpc_value_type(v) == XMLRPC_TYPE_INT);
xmlrpc_read_int(&env, v, &i);
TEST_NO_FAULT(&env);
TEST(i == 25);
xmlrpc_DECREF(v);
+ v = xmlrpc_int_new(&env, (xmlrpc_int32) -25);
+ TEST_NO_FAULT(&env);
+ TEST(xmlrpc_value_type(v) == XMLRPC_TYPE_INT);
+ xmlrpc_read_int(&env, v, &i);
+ TEST_NO_FAULT(&env);
+ TEST(i == -25);
+ xmlrpc_DECREF(v);
+
v = xmlrpc_build_value(&env, "i", (xmlrpc_int32) 10);
TEST_NO_FAULT(&env);
TEST(v != NULL);
- TEST(XMLRPC_TYPE_INT == xmlrpc_value_type(v));
+ TEST(xmlrpc_value_type(v) == XMLRPC_TYPE_INT);
xmlrpc_decompose_value(&env, v, "i", &i);
xmlrpc_DECREF(v);
TEST_NO_FAULT(&env);
@@ -86,6 +101,8 @@
xmlrpc_env_init(&env);
+ TEST(streq(xmlrpc_type_name(XMLRPC_TYPE_BOOL), "BOOL"));
+
v = xmlrpc_bool_new(&env, (xmlrpc_bool) 1);
TEST_NO_FAULT(&env);
TEST(XMLRPC_TYPE_BOOL == xmlrpc_value_type(v));
@@ -117,6 +134,8 @@
xmlrpc_env_init(&env);
+ TEST(streq(xmlrpc_type_name(XMLRPC_TYPE_DOUBLE), "DOUBLE"));
+
v = xmlrpc_double_new(&env, -3.25);
TEST_NO_FAULT(&env);
TEST(XMLRPC_TYPE_DOUBLE == xmlrpc_value_type(v));
@@ -140,10 +159,8 @@
static void
-test_value_datetime(void) {
-
- const char * datestring = "19980717T14:08:55";
- time_t const datetime = 900684535;
+test_value_datetime_varytime(const char * const datestring,
+ time_t const datetime) {
xmlrpc_value * v;
xmlrpc_env env;
@@ -156,11 +173,6 @@
TEST_NO_FAULT(&env);
TEST(XMLRPC_TYPE_DATETIME == xmlrpc_value_type(v));
- xmlrpc_read_datetime_str(&env, v, &ds);
- TEST_NO_FAULT(&env);
- TEST(strcmp(ds, datestring) == 0);
- strfree(ds);
-
xmlrpc_read_datetime_sec(&env, v, &dt);
TEST_NO_FAULT(&env);
TEST(dt == datetime);
@@ -173,23 +185,118 @@
xmlrpc_read_datetime_str(&env, v, &ds);
TEST_NO_FAULT(&env);
- TEST(strcmp(ds, datestring) == 0);
+ TEST(streq(ds, datestring));
strfree(ds);
+ xmlrpc_DECREF(v);
+
+ xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+test_value_datetime_not_unix(const char * const datestring) {
+
+ xmlrpc_value * v;
+ xmlrpc_env env;
+ time_t dt;
+
+ xmlrpc_env_init(&env);
+
+ v = xmlrpc_datetime_new_str(&env, datestring);
+ TEST_NO_FAULT(&env);
+
xmlrpc_read_datetime_sec(&env, v, &dt);
+ TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+
+ xmlrpc_DECREF(v);
+
+ xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+test_value_datetime_invalid(const char * const datestring) {
+
+ /* Ideally, xmlrpc_datetime_new_str() would fail on these, but
+ the code doesn't implement that today. However,
+ xmlrpc_read_datetime_sec() does catch many cases, so we
+ use that.
+
+ Note that xmlrpc_read_datetime_sec() doesn't catch them all.
+ Sometimes it just returns garbage, e.g. returns July 1 for
+ June 31.
+ */
+
+ xmlrpc_value * v;
+ xmlrpc_env env;
+ time_t dt;
+
+ xmlrpc_env_init(&env);
+
+ v = xmlrpc_datetime_new_str(&env, datestring);
+ TEST_NO_FAULT(&env);
+
+ xmlrpc_read_datetime_sec(&env, v, &dt);
+ TEST_FAULT(&env, XMLRPC_PARSE_ERROR);
+
+ xmlrpc_DECREF(v);
+
+ xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+test_build_decomp_datetime(void) {
+
+ const char * datestring = "19980717T14:08:55";
+ time_t const datetime = 900684535;
+
+ xmlrpc_env env;
+ xmlrpc_value * v;
+ time_t dt;
+ const char * ds;
+
+ xmlrpc_env_init(&env);
+
+ v = xmlrpc_build_value(&env, "t", datetime);
TEST_NO_FAULT(&env);
+ TEST(v != NULL);
+ TEST(xmlrpc_value_type(v) == XMLRPC_TYPE_DATETIME);
+
+ dt = 0;
+ xmlrpc_read_datetime_sec(&env, v, &dt);
TEST(dt == datetime);
+ dt = 0;
+ xmlrpc_decompose_value(&env, v, "t", &dt);
+ xmlrpc_DECREF(v);
+ TEST_NO_FAULT(&env);
+ TEST(dt == datetime);
+
+ v = xmlrpc_int_new(&env, 9);
+ TEST_NO_FAULT(&env);
+ xmlrpc_decompose_value(&env, v, "t", &dt);
+ TEST_FAULT(&env, XMLRPC_TYPE_ERROR);
+ xmlrpc_env_clean(&env);
+ xmlrpc_env_init(&env);
+ xmlrpc_decompose_value(&env, v, "8", &ds);
+ TEST_FAULT(&env, XMLRPC_TYPE_ERROR);
+ xmlrpc_env_clean(&env);
+ xmlrpc_env_init(&env);
xmlrpc_DECREF(v);
v = xmlrpc_build_value(&env, "8", datestring);
TEST_NO_FAULT(&env);
TEST(v != NULL);
- TEST(XMLRPC_TYPE_DATETIME == xmlrpc_value_type(v));
+ TEST(xmlrpc_value_type(v) == XMLRPC_TYPE_DATETIME);
xmlrpc_decompose_value(&env, v, "8", &ds);
xmlrpc_DECREF(v);
TEST_NO_FAULT(&env);
- TEST(strcmp(ds, datestring) == 0);
+ TEST(streq(ds, datestring));
strfree(ds);
xmlrpc_env_clean(&env);
@@ -198,38 +305,129 @@
static void
+test_value_datetime(void) {
+
+ const char * datestring = "19980717T14:08:55";
+ time_t const datetime = 900684535;
+
+ xmlrpc_env env;
+
+ xmlrpc_env_init(&env);
+
+ TEST(streq(xmlrpc_type_name(XMLRPC_TYPE_DATETIME), "DATETIME"));
+
+ /* Valid datetime, generated from XML-RPC string */
+
+ test_value_datetime_varytime(datestring, datetime);
+
+ /* Leap years */
+ test_value_datetime_varytime("20000229T23:59:59", 951868799);
+ test_value_datetime_varytime("20000301T00:00:00", 951868800);
+ test_value_datetime_varytime("20010228T23:59:59", 983404799);
+ test_value_datetime_varytime("20010301T00:00:00", 983404800);
+ test_value_datetime_varytime("20040229T23:59:59", 1078099199);
+ test_value_datetime_varytime("20040301T00:00:00", 1078099200);
+
+ /* Datetimes that can't be represented as time_t */
+ test_value_datetime_not_unix("19691231T23:59:59");
+
+ /* Invalid datetimes */
+ /* Note that the code today does a pretty weak job of validating datetimes,
+ so we test only the validation that we know is implemented.
+ */
+ test_value_datetime_invalid("19700101T25:00:00");
+ test_value_datetime_invalid("19700101T10:61:01");
+ test_value_datetime_invalid("19700101T10:59:61");
+ test_value_datetime_invalid("19700001T10:00:00");
+ test_value_datetime_invalid("19701301T10:00:00");
+ test_value_datetime_invalid("19700132T10:00:00");
+
+ test_build_decomp_datetime();
+
+ xmlrpc_env_clean(&env);
+}
+
+
+
+static xmlrpc_value *
+test_string_new_va(xmlrpc_env * const envP,
+ const char * const format,
+ ...) {
+
+ va_list args;
+
+ xmlrpc_value * v;
+
+ va_start(args, format);
+
+ v = xmlrpc_string_new_va(envP, format, args);
+
+ va_end(args);
+
+ return v;
+}
+
+
+
+static void
test_value_string_no_null(void) {
+ /* Test strings (without '\0' bytes). */
+
xmlrpc_value * v;
xmlrpc_env env;
const char * str;
size_t len;
- /* Test strings (without '\0' bytes). */
xmlrpc_env_init(&env);
- v = xmlrpc_string_new(&env, test_string_1);
+ TEST(streq(xmlrpc_type_name(XMLRPC_TYPE_STRING), "STRING"));
+
+ v = xmlrpc_string_new(&env, "foo");
TEST_NO_FAULT(&env);
- TEST(XMLRPC_TYPE_STRING == xmlrpc_value_type(v));
+ TEST(xmlrpc_value_type(v) == XMLRPC_TYPE_STRING);
xmlrpc_read_string(&env, v, &str);
TEST_NO_FAULT(&env);
- TEST(strcmp(str, test_string_1) == 0);
+ TEST(streq(str, "foo"));
xmlrpc_DECREF(v);
strfree(str);
- v = xmlrpc_build_value(&env, "s", test_string_1);
+ v = xmlrpc_string_new_f(&env, "String %s, number %d", "xyz", 7);
+ TEST_NO_FAULT(&env);
+ TEST(xmlrpc_value_type(v) == XMLRPC_TYPE_STRING);
+ xmlrpc_read_string(&env, v, &str);
+ TEST_NO_FAULT(&env);
+ TEST(streq(str, "String xyz, number 7"));
+ xmlrpc_DECREF(v);
+ strfree(str);
+
+ v = test_string_new_va(&env, "String %s, number %d", "xyz", 7);
+ TEST_NO_FAULT(&env);
+ TEST(xmlrpc_value_type(v) == XMLRPC_TYPE_STRING);
+ xmlrpc_read_string(&env, v, &str);
+ TEST_NO_FAULT(&env);
+ TEST(streq(str, "String xyz, number 7"));
+ xmlrpc_DECREF(v);
+ strfree(str);
+
+ v = xmlrpc_build_value(&env, "s", "foo");
TEST_NO_FAULT(&env);
TEST(v != NULL);
TEST(XMLRPC_TYPE_STRING == xmlrpc_value_type(v));
+
xmlrpc_decompose_value(&env, v, "s", &str);
TEST_NO_FAULT(&env);
- TEST(strcmp(str, test_string_1) == 0);
+ TEST(streq(str, "foo"));
+ strfree(str);
+
xmlrpc_decompose_value(&env, v, "s#", &str, &len);
TEST_NO_FAULT(&env);
- TEST(memcmp(str, test_string_1, strlen(test_string_1)) == 0);
- TEST(strlen(str) == strlen(test_string_1));
+ TEST(len == strlen("foo"));
+ TEST(xmlrpc_streq(str, "foo"));
+ TEST(strlen(str) == strlen("foo"));
strfree(str);
+
xmlrpc_DECREF(v);
xmlrpc_env_clean(&env);
@@ -256,7 +454,7 @@
xmlrpc_read_string_lp(&env, v, &len, &str);
TEST_NO_FAULT(&env);
TEST(len == 7);
- TEST(memcmp(str, "foo\0bar", 7) == 0);
+ TEST(memeq(str, "foo\0bar", 7));
xmlrpc_DECREF(v);
strfree(str);
@@ -267,7 +465,7 @@
xmlrpc_decompose_value(&env, v, "s#", &str, &len);
TEST_NO_FAULT(&env);
- TEST(memcmp(str, "foo\0bar", 7) == 0);
+ TEST(memeq(str, "foo\0bar", 7));
TEST(len == 7);
strfree(str);
@@ -284,7 +482,214 @@
-#ifdef HAVE_UNICODE_WCHAR
+static void
+test_value_string_multiline(void) {
+
+ xmlrpc_env env;
+ xmlrpc_value * v;
+ const char * str;
+ size_t len;
+
+ xmlrpc_env_init(&env);
+
+ /* LF line ending */
+
+ v = xmlrpc_string_new(&env, "foo\n");
+ TEST_NO_FAULT(&env);
+ xmlrpc_read_string(&env, v, &str);
+ TEST_NO_FAULT(&env);
+ TEST(streq(str, "foo\n"));
+ strfree(str);
+ xmlrpc_read_string_crlf(&env, v, &str);
+ TEST_NO_FAULT(&env);
+ TEST(streq(str, "foo\r\n"));
+ strfree(str);
+ xmlrpc_DECREF(v);
+
+ v = xmlrpc_string_new(&env, "foo\n\n");
+ TEST_NO_FAULT(&env);
+ xmlrpc_read_string(&env, v, &str);
+ TEST_NO_FAULT(&env);
+ TEST(streq(str, "foo\n\n"));
+ strfree(str);
+ xmlrpc_read_string_crlf(&env, v, &str);
+ TEST_NO_FAULT(&env);
+ TEST(streq(str, "foo\r\n\r\n"));
+ strfree(str);
+ xmlrpc_DECREF(v);
+
+ v = xmlrpc_string_new(&env, "foo\nbar");
+ TEST_NO_FAULT(&env);
+ xmlrpc_read_string(&env, v, &str);
+ TEST_NO_FAULT(&env);
+ TEST(streq(str, "foo\nbar"));
+ strfree(str);
+ xmlrpc_read_string_crlf(&env, v, &str);
+ TEST_NO_FAULT(&env);
+ TEST(streq(str, "foo\r\nbar"));
+ strfree(str);
+ xmlrpc_DECREF(v);
+
+ v = xmlrpc_string_new(&env, "foo\nbar\n");
+ TEST_NO_FAULT(&env);
+ xmlrpc_read_string(&env, v, &str);
+ TEST_NO_FAULT(&env);
+ TEST(streq(str, "foo\nbar\n"));
+ strfree(str);
+ xmlrpc_read_string_crlf(&env, v, &str);
+ TEST_NO_FAULT(&env);
+ TEST(streq(str, "foo\r\nbar\r\n"));
+ strfree(str);
+ xmlrpc_DECREF(v);
+
+ v = xmlrpc_string_new(&env, "foo\nbar\nbaz");
+ TEST_NO_FAULT(&env);
+ xmlrpc_read_string(&env, v, &str);
+ TEST_NO_FAULT(&env);
+ TEST(streq(str, "foo\nbar\nbaz"));
+ strfree(str);
+ xmlrpc_read_string_crlf(&env, v, &str);
+ TEST_NO_FAULT(&env);
+ TEST(streq(str, "foo\r\nbar\r\nbaz"));
+ strfree(str);
+ xmlrpc_DECREF(v);
+
+ /* CR line ending */
+
+ v = xmlrpc_string_new(&env, "foo\r");
+ TEST_NO_FAULT(&env);
+ xmlrpc_read_string(&env, v, &str);
+ TEST_NO_FAULT(&env);
+ TEST(streq(str, "foo\n"));
+ xmlrpc_DECREF(v);
+ strfree(str);
+
+ v = xmlrpc_string_new(&env, "foo\r\r");
+ TEST_NO_FAULT(&env);
+ xmlrpc_read_string(&env, v, &str);
+ TEST_NO_FAULT(&env);
+ TEST(streq(str, "foo\n\n"));
+ xmlrpc_DECREF(v);
+ strfree(str);
+
+ v = xmlrpc_string_new(&env, "foo\rbar");
+ TEST_NO_FAULT(&env);
+ xmlrpc_read_string(&env, v, &str);
+ TEST_NO_FAULT(&env);
+ TEST(streq(str, "foo\nbar"));
+ xmlrpc_DECREF(v);
+ strfree(str);
+
+ v = xmlrpc_string_new(&env, "foo\rbar\r");
+ TEST_NO_FAULT(&env);
+ xmlrpc_read_string(&env, v, &str);
+ TEST_NO_FAULT(&env);
+ TEST(streq(str, "foo\nbar\n"));
+ xmlrpc_DECREF(v);
+ strfree(str);
+
+ v = xmlrpc_string_new(&env, "foo\rbar\rbaz");
+ TEST_NO_FAULT(&env);
+ xmlrpc_read_string(&env, v, &str);
+ TEST_NO_FAULT(&env);
+ TEST(streq(str, "foo\nbar\nbaz"));
+ xmlrpc_DECREF(v);
+ strfree(str);
+
+ /* CRLF line ending */
+
+ v = xmlrpc_string_new(&env, "foo\r\n");
+ TEST_NO_FAULT(&env);
+ xmlrpc_read_string(&env, v, &str);
+ TEST_NO_FAULT(&env);
+ TEST(streq(str, "foo\n"));
+ xmlrpc_DECREF(v);
+ strfree(str);
+
+ v = xmlrpc_string_new(&env, "foo\r\n\r\n");
+ TEST_NO_FAULT(&env);
+ xmlrpc_read_string(&env, v, &str);
+ TEST_NO_FAULT(&env);
+ TEST(streq(str, "foo\n\n"));
+ xmlrpc_DECREF(v);
+ strfree(str);
+
+ v = xmlrpc_string_new(&env, "foo\r\nbar");
+ TEST_NO_FAULT(&env);
+ xmlrpc_read_string(&env, v, &str);
+ TEST_NO_FAULT(&env);
+ TEST(streq(str, "foo\nbar"));
+ xmlrpc_DECREF(v);
+ strfree(str);
+
+ v = xmlrpc_string_new(&env, "foo\r\nbar\r\n");
+ TEST_NO_FAULT(&env);
+ xmlrpc_read_string(&env, v, &str);
+ TEST_NO_FAULT(&env);
+ TEST(streq(str, "foo\nbar\n"));
+ xmlrpc_DECREF(v);
+ strfree(str);
+
+ v = xmlrpc_string_new(&env, "foo\r\nbar\r\nbaz");
+ TEST_NO_FAULT(&env);
+ xmlrpc_read_string(&env, v, &str);
+ TEST_NO_FAULT(&env);
+ TEST(streq(str, "foo\nbar\nbaz"));
+ xmlrpc_DECREF(v);
+ strfree(str);
+
+ /* Embedded null */
+
+ v = xmlrpc_string_new_lp(&env, 14, "foo\r\n\0bar\r\nbaz");
+ TEST_NO_FAULT(&env);
+ xmlrpc_read_string_lp(&env, v, &len, &str);
+ TEST_NO_FAULT(&env);
+ TEST(len == 12);
+ TEST(memeq(str, "foo\n\0bar\nbaz", len));
+ strfree(str);
+ xmlrpc_read_string_lp_crlf(&env, v, &len, &str);
+ TEST_NO_FAULT(&env);
+ TEST(len == 14);
+ TEST(memeq(str, "foo\r\n\0bar\r\nbaz", len));
+ strfree(str);
+ xmlrpc_DECREF(v);
+
+ xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+test_value_string_cr(void) {
+
+ xmlrpc_env env;
+ xmlrpc_value * v;
+ const char * str;
+ size_t len;
+
+ xmlrpc_env_init(&env);
+ v = xmlrpc_string_new_cr(&env, "foo\r\nbar\r\nbaz");
+ TEST_NO_FAULT(&env);
+ xmlrpc_read_string(&env, v, &str);
+ TEST_NO_FAULT(&env);
+ TEST(streq(str, "foo\r\nbar\r\nbaz"));
+ xmlrpc_DECREF(v);
+ strfree(str);
+
+ v = xmlrpc_string_new_lp_cr(&env, 7, "\0foo\rbar");
+ TEST_NO_FAULT(&env);
+ xmlrpc_read_string_lp(&env, v, &len, &str);
+ TEST_NO_FAULT(&env);
+ TEST(len == 7);
+ TEST(memeq(str, "\0foo\rbar", len));
+ xmlrpc_DECREF(v);
+ strfree(str);
+
+ xmlrpc_env_clean(&env);
+}
+
+
+#if HAVE_UNICODE_WCHAR
/* Here is a 3-character, NUL-terminated string, once in UTF-8 chars,
and once in UTF-16 wchar_ts. Note that 2 of the UTF-16 characters
@@ -316,7 +721,7 @@
TEST(wcs != NULL);
TEST(len == 3);
TEST(wcs[len] == '\0');
- TEST(0 == wcsncmp(wcs, wcs_data, len));
+ TEST(wcsneq(wcs, wcs_data, len));
free((void*)wcs);
xmlrpc_DECREF(valueP);
@@ -332,16 +737,72 @@
TEST(wcs != NULL);
TEST(len == 3);
TEST(wcs[len] == '\0');
- TEST(0 == wcsncmp(wcs, wcs_data, len));
+ TEST(wcsneq(wcs, wcs_data, len));
+ free((void*)wcs);
+
+ xmlrpc_DECREF(valueP);
+}
+#endif /* HAVE_UNICODE_WCHAR */
+
+
+static void
+test_value_string_wide_line(void) {
+ /* Test with various line delimiters */
+
+#if HAVE_UNICODE_WCHAR
+ xmlrpc_env env;
+ xmlrpc_value * valueP;
+ const wchar_t * wcs;
+ size_t len;
+
+ wchar_t const wcs_lines[] = {'\n', '\r', '\r', '\n', '\0'};
+ wchar_t const wcs_lines_lf[] = {'\n', '\n', '\n'};
+ wchar_t const wcs_lines_crlf[] = {
+ '\r', '\n', '\r', '\n', '\r', '\n' };
+
+ xmlrpc_env_init(&env);
+
+ valueP = xmlrpc_string_w_new(&env, wcs_lines);
+ TEST_NO_FAULT(&env);
+
+ xmlrpc_read_string_w_lp(&env, valueP, &len, &wcs);
+ TEST_NO_FAULT(&env);
+ TEST(len == 3);
+ TEST(wcs[len] == '\0');
+ TEST(wcsneq(wcs, wcs_lines_lf, len));
+ free((void*)wcs);
+
+ xmlrpc_read_string_w_lp_crlf(&env, valueP, &len, &wcs);
+ TEST_NO_FAULT(&env);
+ TEST(len == 6);
+ TEST(wcs[len] == '\0');
+ TEST(wcsneq(wcs, wcs_lines_crlf, len));
free((void*)wcs);
xmlrpc_DECREF(valueP);
+
+ valueP = xmlrpc_string_w_new_cr(&env, wcs_lines);
+ TEST_NO_FAULT(&env);
+
+ xmlrpc_read_string_w_lp(&env, valueP, &len, &wcs);
+ TEST_NO_FAULT(&env);
+ TEST(len == 4);
+ TEST(wcs[len] == '\0');
+ TEST(wcsneq(wcs, wcs_lines, len));
+ free((void*)wcs);
+
+ xmlrpc_DECREF(valueP);
+
+ xmlrpc_env_clean(&env);
+#endif /* HAVE_UNICODE_WCHAR */
}
static void
test_value_string_wide(void) {
+
+#if HAVE_UNICODE_WCHAR
xmlrpc_env env;
xmlrpc_value * valueP;
const wchar_t * wcs;
@@ -360,14 +821,14 @@
TEST(wcs != NULL);
TEST(len == 3);
TEST(wcs[len] == '\0');
- TEST(0 == wcsncmp(wcs, wcs_data, len));
+ TEST(wcsneq(wcs, wcs_data, len));
free((void*)wcs);
xmlrpc_read_string_w(&env, valueP, &wcs);
TEST_NO_FAULT(&env);
TEST(wcs != NULL);
TEST(wcs[3] == '\0');
- TEST(0 == wcsncmp(wcs, wcs_data, 3));
+ TEST(wcsneq(wcs, wcs_data, 3));
free((void*)wcs);
xmlrpc_decompose_value(&env, valueP, "w#", &wcs, &len);
@@ -375,7 +836,7 @@
TEST(wcs != NULL);
TEST(len == 3);
TEST(wcs[len] == '\0');
- TEST(0 == wcsncmp(wcs, wcs_data, len));
+ TEST(wcsneq(wcs, wcs_data, len));
free((void*)wcs);
{
@@ -405,7 +866,7 @@
TEST(wcs != NULL);
TEST(len == 3);
TEST(wcs[len] == '\0');
- TEST(0 == wcsncmp(wcs, wcs_data, len));
+ TEST(wcsneq(wcs, wcs_data, len));
free((void*)wcs);
xmlrpc_DECREF(valueP);
@@ -423,8 +884,9 @@
TEST(wcs != NULL);
TEST(len == 3);
TEST(wcs[len] == 0x0000);
- TEST(0 == wcsncmp(wcs, wcs_data, len));
+ TEST(wcsneq(wcs, wcs_data, len));
free((void*)wcs);
+ xmlrpc_DECREF(valueP);
/* Test with embedded NUL. We use a length of 4 so that the terminating
NUL actually becomes part of the string.
@@ -439,16 +901,19 @@
TEST(wcs != NULL);
TEST(len == 4);
TEST(wcs[len] == '\0');
- TEST(0 == wcsncmp(wcs, wcs_data, len));
+ TEST(wcsneq(wcs, wcs_data, len));
free((void*)wcs);
xmlrpc_read_string_w(&env, valueP, &wcs);
TEST_FAULT(&env, XMLRPC_TYPE_ERROR);
+
+ xmlrpc_DECREF(valueP);
+
+ test_value_string_wide_line();
+
+ xmlrpc_env_clean(&env);
+#endif /* HAVE_UNICODE_WCHAR */
}
-#else
-static void
-test_value_string_wide(void) {}
-#endif
@@ -467,12 +932,14 @@
xmlrpc_env_init(&env);
+ TEST(streq(xmlrpc_type_name(XMLRPC_TYPE_BASE64), "BASE64"));
+
v = xmlrpc_base64_new(&env, sizeof(data1), data1);
TEST_NO_FAULT(&env);
TEST(XMLRPC_TYPE_BASE64 == xmlrpc_value_type(v));
xmlrpc_read_base64(&env, v, &len, &data);
TEST_NO_FAULT(&env);
- TEST(memcmp(data, data1, sizeof(data1)) == 0);
+ TEST(memeq(data, data1, sizeof(data1)));
TEST(len == sizeof(data1));
xmlrpc_DECREF(v);
free((void*)data);
@@ -484,7 +951,7 @@
xmlrpc_DECREF(v);
TEST_NO_FAULT(&env);
TEST(len == sizeof(data2));
- TEST(memcmp(data, data1, sizeof(data2)) == 0);
+ TEST(memeq(data, data1, sizeof(data2)));
strfree(data);
xmlrpc_env_clean(&env);
@@ -530,6 +997,8 @@
xmlrpc_env_init(&env);
+ TEST(streq(xmlrpc_type_name(XMLRPC_TYPE_ARRAY), "ARRAY"));
+
v = xmlrpc_array_new(&env);
TEST_NO_FAULT(&env);
TEST(XMLRPC_TYPE_ARRAY == xmlrpc_value_type(v));
@@ -596,19 +1065,17 @@
/* Test typechecks for 'A' and 'S'. */
xmlrpc_env_init(&env);
+ xmlrpc_env_init(&env2);
v = xmlrpc_build_value(&env, "s", "foo");
TEST_NO_FAULT(&env);
- xmlrpc_env_init(&env2);
xmlrpc_decompose_value(&env2, v, "A", &v2);
TEST_FAULT(&env2, XMLRPC_TYPE_ERROR);
- xmlrpc_env_clean(&env2);
- xmlrpc_env_init(&env2);
xmlrpc_decompose_value(&env2, v, "S", &v2);
TEST_FAULT(&env2, XMLRPC_TYPE_ERROR);
- xmlrpc_env_clean(&env2);
xmlrpc_DECREF(v);
+ xmlrpc_env_clean(&env2);
xmlrpc_env_clean(&env);
}
@@ -619,7 +1086,7 @@
xmlrpc_value * arrayP;
xmlrpc_env env;
- xmlrpc_int32 i, i1, i2, i3, i4;
+ xmlrpc_int32 i, i1, i2, i3, i4, i5;
xmlrpc_value * itemP;
xmlrpc_value * subarrayP;
size_t len;
@@ -671,22 +1138,42 @@
xmlrpc_decompose_value(&env, arrayP, "(i(ii*)i)", &i1, &i2, &i3, &i4);
TEST_NO_FAULT(&env);
+ xmlrpc_decompose_value(&env, arrayP, "(i(iii)i)", &i1, &i2, &i3, &i4, &i5);
+ TEST_FAULT(&env, XMLRPC_INDEX_ERROR);
+
+ xmlrpc_decompose_value(&env, arrayP, "(i(i)i)", &i1, &i2, &i3, &i4, &i5);
+ TEST_FAULT(&env, XMLRPC_INDEX_ERROR);
+
+ xmlrpc_decompose_value(&env, arrayP, "(i(ii)i*i)",
+ &i1, &i2, &i3, &i4, &i5);
+ TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+
+ xmlrpc_decompose_value(&env, arrayP, "(i(iiQ)i*i)",
+ &i1, &i2, &i3, &i4, &i5);
+ TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+
+ xmlrpc_decompose_value(&env, arrayP, "(",
+ &i1, &i2, &i3, &i4, &i5);
+ TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+
+ xmlrpc_decompose_value(&env, arrayP, "(i",
+ &i1, &i2, &i3, &i4, &i5);
+ TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+
+ xmlrpc_decompose_value(&env, arrayP, "(i*",
+ &i1, &i2, &i3, &i4, &i5);
+ TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+
/* Test bounds check on xmlrpc_array_get_item. */
xmlrpc_array_read_item(&env, arrayP, 3, &itemP);
TEST_FAULT(&env, XMLRPC_INDEX_ERROR);
- xmlrpc_env_clean(&env);
- xmlrpc_env_init(&env);
xmlrpc_array_get_item(&env, arrayP, 3);
TEST_FAULT(&env, XMLRPC_INDEX_ERROR);
- xmlrpc_env_clean(&env);
- xmlrpc_env_init(&env);
xmlrpc_array_get_item(&env, arrayP, -1);
TEST_FAULT(&env, XMLRPC_INDEX_ERROR);
- xmlrpc_env_clean(&env);
- xmlrpc_env_init(&env);
xmlrpc_DECREF(arrayP);
@@ -732,44 +1219,14 @@
TEST_NO_FAULT(&env);
TEST(i1 == 10 && i2 == 20);
- /* Test bounds check on xmlrpc_array_get_item. */
- xmlrpc_array_read_item(&env, arrayP, 4, &itemP);
- TEST_FAULT(&env, XMLRPC_INDEX_ERROR);
- xmlrpc_env_clean(&env);
- xmlrpc_env_init(&env);
-
- xmlrpc_array_get_item(&env, arrayP, 4);
- TEST_FAULT(&env, XMLRPC_INDEX_ERROR);
- xmlrpc_env_clean(&env);
- xmlrpc_env_init(&env);
-
- xmlrpc_DECREF(arrayP);
-
- xmlrpc_env_clean(&env);
-}
-
-
-
-static void
-test_value_type_mismatch(void) {
-
- xmlrpc_value * v;
- xmlrpc_env env;
- xmlrpc_env env2;
- char * str;
-
- /* Test for one, simple kind of type mismatch error. We assume that
- ** if one of these typechecks works, the rest work fine. */
-
- xmlrpc_env_init(&env);
+ /* Test bounds check on xmlrpc_array_get_item. */
+ xmlrpc_array_read_item(&env, arrayP, 4, &itemP);
+ TEST_FAULT(&env, XMLRPC_INDEX_ERROR);
- v = xmlrpc_build_value(&env, "i", (xmlrpc_int32) 5);
- TEST_NO_FAULT(&env);
- xmlrpc_env_init(&env2);
- xmlrpc_decompose_value(&env2, v, "s", &str);
- xmlrpc_DECREF(v);
- TEST_FAULT(&env2, XMLRPC_TYPE_ERROR);
- xmlrpc_env_clean(&env2);
+ xmlrpc_array_get_item(&env, arrayP, 4);
+ TEST_FAULT(&env, XMLRPC_INDEX_ERROR);
+
+ xmlrpc_DECREF(arrayP);
xmlrpc_env_clean(&env);
}
@@ -789,6 +1246,8 @@
xmlrpc_env_init(&env);
+ TEST(streq(xmlrpc_type_name(XMLRPC_TYPE_C_PTR), "C_PTR"));
+
v = xmlrpc_build_value(&env, "p", (void*) 0x00000017);
TEST_NO_FAULT(&env);
TEST(XMLRPC_TYPE_C_PTR == xmlrpc_value_type(v));
@@ -810,6 +1269,8 @@
xmlrpc_env_init(&env);
+ TEST(streq(xmlrpc_type_name(XMLRPC_TYPE_NIL), "NIL"));
+
v = xmlrpc_nil_new(&env);
TEST_NO_FAULT(&env);
TEST(XMLRPC_TYPE_NIL == xmlrpc_value_type(v));
@@ -828,6 +1289,81 @@
static void
+test_value_i8(void) {
+
+ xmlrpc_value * v;
+ xmlrpc_env env;
+ xmlrpc_int64 i;
+
+ xmlrpc_env_init(&env);
+
+ TEST(streq(xmlrpc_type_name(XMLRPC_TYPE_I8), "I8"));
+
+ v = xmlrpc_i8_new(&env, (xmlrpc_int64) 25);
+ TEST_NO_FAULT(&env);
+ TEST(xmlrpc_value_type(v) == XMLRPC_TYPE_I8);
+ xmlrpc_read_i8(&env, v, &i);
+ TEST_NO_FAULT(&env);
+ TEST(i == 25);
+ xmlrpc_DECREF(v);
+
+ v = xmlrpc_i8_new(&env, (xmlrpc_int64) -25);
+ TEST_NO_FAULT(&env);
+ TEST(xmlrpc_value_type(v) == XMLRPC_TYPE_I8);
+ xmlrpc_read_i8(&env, v, &i);
+ TEST_NO_FAULT(&env);
+ TEST(i == -25);
+ xmlrpc_DECREF(v);
+
+ v = xmlrpc_i8_new(&env, (xmlrpc_int64)1 << 40);
+ TEST_NO_FAULT(&env);
+ TEST(xmlrpc_value_type(v) == XMLRPC_TYPE_I8);
+ xmlrpc_read_i8(&env, v, &i);
+ TEST_NO_FAULT(&env);
+ TEST(i == (xmlrpc_int64)1 << 40);
+ xmlrpc_DECREF(v);
+
+ v = xmlrpc_build_value(&env, "I", (xmlrpc_int64) 10);
+ TEST_NO_FAULT(&env);
+ TEST(v != NULL);
+ TEST(xmlrpc_value_type(v) == XMLRPC_TYPE_I8);
+ xmlrpc_decompose_value(&env, v, "I", &i);
+ xmlrpc_DECREF(v);
+ TEST_NO_FAULT(&env);
+ TEST(i == 10);
+
+ xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+test_value_type_mismatch(void) {
+
+ xmlrpc_value * v;
+ xmlrpc_env env;
+ xmlrpc_env env2;
+ char * str;
+
+ /* Test for one, simple kind of type mismatch error. We assume that
+ ** if one of these typechecks works, the rest work fine. */
+
+ xmlrpc_env_init(&env);
+ xmlrpc_env_init(&env2);
+
+ v = xmlrpc_build_value(&env, "i", (xmlrpc_int32) 5);
+ TEST_NO_FAULT(&env);
+ xmlrpc_decompose_value(&env2, v, "s", &str);
+ xmlrpc_DECREF(v);
+ TEST_FAULT(&env2, XMLRPC_TYPE_ERROR);
+
+ xmlrpc_env_clean(&env2);
+ xmlrpc_env_clean(&env);
+}
+
+
+
+static void
test_value_invalid_type(void) {
xmlrpc_value * v;
@@ -854,13 +1390,13 @@
/* Test missing close parenthesis on array */
xmlrpc_env_init(&env);
+
v = xmlrpc_build_value(&env, "(");
TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
- xmlrpc_env_clean(&env);
- xmlrpc_env_init(&env);
v = xmlrpc_build_value(&env, "(i");
TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+
xmlrpc_env_clean(&env);
}
@@ -875,18 +1411,16 @@
/* Test missing closing brace on struct */
xmlrpc_env_init(&env);
+
v = xmlrpc_build_value(&env, "{");
TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
- xmlrpc_env_clean(&env);
- xmlrpc_env_init(&env);
v = xmlrpc_build_value(&env, "{s:i", "key1", 7);
TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
- xmlrpc_env_clean(&env);
- xmlrpc_env_init(&env);
v = xmlrpc_build_value(&env, "{s:i,s:i", "key1", 9, "key2", -4);
TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+
xmlrpc_env_clean(&env);
}
@@ -897,20 +1431,24 @@
xmlrpc_value * v;
xmlrpc_env env;
+
+ /* Note that even though the format strings are invalid, we have
+ to supply the variable arguments that xmlrpc_build_value() will
+ be looking for as it tries to parse it. Otherwise, we get wild
+ memory references and consequent Valgrind flags.
+ */
xmlrpc_env_init(&env);
- v = xmlrpc_build_value(&env, "{s:ii");
+
+ v = xmlrpc_build_value(&env, "{s:ii", "key1", 9, 9);
TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
- xmlrpc_env_clean(&env);
- xmlrpc_env_init(&env);
- v = xmlrpc_build_value(&env, "{si:");
+ v = xmlrpc_build_value(&env, "{si:", "key1", 9);
TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
- xmlrpc_env_clean(&env);
- xmlrpc_env_init(&env);
- v = xmlrpc_build_value(&env, "{s");
+ v = xmlrpc_build_value(&env, "{s", "key1");
TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+
xmlrpc_env_clean(&env);
}
@@ -958,12 +1496,12 @@
TEST(i == 7);
TEST(d == 3.14);
TEST(b == (xmlrpc_bool)1);
- TEST(strcmp(dt_str, datestring) == 0);
- TEST(strcmp(s1, "hello world") == 0);
+ TEST(streq(dt_str, datestring));
+ TEST(streq(s1, "hello world"));
TEST(s2_len == 3);
- TEST(memcmp(s2, "a\0b", 3) == 0);
+ TEST(memeq(s2, "a\0b", 3));
TEST(b64_len == strlen("base64 data"));
- TEST(memcmp(b64, "base64 data", b64_len) == 0);
+ TEST(memeq(b64, "base64 data", b64_len));
TEST(XMLRPC_TYPE_ARRAY == xmlrpc_value_type(arrayP));
TEST(XMLRPC_TYPE_STRUCT == xmlrpc_value_type(structP));
TEST(cptr == &valueP);
@@ -978,21 +1516,21 @@
static void
test_struct_get_element(xmlrpc_value * const structP,
- xmlrpc_value * const i1,
- xmlrpc_value * const i2,
+ xmlrpc_value * const fooValueP,
+ xmlrpc_value * const weirdValueP,
const char * const weirdKey,
unsigned int const weirdKeyLen) {
xmlrpc_env env;
xmlrpc_value * valueP;
- xmlrpc_value * aasStringP;
+ xmlrpc_value * fooStringP;
xmlrpc_value * bogusKeyStringP;
xmlrpc_env_init(&env);
/* build test tools */
- aasStringP = xmlrpc_build_value(&env, "s", "aas");
+ fooStringP = xmlrpc_build_value(&env, "s", "foo");
TEST_NO_FAULT(&env);
bogusKeyStringP = xmlrpc_build_value(&env, "s", "doesn't_exist");
@@ -1000,78 +1538,69 @@
/* "find" interface */
- xmlrpc_struct_find_value(&env, structP, "aas", &valueP);
+ xmlrpc_struct_find_value(&env, structP, "foo", &valueP);
TEST_NO_FAULT(&env);
- TEST(valueP == i1);
+ TEST(valueP == fooValueP);
+ xmlrpc_DECREF(valueP);
xmlrpc_struct_find_value(&env, structP, "doesn't_exist", &valueP);
TEST_NO_FAULT(&env);
TEST(valueP == NULL);
- xmlrpc_struct_find_value_v(&env, structP, aasStringP, &valueP);
+ xmlrpc_struct_find_value_v(&env, structP, fooStringP, &valueP);
TEST_NO_FAULT(&env);
- TEST(valueP == i1);
+ TEST(valueP == fooValueP);
xmlrpc_DECREF(valueP);
xmlrpc_struct_find_value_v(&env, structP, bogusKeyStringP, &valueP);
TEST_NO_FAULT(&env);
TEST(valueP == NULL);
- xmlrpc_struct_find_value(&env, i1, "aas", &valueP);
+ xmlrpc_struct_find_value(&env, fooValueP, "foo", &valueP);
TEST_FAULT(&env, XMLRPC_TYPE_ERROR);
- xmlrpc_env_clean(&env);
- xmlrpc_env_init(&env);
/* "read" interface */
- xmlrpc_struct_read_value(&env, structP, "aas", &valueP);
+ xmlrpc_struct_read_value(&env, structP, "foo", &valueP);
TEST_NO_FAULT(&env);
- TEST(valueP == i1);
+ TEST(valueP == fooValueP);
xmlrpc_DECREF(valueP);
xmlrpc_struct_read_value(&env, structP, "doesn't_exist", &valueP);
TEST_FAULT(&env, XMLRPC_INDEX_ERROR);
- xmlrpc_env_clean(&env);
- xmlrpc_env_init(&env);
- xmlrpc_struct_read_value_v(&env, structP, aasStringP, &valueP);
+ xmlrpc_struct_read_value_v(&env, structP, fooStringP, &valueP);
TEST_NO_FAULT(&env);
- TEST(valueP == i1);
+ TEST(valueP == fooValueP);
xmlrpc_DECREF(valueP);
xmlrpc_struct_read_value_v(&env, structP, bogusKeyStringP, &valueP);
TEST_FAULT(&env, XMLRPC_INDEX_ERROR);
- xmlrpc_env_clean(&env);
- xmlrpc_env_init(&env);
- xmlrpc_struct_read_value(&env, i1, "aas", &valueP);
+ xmlrpc_struct_read_value(&env, fooValueP, "foo", &valueP);
TEST_FAULT(&env, XMLRPC_TYPE_ERROR);
- xmlrpc_env_clean(&env);
- xmlrpc_env_init(&env);
- /* obsolete "get" interface */
+ /* obsolete "get" interface. Note that it does not update the
+ reference count of the xmlrpc_value it returns.
+ */
- valueP = xmlrpc_struct_get_value(&env, structP, "aas");
+ valueP = xmlrpc_struct_get_value(&env, structP, "foo");
TEST_NO_FAULT(&env);
- TEST(valueP == i1);
+ TEST(valueP == fooValueP);
valueP = xmlrpc_struct_get_value(&env, structP, "doesn't_exist");
TEST_FAULT(&env, XMLRPC_INDEX_ERROR);
- xmlrpc_env_clean(&env);
- xmlrpc_env_init(&env);
- valueP = xmlrpc_struct_get_value(&env, i1, "foo");
+ valueP = xmlrpc_struct_get_value(&env, fooValueP, "foo");
TEST_FAULT(&env, XMLRPC_TYPE_ERROR);
- xmlrpc_env_clean(&env);
- xmlrpc_env_init(&env);
valueP = xmlrpc_struct_get_value_n(&env, structP, weirdKey, weirdKeyLen);
TEST_NO_FAULT(&env);
- TEST(valueP == i2);
+ TEST(valueP == weirdValueP);
/* Clean up */
- xmlrpc_DECREF(aasStringP);
+ xmlrpc_DECREF(fooStringP);
xmlrpc_DECREF(bogusKeyStringP);
xmlrpc_env_clean(&env);
@@ -1100,8 +1629,6 @@
xmlrpc_struct_read_member(&env, structP, expectedSize, &keyP, &valueP);
TEST_FAULT(&env, XMLRPC_INDEX_ERROR);
- xmlrpc_env_clean(&env);
- xmlrpc_env_init(&env);
for (index = 0; index < expectedSize; ++index) {
xmlrpc_struct_get_key_and_value(&env, structP, index, &keyP, &valueP);
@@ -1113,15 +1640,161 @@
static void
+test_struct_decompose_invalid_format_string(
+ xmlrpc_value * const testStructP) {
+
+ xmlrpc_env env;
+ xmlrpc_int32 ival;
+ xmlrpc_bool bval;
+ char * sval;
+
+ xmlrpc_env_init(&env);
+
+ /* Premature end of format string: */
+
+ xmlrpc_decompose_value(&env, testStructP, "{");
+ TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+
+ xmlrpc_decompose_value(&env, testStructP, "{s", "baz");
+ TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+
+ xmlrpc_decompose_value(&env, testStructP, "{s:", "baz");
+ TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+
+ xmlrpc_decompose_value(&env, testStructP, "{s:", "baz");
+ TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+
+ xmlrpc_decompose_value(&env, testStructP, "{s:b", "baz", &bval);
+ TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+
+ xmlrpc_decompose_value(&env, testStructP, "{s:b,", "baz", &bval);
+ TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+
+ xmlrpc_decompose_value(&env, testStructP, "{s:b,*", "baz", &bval);
+ TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+
+ /* Key not 's' */
+ xmlrpc_decompose_value(&env, testStructP, "{i:s,s:i,*}",
+ "baz", &sval,
+ "foo", &ival);
+ TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+
+ /* Missing colon */
+ xmlrpc_decompose_value(&env, testStructP, "{is,s:i,*}",
+ "baz", &sval,
+ "foo", &ival);
+ TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+
+ /* Missing comma */
+ xmlrpc_decompose_value(&env, testStructP, "{i:ss:i,*}",
+ "baz", &sval,
+ "foo", &ival);
+ TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+
+ /* Undefined format specifier */
+ xmlrpc_decompose_value(&env, testStructP, "{s:Q,*}",
+ "baz", &sval);
+ TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+
+ /* No * at end */
+ xmlrpc_decompose_value(&env, testStructP, "{s:b,s:s,s:i}",
+ "baz", &bval,
+ "foo", &sval,
+ "bar", &ival);
+ TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+
+ xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+test_struct_decompose(xmlrpc_value * const testStructP) {
+
+ xmlrpc_env env;
+
+ xmlrpc_int32 ival;
+ xmlrpc_bool bval;
+ char * sval;
+ xmlrpc_value * topStructP;
+ xmlrpc_value * value1P;
+
+ xmlrpc_env_init(&env);
+
+ /* Make a test struct */
+ topStructP = xmlrpc_build_value(&env, "{s:S,s:s}",
+ "key1", testStructP,
+ "key2", "my_string_value");
+ TEST_NO_FAULT(&env);
+
+ test_struct_decompose_invalid_format_string(testStructP);
+
+ /* Decompose a struct */
+ xmlrpc_decompose_value(&env, testStructP, "{s:b,s:s,s:i,*}",
+ "baz", &bval,
+ "foo", &sval,
+ "bar", &ival);
+ TEST_NO_FAULT(&env);
+ TEST(ival == 1);
+ TEST(!bval);
+ TEST(streq(sval, "Hello!"));
+ free(sval);
+
+ /* Decompose a deep struct */
+
+ xmlrpc_decompose_value(&env, topStructP, "{s:S,*}", "key1", &value1P);
+ TEST_NO_FAULT(&env);
+ TEST(xmlrpc_value_type(value1P) == XMLRPC_TYPE_STRUCT);
+ xmlrpc_DECREF(value1P);
+
+ xmlrpc_decompose_value(&env, topStructP, "{s:{s:b,s:s,s:i,*},*}",
+ "key1",
+ "baz", &bval,
+ "foo", &sval,
+ "bar", &ival);
+ TEST_NO_FAULT(&env);
+
+ /* First value of wrong type */
+ xmlrpc_decompose_value(&env, testStructP, "{s:b,s:i,*}",
+ "baz", &sval,
+ "foo", &ival);
+ TEST_FAULT(&env, XMLRPC_TYPE_ERROR);
+
+ /* Subsequent value of wrong type */
+ xmlrpc_decompose_value(&env, testStructP, "{s:s,s:i,*}",
+ "foo", &sval,
+ "baz", &bval);
+ TEST_FAULT(&env, XMLRPC_TYPE_ERROR);
+
+ /* Nonexistent key */
+ xmlrpc_decompose_value(&env, testStructP, "{s:b,s:i,*}",
+ "baz", &bval,
+ "nosuch", &sval);
+ TEST_FAULT(&env, XMLRPC_INDEX_ERROR);
+
+ /* Error subsequent to nested value */
+ xmlrpc_decompose_value(&env, topStructP, "{s:{s:s,*},s:i,*}",
+ "key1",
+ "foo", &sval,
+ "key2", &ival);
+ TEST_FAULT(&env, XMLRPC_TYPE_ERROR);
+
+ xmlrpc_DECREF(topStructP);
+
+ xmlrpc_env_clean(&env);
+}
+
+
+
+static void
test_struct (void) {
- xmlrpc_env env, env2;
+ xmlrpc_env env;
+ xmlrpc_value * value1P;
xmlrpc_value *s, *i, *i1, *i2, *i3, *key, *value;
size_t size;
int present;
- xmlrpc_int32 ival;
xmlrpc_bool bval;
- char *sval;
char const weirdKey[] = {'f', 'o', 'o', '\0', 'b', 'a', 'r'};
xmlrpc_env_init(&env);
@@ -1150,44 +1823,53 @@
TEST_NO_FAULT(&env);
TEST(size == 1);
- /* Insert two more items with conflicting hash codes. (We assume that
- ** nobody has changed the hash function.) */
- xmlrpc_struct_set_value(&env, s, "bar", i2);
- TEST_NO_FAULT(&env);
- xmlrpc_struct_set_value(&env, s, "aas", i3);
+ /* Insert an item whose key has the same hash value as "foo". */
+ xmlrpc_struct_set_value(&env, s, "qmdebdw", i2);
TEST_NO_FAULT(&env);
size = xmlrpc_struct_size(&env, s);
TEST_NO_FAULT(&env);
- TEST(size == 3);
+ TEST(size == 2);
+ i = xmlrpc_struct_get_value(&env, s, "foo");
+ TEST_NO_FAULT(&env);
+ TEST(i == i1);
+ i = xmlrpc_struct_get_value(&env, s, "qmdebdw");
+ TEST_NO_FAULT(&env);
+ TEST(i == i2);
/* Replace an existing element with a different element. */
- xmlrpc_struct_set_value(&env, s, "aas", i1);
+ xmlrpc_struct_set_value(&env, s, "foo", i3);
TEST_NO_FAULT(&env);
size = xmlrpc_struct_size(&env, s);
TEST_NO_FAULT(&env);
- TEST(size == 3);
+ TEST(size == 2);
+ i = xmlrpc_struct_get_value(&env, s, "foo");
+ TEST_NO_FAULT(&env);
+ TEST(i == i3);
/* Insert an item with a NUL in the key */
xmlrpc_struct_set_value_n(&env, s, weirdKey, sizeof(weirdKey), i2);
TEST_NO_FAULT(&env);
size = xmlrpc_struct_size(&env, s);
TEST_NO_FAULT(&env);
- TEST(size == 4);
+ TEST(size == 3);
- test_struct_get_element(s, i1, i2, weirdKey, sizeof(weirdKey));
+ test_struct_get_element(s, i3, i2, weirdKey, sizeof(weirdKey));
/* Replace an existing element with the same element (tricky). */
- xmlrpc_struct_set_value(&env, s, "aas", i1);
+ xmlrpc_struct_set_value(&env, s, "foo", i3);
TEST_NO_FAULT(&env);
size = xmlrpc_struct_size(&env, s);
TEST_NO_FAULT(&env);
- TEST(size == 4);
- i = xmlrpc_struct_get_value(&env, s, "aas");
+ TEST(size == 3);
+ i = xmlrpc_struct_get_value(&env, s, "foo");
TEST_NO_FAULT(&env);
- TEST(i == i1);
+ TEST(i == i3);
/* Test for the presence and absence of elements. */
- present = xmlrpc_struct_has_key(&env, s, "aas");
+ present = xmlrpc_struct_has_key(&env, s, "foo");
+ TEST_NO_FAULT(&env);
+ TEST(present);
+ present = xmlrpc_struct_has_key(&env, s, "qmdebdw");
TEST_NO_FAULT(&env);
TEST(present);
present = xmlrpc_struct_has_key(&env, s, "bogus");
@@ -1195,37 +1877,28 @@
TEST(!present);
/* Make sure our typechecks work correctly. */
- xmlrpc_env_init(&env2);
- xmlrpc_struct_size(&env2, i1);
- TEST_FAULT(&env2, XMLRPC_TYPE_ERROR);
- xmlrpc_env_clean(&env2);
+ xmlrpc_struct_size(&env, i1);
+ TEST_FAULT(&env, XMLRPC_TYPE_ERROR);
- xmlrpc_env_init(&env2);
- xmlrpc_struct_has_key(&env2, i1, "foo");
- TEST_FAULT(&env2, XMLRPC_TYPE_ERROR);
- xmlrpc_env_clean(&env2);
+ xmlrpc_struct_has_key(&env, i1, "foo");
+ TEST_FAULT(&env, XMLRPC_TYPE_ERROR);
- xmlrpc_env_init(&env2);
- xmlrpc_struct_set_value(&env2, i1, "foo", i2);
- TEST_FAULT(&env2, XMLRPC_TYPE_ERROR);
- xmlrpc_env_clean(&env2);
+ xmlrpc_struct_set_value(&env, i1, "foo", i2);
+ TEST_FAULT(&env, XMLRPC_TYPE_ERROR);
- xmlrpc_env_init(&env2);
- xmlrpc_struct_set_value_v(&env2, s, s, i2);
- TEST_FAULT(&env2, XMLRPC_TYPE_ERROR);
- xmlrpc_env_clean(&env2);
+ xmlrpc_struct_set_value_v(&env, s, s, i2);
+ TEST_FAULT(&env, XMLRPC_TYPE_ERROR);
/* Test cleanup code (w/memprof). */
xmlrpc_DECREF(s);
- /* Build a struct using our automagic struct builder. */
s = xmlrpc_build_value(&env, "{s:s,s:i,s:b}",
"foo", "Hello!",
"bar", (xmlrpc_int32) 1,
"baz", (xmlrpc_bool) 0);
TEST_NO_FAULT(&env);
TEST(s != NULL);
- TEST(XMLRPC_TYPE_STRUCT == xmlrpc_value_type(s));
+ TEST(xmlrpc_value_type(s) == XMLRPC_TYPE_STRUCT);
size = xmlrpc_struct_size(&env, s);
TEST_NO_FAULT(&env);
TEST(size == 3);
@@ -1238,60 +1911,30 @@
present = xmlrpc_struct_has_key(&env, s, "baz");
TEST_NO_FAULT(&env);
TEST(present);
- i = xmlrpc_struct_get_value(&env, s, "baz");
+ xmlrpc_struct_read_value(&env, s, "baz", &value1P);
TEST_NO_FAULT(&env);
- xmlrpc_decompose_value(&env, i, "b", &bval);
+ xmlrpc_read_bool(&env, value1P, &bval);
TEST_NO_FAULT(&env);
TEST(!bval);
+ xmlrpc_DECREF(value1P);
testStructReadout(s, 3);
- /* Test our automagic struct parser. */
- xmlrpc_decompose_value(&env, s, "{s:b,s:s,s:i,*}",
- "baz", &bval,
- "foo", &sval,
- "bar", &ival);
- TEST_NO_FAULT(&env);
- TEST(ival == 1);
- TEST(!bval);
- TEST(strcmp(sval, "Hello!") == 0);
- free(sval);
-
- /* Test automagic struct parser with value of wrong type. */
- xmlrpc_env_init(&env2);
- xmlrpc_decompose_value(&env2, s, "{s:b,s:i,*}",
- "baz", &bval,
- "foo", &sval);
- TEST_FAULT(&env2, XMLRPC_TYPE_ERROR);
- xmlrpc_env_clean(&env2);
-
- /* Test automagic struct parser with bad key. */
- xmlrpc_env_init(&env2);
- xmlrpc_decompose_value(&env2, s, "{s:b,s:i,*}",
- "baz", &bval,
- "nosuch", &sval);
- TEST_FAULT(&env2, XMLRPC_INDEX_ERROR);
- xmlrpc_env_clean(&env2);
+ test_struct_decompose(s);
/* Test type check. */
- xmlrpc_env_init(&env2);
- xmlrpc_struct_get_key_and_value(&env2, i1, 0, &key, &value);
- TEST_FAULT(&env2, XMLRPC_TYPE_ERROR);
+ xmlrpc_struct_get_key_and_value(&env, i1, 0, &key, &value);
+ TEST_FAULT(&env, XMLRPC_TYPE_ERROR);
TEST(key == NULL && value == NULL);
- xmlrpc_env_clean(&env2);
/* Test bounds checks. */
- xmlrpc_env_init(&env2);
- xmlrpc_struct_get_key_and_value(&env2, s, -1, &key, &value);
- TEST_FAULT(&env2, XMLRPC_INDEX_ERROR);
+ xmlrpc_struct_get_key_and_value(&env, s, -1, &key, &value);
+ TEST_FAULT(&env, XMLRPC_INDEX_ERROR);
TEST(key == NULL && value == NULL);
- xmlrpc_env_clean(&env2);
- xmlrpc_env_init(&env2);
- xmlrpc_struct_get_key_and_value(&env2, s, 3, &key, &value);
- TEST_FAULT(&env2, XMLRPC_INDEX_ERROR);
+ xmlrpc_struct_get_key_and_value(&env, s, 3, &key, &value);
+ TEST_FAULT(&env, XMLRPC_INDEX_ERROR);
TEST(key == NULL && value == NULL);
- xmlrpc_env_clean(&env2);
/* Test cleanup code (w/memprof). */
xmlrpc_DECREF(s);
@@ -1304,19 +1947,20 @@
-
void
test_value(void) {
printf("Running value tests.");
test_value_alloc_dealloc();
- test_value_integer();
+ test_value_int();
test_value_bool();
test_value_double();
test_value_datetime();
test_value_string_no_null();
test_value_string_null();
+ test_value_string_multiline();
+ test_value_string_cr();
test_value_string_wide();
test_value_base64();
test_value_array();
@@ -1327,6 +1971,7 @@
test_value_AS_typecheck();
test_value_cptr();
test_value_nil();
+ test_value_i8();
test_value_type_mismatch();
test_value_invalid_type();
test_value_missing_array_delim();
Modified: freeswitch/trunk/libs/xmlrpc-c/src/test/xml_data.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/src/test/xml_data.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/src/test/xml_data.c Fri May 23 16:56:24 2008
@@ -1,6 +1,6 @@
#include <stddef.h>
-#define XML_PROLOGUE "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
+#include "xml_data.h"
#define RAW_STRING_DATA \
"<value><array><data>\r\n" \
@@ -31,14 +31,6 @@
"</params>\r\n"
"</methodCall>\r\n";
-char const serialized_response[] =
- XML_PROLOGUE
- "<methodResponse>\r\n"
- "<params>\r\n"
- "<param><value><i4>30</i4></value></param>\r\n"
- "</params>\r\n"
- "</methodResponse>\r\n";
-
char const serialized_fault[] =
XML_PROLOGUE
"<methodResponse>\r\n"
@@ -56,8 +48,10 @@
char const expat_error_data[] =
XML_PROLOGUE \
"<foo><bar>abc</bar><baz></baz>\r\n";
+ /* Invalid because there's no closing </foo> */
+
-char const correct_value[] =
+char const good_response_xml[] =
XML_PROLOGUE
"<methodResponse><params><param>\r\n"
"<value><array><data>\r\n"
@@ -100,8 +94,12 @@
VALUE_HEADER"<i4>0 </i4>"VALUE_FOOTER,
VALUE_HEADER"<boolean>2</boolean>"VALUE_FOOTER,
VALUE_HEADER"<boolean>-1</boolean>"VALUE_FOOTER,
- VALUE_HEADER"<double> 0.0</double>"VALUE_FOOTER,
+ VALUE_HEADER"<double></double>"VALUE_FOOTER,
VALUE_HEADER"<double>0.0 </double>"VALUE_FOOTER,
+ VALUE_HEADER"<double>a</double>"VALUE_FOOTER,
+ VALUE_HEADER"<double>1.1.1</double>"VALUE_FOOTER,
+ VALUE_HEADER"<double>1a</double>"VALUE_FOOTER,
+ VALUE_HEADER"<double>1.1a</double>"VALUE_FOOTER,
VALUE_HEADER"<array></array>"VALUE_FOOTER,
VALUE_HEADER"<array><data></data><data></data></array>"VALUE_FOOTER,
VALUE_HEADER"<array><data></data><data></data></array>"VALUE_FOOTER,
Modified: freeswitch/trunk/libs/xmlrpc-c/src/test/xml_data.h
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/src/test/xml_data.h (original)
+++ freeswitch/trunk/libs/xmlrpc-c/src/test/xml_data.h Fri May 23 16:56:24 2008
@@ -1,15 +1,18 @@
+#ifndef XML_DATA_H_INCLUDED
+#define XML_DATA_H_INCLUDED
+
+#define XML_PROLOGUE "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
+
extern char const serialized_data[];
extern char const serialized_call[];
-extern char const serialized_response[];
-
extern char const serialized_fault[];
extern char const expat_data[];
extern char const expat_error_data[];
-extern char const correct_value[];
+extern char const good_response_xml[];
extern char const unparseable_value[];
@@ -18,3 +21,5 @@
extern const char *(bad_responses[]);
extern const char *(bad_calls[]);
+
+#endif
Added: freeswitch/trunk/libs/xmlrpc-c/src/trace.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/trace.c Fri May 23 16:56:24 2008
@@ -0,0 +1,62 @@
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+
+#include "xmlrpc-c/base_int.h"
+#include "xmlrpc-c/string_int.h"
+
+
+static size_t
+nextLineSize(const char * const string,
+ size_t const startPos,
+ size_t const stringSize) {
+/*----------------------------------------------------------------------------
+ Return the length of the line that starts at offset 'startPos' in the
+ string 'string', which is 'stringSize' characters long.
+
+ 'string' in not NUL-terminated.
+
+ A line begins at beginning of string or after a newline character and
+ runs through the next newline character or end of string. The line
+ includes the newline character at the end, if any.
+-----------------------------------------------------------------------------*/
+ size_t i;
+
+ for (i = startPos; i < stringSize && string[i] != '\n'; ++i);
+
+ if (i < stringSize)
+ ++i; /* Include the newline */
+
+ return i - startPos;
+}
+
+
+
+void
+xmlrpc_traceXml(const char * const label,
+ const char * const xml,
+ unsigned int const xmlLength) {
+
+ if (getenv("XMLRPC_TRACE_XML")) {
+ size_t cursor; /* Index into xml[] */
+
+ fprintf(stderr, "%s:\n\n", label);
+
+ for (cursor = 0; cursor < xmlLength; ) {
+ /* Print one line of XML */
+
+ size_t const lineSize = nextLineSize(xml, cursor, xmlLength);
+ const char * const xmlPrintableLine =
+ xmlrpc_makePrintable_lp(&xml[cursor], lineSize);
+
+ fprintf(stderr, "%s\n", xmlPrintableLine);
+
+ cursor += lineSize;
+
+ xmlrpc_strfree(xmlPrintableLine);
+ }
+ fprintf(stderr, "\n");
+ }
+}
+
Added: freeswitch/trunk/libs/xmlrpc-c/src/version.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/version.c Fri May 23 16:56:24 2008
@@ -0,0 +1,7 @@
+#include "version.h"
+
+#include "xmlrpc-c/base.h"
+
+unsigned int const xmlrpc_version_major = XMLRPC_VERSION_MAJOR;
+unsigned int const xmlrpc_version_minor = XMLRPC_VERSION_MINOR;
+unsigned int const xmlrpc_version_point = XMLRPC_VERSION_POINT;
Modified: freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_array.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_array.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_array.c Fri May 23 16:56:24 2008
@@ -10,10 +10,12 @@
#include <stddef.h>
#include <stdlib.h>
+#include "xmlrpc-c/util.h"
#include "xmlrpc-c/base.h"
#include "xmlrpc-c/base_int.h"
+
void
xmlrpc_abort_if_array_bad(xmlrpc_value * const arrayP) {
Modified: freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_authcookie.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_authcookie.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_authcookie.c Fri May 23 16:56:24 2008
@@ -68,7 +68,7 @@
/* Set HTTP_COOKIE_AUTH to the character representation of the
encoded string.
*/
-#ifdef HAVE_SETENV
+#if HAVE_SETENV
setenv("HTTP_COOKIE_AUTH",
XMLRPC_MEMBLOCK_CONTENTS(char, token),
1);
Added: freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_build.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_build.c Fri May 23 16:56:24 2008
@@ -0,0 +1,438 @@
+/* Copyright information is at end of file */
+
+#include "xmlrpc_config.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "bool.h"
+#include "c_util.h"
+#include "mallocvar.h"
+#include "stdargx.h"
+
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/base_int.h"
+#include "xmlrpc-c/string_int.h"
+
+
+/*=========================================================================
+** Creating XML-RPC values.
+**=========================================================================
+** Build new XML-RPC values from a format string. This code is heavily
+** inspired by Py_BuildValue from Python 1.5.2. In particular, our
+** particular abuse of the va_list data type is copied from the equivalent
+** Python code in modsupport.c. Since Python is portable, our code should
+** (in theory) also be portable.
+*/
+
+
+static void
+getString(xmlrpc_env * const envP,
+ const char ** const formatP,
+ va_listx * const argsP,
+ xmlrpc_value ** const valPP) {
+
+ const char * str;
+ unsigned int len;
+
+ str = (const char*) va_arg(argsP->v, char*);
+ if (**formatP == '#') {
+ (*formatP)++;
+ len = (size_t) va_arg(argsP->v, size_t);
+ } else
+ len = strlen(str);
+
+ *valPP = xmlrpc_string_new_lp(envP, len, str);
+}
+
+
+
+static void
+getWideString(xmlrpc_env * const envP ATTR_UNUSED,
+ const char ** const formatP ATTR_UNUSED,
+ va_listx * const argsP ATTR_UNUSED,
+ xmlrpc_value ** const valPP ATTR_UNUSED) {
+
+#if HAVE_UNICODE_WCHAR
+ wchar_t *wcs;
+ size_t len;
+
+ wcs = (wchar_t*) va_arg(argsP->v, wchar_t*);
+ if (**formatP == '#') {
+ (*formatP)++;
+ len = (size_t) va_arg(argsP->v, size_t);
+ } else
+ len = wcslen(wcs);
+
+ *valPP = xmlrpc_string_w_new_lp(envP, len, wcs);
+
+#endif /* HAVE_UNICODE_WCHAR */
+}
+
+
+
+static void
+getBase64(xmlrpc_env * const envP,
+ va_listx * const argsP,
+ xmlrpc_value ** const valPP) {
+
+ unsigned char * value;
+ size_t length;
+
+ value = (unsigned char*) va_arg(argsP->v, unsigned char*);
+ length = (size_t) va_arg(argsP->v, size_t);
+
+ *valPP = xmlrpc_base64_new(envP, length, value);
+}
+
+
+
+static void
+getValue(xmlrpc_env * const envP,
+ const char** const format,
+ va_listx * const argsP,
+ xmlrpc_value ** const valPP);
+
+
+
+static void
+getArray(xmlrpc_env * const envP,
+ const char ** const formatP,
+ char const delimiter,
+ va_listx * const argsP,
+ xmlrpc_value ** const arrayPP) {
+
+ xmlrpc_value * arrayP;
+
+ arrayP = xmlrpc_array_new(envP);
+
+ /* Add items to the array until we hit our delimiter. */
+
+ while (**formatP != delimiter && !envP->fault_occurred) {
+
+ xmlrpc_value * itemP;
+
+ if (**formatP == '\0')
+ xmlrpc_env_set_fault(
+ envP, XMLRPC_INTERNAL_ERROR,
+ "format string ended before closing ')'.");
+ else {
+ getValue(envP, formatP, argsP, &itemP);
+ if (!envP->fault_occurred) {
+ xmlrpc_array_append_item(envP, arrayP, itemP);
+ xmlrpc_DECREF(itemP);
+ }
+ }
+ }
+ if (envP->fault_occurred)
+ xmlrpc_DECREF(arrayP);
+
+ *arrayPP = arrayP;
+}
+
+
+
+static void
+getStructMember(xmlrpc_env * const envP,
+ const char ** const formatP,
+ va_listx * const argsP,
+ xmlrpc_value ** const keyPP,
+ xmlrpc_value ** const valuePP) {
+
+
+ /* Get the key */
+ getValue(envP, formatP, argsP, keyPP);
+ if (!envP->fault_occurred) {
+ if (**formatP != ':')
+ xmlrpc_env_set_fault(
+ envP, XMLRPC_INTERNAL_ERROR,
+ "format string does not have ':' after a "
+ "structure member key.");
+ else {
+ /* Skip over colon that separates key from value */
+ (*formatP)++;
+
+ /* Get the value */
+ getValue(envP, formatP, argsP, valuePP);
+ }
+ if (envP->fault_occurred)
+ xmlrpc_DECREF(*keyPP);
+ }
+}
+
+
+
+static void
+getStruct(xmlrpc_env * const envP,
+ const char ** const formatP,
+ char const delimiter,
+ va_listx * const argsP,
+ xmlrpc_value ** const structPP) {
+
+ xmlrpc_value * structP;
+
+ structP = xmlrpc_struct_new(envP);
+ if (!envP->fault_occurred) {
+ while (**formatP != delimiter && !envP->fault_occurred) {
+ xmlrpc_value * keyP;
+ xmlrpc_value * valueP;
+
+ getStructMember(envP, formatP, argsP, &keyP, &valueP);
+
+ if (!envP->fault_occurred) {
+ if (**formatP == ',')
+ (*formatP)++; /* Skip over the comma */
+ else if (**formatP == delimiter) {
+ /* End of the line */
+ } else
+ xmlrpc_env_set_fault(
+ envP, XMLRPC_INTERNAL_ERROR,
+ "format string does not have ',' or ')' after "
+ "a structure member");
+
+ if (!envP->fault_occurred)
+ /* Add the new member to the struct. */
+ xmlrpc_struct_set_value_v(envP, structP, keyP, valueP);
+
+ xmlrpc_DECREF(valueP);
+ xmlrpc_DECREF(keyP);
+ }
+ }
+ if (envP->fault_occurred)
+ xmlrpc_DECREF(structP);
+ }
+ *structPP = structP;
+}
+
+
+
+static void
+mkArrayFromVal(xmlrpc_env * const envP,
+ xmlrpc_value * const value,
+ xmlrpc_value ** const valPP) {
+
+ if (xmlrpc_value_type(value) != XMLRPC_TYPE_ARRAY)
+ xmlrpc_env_set_fault(envP, XMLRPC_INTERNAL_ERROR,
+ "Array format ('A'), non-array xmlrpc_value");
+ else
+ xmlrpc_INCREF(value);
+
+ *valPP = value;
+}
+
+
+
+static void
+mkStructFromVal(xmlrpc_env * const envP,
+ xmlrpc_value * const value,
+ xmlrpc_value ** const valPP) {
+
+ if (xmlrpc_value_type(value) != XMLRPC_TYPE_STRUCT)
+ xmlrpc_env_set_fault(envP, XMLRPC_INTERNAL_ERROR,
+ "Struct format ('S'), non-struct xmlrpc_value");
+ else
+ xmlrpc_INCREF(value);
+
+ *valPP = value;
+}
+
+
+
+static void
+getValue(xmlrpc_env * const envP,
+ const char** const formatP,
+ va_listx * const argsP,
+ xmlrpc_value ** const valPP) {
+/*----------------------------------------------------------------------------
+ Get the next value from the list. *formatP points to the specifier
+ for the next value in the format string (i.e. to the type code
+ character) and we move *formatP past the whole specifier for the
+ next value. We read the required arguments from 'argsP'. We return
+ the value as *valPP with a reference to it.
+
+ For example, if *formatP points to the "i" in the string "sis",
+ we read one argument from 'argsP' and return as *valP an integer whose
+ value is the argument we read. We advance *formatP to point to the
+ last 's' and advance 'argsP' to point to the argument that belongs to
+ that 's'.
+-----------------------------------------------------------------------------*/
+ char const formatChar = *(*formatP)++;
+
+ switch (formatChar) {
+ case 'i':
+ *valPP =
+ xmlrpc_int_new(envP, (xmlrpc_int32) va_arg(argsP->v,
+ xmlrpc_int32));
+ break;
+
+ case 'b':
+ *valPP =
+ xmlrpc_bool_new(envP, (xmlrpc_bool) va_arg(argsP->v, xmlrpc_bool));
+ break;
+
+ case 'd':
+ *valPP =
+ xmlrpc_double_new(envP, (double) va_arg(argsP->v, double));
+ break;
+
+ case 's':
+ getString(envP, formatP, argsP, valPP);
+ break;
+
+ case 'w':
+ getWideString(envP, formatP, argsP, valPP);
+ break;
+
+ case 't':
+ *valPP = xmlrpc_datetime_new_sec(envP, va_arg(argsP->v, time_t));
+ break;
+
+ case '8':
+ *valPP = xmlrpc_datetime_new_str(envP, va_arg(argsP->v, char*));
+ break;
+
+ case '6':
+ getBase64(envP, argsP, valPP);
+ break;
+
+ case 'n':
+ *valPP =
+ xmlrpc_nil_new(envP);
+ break;
+
+ case 'I':
+ *valPP =
+ xmlrpc_i8_new(envP, (xmlrpc_int64) va_arg(argsP->v, xmlrpc_int64));
+ break;
+
+ case 'p':
+ *valPP =
+ xmlrpc_cptr_new(envP, (void*) va_arg(argsP->v, void*));
+ break;
+
+ case 'A':
+ mkArrayFromVal(envP, (xmlrpc_value*) va_arg(argsP->v, xmlrpc_value*),
+ valPP);
+ break;
+
+ case 'S':
+ mkStructFromVal(envP, (xmlrpc_value*) va_arg(argsP->v, xmlrpc_value*),
+ valPP);
+ break;
+
+ case 'V':
+ *valPP = (xmlrpc_value*) va_arg(argsP->v, xmlrpc_value*);
+ xmlrpc_INCREF(*valPP);
+ break;
+
+ case '(':
+ getArray(envP, formatP, ')', argsP, valPP);
+ if (!envP->fault_occurred) {
+ XMLRPC_ASSERT(**formatP == ')');
+ (*formatP)++; /* Skip over closing parenthesis */
+ }
+ break;
+
+ case '{':
+ getStruct(envP, formatP, '}', argsP, valPP);
+ if (!envP->fault_occurred) {
+ XMLRPC_ASSERT(**formatP == '}');
+ (*formatP)++; /* Skip over closing brace */
+ }
+ break;
+
+ default: {
+ const char * const badCharacter = xmlrpc_makePrintableChar(formatChar);
+ xmlrpc_env_set_fault_formatted(
+ envP, XMLRPC_INTERNAL_ERROR,
+ "Unexpected character '%s' in format string", badCharacter);
+ xmlrpc_strfree(badCharacter);
+ }
+ }
+}
+
+
+
+void
+xmlrpc_build_value_va(xmlrpc_env * const envP,
+ const char * const format,
+ va_list const args,
+ xmlrpc_value ** const valPP,
+ const char ** const tailP) {
+
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT(format != NULL);
+
+ if (strlen(format) == 0)
+ xmlrpc_faultf(envP, "Format string is empty.");
+ else {
+ va_listx currentArgs;
+ const char * formatCursor;
+
+ init_va_listx(¤tArgs, args);
+ formatCursor = &format[0];
+ getValue(envP, &formatCursor, ¤tArgs, valPP);
+
+ if (!envP->fault_occurred)
+ XMLRPC_ASSERT_VALUE_OK(*valPP);
+
+ *tailP = formatCursor;
+ }
+}
+
+
+
+xmlrpc_value *
+xmlrpc_build_value(xmlrpc_env * const envP,
+ const char * const format,
+ ...) {
+
+ va_list args;
+ xmlrpc_value * retval;
+ const char * suffix;
+
+ va_start(args, format);
+ xmlrpc_build_value_va(envP, format, args, &retval, &suffix);
+ va_end(args);
+
+ if (!envP->fault_occurred) {
+ if (*suffix != '\0')
+ xmlrpc_env_set_fault_formatted(
+ envP, XMLRPC_INTERNAL_ERROR, "Junk after the argument "
+ "specifier: '%s'. There must be exactly one arument.",
+ suffix);
+
+ if (envP->fault_occurred)
+ xmlrpc_DECREF(retval);
+ }
+ return retval;
+}
+
+
+/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
+** Copyright (C) 2001 by Eric Kidd. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR 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. */
Modified: freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_client.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_client.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_client.c Fri May 23 16:56:24 2008
@@ -1,33 +1,11 @@
-/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
-**
-** Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions
-** are met:
-** 1. Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** 2. Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in the
-** documentation and/or other materials provided with the distribution.
-** 3. The name of the author may not be used to endorse or promote products
-** derived from this software without specific prior written permission.
-**
-** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR 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. */
+/* Copyright information is at end of file */
#include "xmlrpc_config.h"
#undef PACKAGE
#undef VERSION
+#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
@@ -37,8 +15,10 @@
#include "bool.h"
#include "mallocvar.h"
+
#include "xmlrpc-c/base.h"
#include "xmlrpc-c/base_int.h"
+#include "xmlrpc-c/string_int.h"
#include "xmlrpc-c/client.h"
#include "xmlrpc-c/client_int.h"
/* transport_config.h defines XMLRPC_DEFAULT_TRANSPORT,
@@ -46,203 +26,426 @@
MUST_BUILD_LIBWWW_CLIENT
*/
#include "transport_config.h"
-
-#if MUST_BUILD_WININET_CLIENT
-#include "xmlrpc_wininet_transport.h"
-#endif
-#if MUST_BUILD_CURL_CLIENT
-#include "xmlrpc_curl_transport.h"
-#endif
-#if MUST_BUILD_LIBWWW_CLIENT
-#include "xmlrpc_libwww_transport.h"
-#endif
+#include "version.h"
struct xmlrpc_client {
/*----------------------------------------------------------------------------
This represents a client object.
-----------------------------------------------------------------------------*/
+ bool myTransport;
+ /* The transport described below was created by this object;
+ No one else knows it exists and this object is responsible
+ for destroying it.
+ */
struct xmlrpc_client_transport * transportP;
- struct xmlrpc_client_transport_ops clientTransportOps;
+ struct xmlrpc_client_transport_ops transportOps;
+ xmlrpc_dialect dialect;
};
-typedef struct xmlrpc_call_info
-{
- /* These fields are used when performing asynchronous calls.
- ** The _asynch_data_holder contains server_url, method_name and
- ** param_array, so it's the only thing we need to free. */
- xmlrpc_value *_asynch_data_holder;
- char *server_url;
- char *method_name;
- xmlrpc_value *param_array;
- xmlrpc_response_handler callback;
- void *user_data;
+struct xmlrpc_call_info {
+ /* This is all the information needed to finish executing a started
+ RPC.
+
+ You don't need this for an RPC the user executes synchronously,
+ because then you can just use the storage in which the user passed
+ his arguments. But for asynchronous, the user will take back his
+ storage, and we need to keep this info in our own.
+ */
+
+ struct {
+ /* This are arguments to pass to the completion function. It
+ doesn't make sense to use them for anything else. In fact, it
+ really doesn't make sense for them to be arguments to the
+ completion function, but they are historically. */
+ const char * serverUrl;
+ const char * methodName;
+ xmlrpc_value * paramArrayP;
+ void * userData;
+ } completionArgs;
+ xmlrpc_response_handler completionFn;
+
/* The serialized XML data passed to this call. We keep this around
** for use by our source_anchor field. */
xmlrpc_mem_block *serialized_xml;
-} xmlrpc_call_info;
+};
+
-static bool clientInitialized = FALSE;
/*=========================================================================
-** Initialization and Shutdown
-**=========================================================================
-*/
+ Global Constant Setup/Teardown
+=========================================================================*/
-static struct xmlrpc_client client;
- /* Some day, we need to make this dynamically allocated, so there can
- be more than one client per program and just generally to provide
- a cleaner interface.
- */
+static void
+callTransportSetup(xmlrpc_env * const envP,
+ xmlrpc_transport_setup setupFn) {
-extern void
-xmlrpc_client_init(int const flags,
- const char * const appname,
- const char * const appversion) {
+ if (setupFn)
+ setupFn(envP);
+}
- struct xmlrpc_clientparms clientparms;
- /* As our interface does not allow for failure, we just fail silently ! */
-
- xmlrpc_env env;
- xmlrpc_env_init(&env);
- clientparms.transport = XMLRPC_DEFAULT_TRANSPORT;
+static void
+setupTransportGlobalConst(xmlrpc_env * const envP) {
+
+#if MUST_BUILD_WININET_CLIENT
+ if (!envP->fault_occurred)
+ callTransportSetup(envP,
+ xmlrpc_wininet_transport_ops.setup_global_const);
+#endif
+#if MUST_BUILD_CURL_CLIENT
+ if (!envP->fault_occurred)
+ callTransportSetup(envP,
+ xmlrpc_curl_transport_ops.setup_global_const);
+#endif
+#if MUST_BUILD_LIBWWW_CLIENT
+ if (!envP->fault_occurred)
+ callTransportSetup(envP,
+ xmlrpc_libwww_transport_ops.setup_global_const);
+#endif
+}
- xmlrpc_client_init2(&env, flags,
- appname, appversion,
- &clientparms, XMLRPC_CPSIZE(transport));
- xmlrpc_env_clean(&env);
+
+static void
+callTransportTeardown(xmlrpc_transport_teardown teardownFn) {
+
+ if (teardownFn)
+ teardownFn();
}
-const char *
-xmlrpc_client_get_default_transport(xmlrpc_env * const env ATTR_UNUSED) {
+static void
+teardownTransportGlobalConst(void) {
- return XMLRPC_DEFAULT_TRANSPORT;
+#if MUST_BUILD_WININET_CLIENT
+ callTransportTeardown(
+ xmlrpc_wininet_transport_ops.teardown_global_const);
+#endif
+#if MUST_BUILD_CURL_CLIENT
+ callTransportTeardown(
+ xmlrpc_curl_transport_ops.teardown_global_const);
+#endif
+#if MUST_BUILD_LIBWWW_CLIENT
+ callTransportTeardown(
+ xmlrpc_libwww_transport_ops.teardown_global_const);
+#endif
}
+/*=========================================================================
+ Global stuff (except the global client)
+=========================================================================*/
+
+static unsigned int constSetupCount = 0;
+
+
+void
+xmlrpc_client_setup_global_const(xmlrpc_env * const envP) {
+/*----------------------------------------------------------------------------
+ Set up pseudo-constant global variables (they'd be constant, except that
+ the library loader doesn't set them. An explicit call from the loaded
+ program does).
+
+ This function is not thread-safe. The user is supposed to call it
+ (perhaps cascaded down from a multitude of higher level libraries)
+ as part of early program setup, when the program is only one thread.
+-----------------------------------------------------------------------------*/
+ if (constSetupCount == 0)
+ setupTransportGlobalConst(envP);
+
+ ++constSetupCount;
+}
+
+
+
+void
+xmlrpc_client_teardown_global_const(void) {
+/*----------------------------------------------------------------------------
+ Complement to xmlrpc_client_setup_global_const().
+
+ This function is not thread-safe. The user is supposed to call it
+ (perhaps cascaded down from a multitude of higher level libraries)
+ as part of final program cleanup, when the program is only one thread.
+-----------------------------------------------------------------------------*/
+ assert(constSetupCount > 0);
+
+ --constSetupCount;
+
+ if (constSetupCount == 0)
+ teardownTransportGlobalConst();
+}
+
+
+
+unsigned int const xmlrpc_client_version_major = XMLRPC_VERSION_MAJOR;
+unsigned int const xmlrpc_client_version_minor = XMLRPC_VERSION_MINOR;
+unsigned int const xmlrpc_client_version_point = XMLRPC_VERSION_POINT;
+
+
+/*=========================================================================
+ Client Create/Destroy
+=========================================================================*/
+
static void
-setupTransport(xmlrpc_env * const envP,
- const char * const transportName) {
+getTransportOps(
+ xmlrpc_env * const envP,
+ const char * const transportName,
+ const struct xmlrpc_client_transport_ops ** const opsPP) {
- if (FALSE) {
+ if (false) {
}
#if MUST_BUILD_WININET_CLIENT
else if (strcmp(transportName, "wininet") == 0)
- client.clientTransportOps = xmlrpc_wininet_transport_ops;
+ *opsPP = &xmlrpc_wininet_transport_ops;
#endif
#if MUST_BUILD_CURL_CLIENT
else if (strcmp(transportName, "curl") == 0)
- client.clientTransportOps = xmlrpc_curl_transport_ops;
+ *opsPP = &xmlrpc_curl_transport_ops;
#endif
#if MUST_BUILD_LIBWWW_CLIENT
else if (strcmp(transportName, "libwww") == 0)
- client.clientTransportOps = xmlrpc_libwww_transport_ops;
+ *opsPP = &xmlrpc_libwww_transport_ops;
#endif
else
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR,
- "Unrecognized XML transport name '%s'", transportName);
+ xmlrpc_faultf(envP, "Unrecognized XML transport name '%s'",
+ transportName);
}
+struct xportParms {
+ const void * parmsP;
+ size_t size;
+};
+
+
+
static void
getTransportParmsFromClientParms(
xmlrpc_env * const envP,
const struct xmlrpc_clientparms * const clientparmsP,
- unsigned int const parm_size,
- const struct xmlrpc_xportparms ** const transportparmsPP,
- size_t * const transportparm_sizeP) {
+ unsigned int const parmSize,
+ struct xportParms * const xportParmsP) {
- if (parm_size < XMLRPC_CPSIZE(transportparmsP) ||
+ if (parmSize < XMLRPC_CPSIZE(transportparmsP) ||
clientparmsP->transportparmsP == NULL) {
- *transportparmsPP = NULL;
- *transportparm_sizeP = 0;
+ xportParmsP->parmsP = NULL;
+ xportParmsP->size = 0;
} else {
- *transportparmsPP = clientparmsP->transportparmsP;
- if (parm_size < XMLRPC_CPSIZE(transportparm_size))
+ xportParmsP->parmsP = clientparmsP->transportparmsP;
+ if (parmSize < XMLRPC_CPSIZE(transportparm_size))
xmlrpc_faultf(envP, "Your 'clientparms' argument contains the "
"transportparmsP member, "
"but no transportparms_size member");
else
- *transportparm_sizeP = clientparmsP->transportparm_size;
+ xportParmsP->size = clientparmsP->transportparm_size;
}
}
static void
-getTransportInfo(xmlrpc_env * const envP,
- const struct xmlrpc_clientparms * const clientparmsP,
- unsigned int const parm_size,
- const char ** const transportNameP,
- const struct xmlrpc_xportparms ** const transportparmsPP,
- size_t * const transportparm_sizeP) {
-
- getTransportParmsFromClientParms(
- envP, clientparmsP, parm_size,
- transportparmsPP, transportparm_sizeP);
+getTransportInfo(
+ xmlrpc_env * const envP,
+ const struct xmlrpc_clientparms * const clientparmsP,
+ unsigned int const parmSize,
+ const char ** const transportNameP,
+ struct xportParms * const transportParmsP,
+ const struct xmlrpc_client_transport_ops ** const transportOpsPP,
+ xmlrpc_client_transport ** const transportPP) {
+
+ const char * transportNameParm;
+ xmlrpc_client_transport * transportP;
+ const struct xmlrpc_client_transport_ops * transportOpsP;
+
+ if (parmSize < XMLRPC_CPSIZE(transport))
+ transportNameParm = NULL;
+ else
+ transportNameParm = clientparmsP->transport;
- if (!envP->fault_occurred) {
- if (parm_size < XMLRPC_CPSIZE(transport) ||
- clientparmsP->transport == NULL) {
+ if (parmSize < XMLRPC_CPSIZE(transportP))
+ transportP = NULL;
+ else
+ transportP = clientparmsP->transportP;
- /* He didn't specify a transport. Use the default */
+ if (parmSize < XMLRPC_CPSIZE(transportOpsP))
+ transportOpsP = NULL;
+ else
+ transportOpsP = clientparmsP->transportOpsP;
- *transportNameP = xmlrpc_client_get_default_transport(envP);
- if (*transportparmsPP)
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR,
+ if ((transportOpsP && !transportP) || (transportP && ! transportOpsP))
+ xmlrpc_faultf(envP, "'transportOpsP' and 'transportP' go together. "
+ "You must specify both or neither");
+ else if (transportNameParm && transportP)
+ xmlrpc_faultf(envP, "You cannot specify both 'transport' and "
+ "'transportP' transport parameters.");
+ else if (transportP)
+ *transportNameP = NULL;
+ else if (transportNameParm)
+ *transportNameP = transportNameParm;
+ else
+ *transportNameP = xmlrpc_client_get_default_transport(envP);
+
+ *transportOpsPP = transportOpsP;
+ *transportPP = transportP;
+
+ if (!envP->fault_occurred) {
+ getTransportParmsFromClientParms(
+ envP, clientparmsP, parmSize, transportParmsP);
+
+ if (!envP->fault_occurred) {
+ if (transportParmsP->parmsP && !transportNameParm)
+ xmlrpc_faultf(
+ envP,
"You specified transport parameters, but did not "
- "specify a transport type. Parameters are specific to "
- "a particular type.");
- } else
- *transportNameP = clientparmsP->transport;
+ "specify a transport type. Parameters are specific "
+ "to a particular type.");
+ }
}
}
-void
-xmlrpc_client_init2(xmlrpc_env * const envP,
- int const flags,
- const char * const appname,
- const char * const appversion,
- const struct xmlrpc_clientparms * const clientparmsP,
- unsigned int const parm_size) {
+static void
+getDialectFromClientParms(
+ const struct xmlrpc_clientparms * const clientparmsP,
+ unsigned int const parmSize,
+ xmlrpc_dialect * const dialectP) {
+
+ if (parmSize < XMLRPC_CPSIZE(dialect))
+ *dialectP = xmlrpc_dialect_i8;
+ else
+ *dialectP = clientparmsP->dialect;
+}
+
- if (clientInitialized)
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR,
- "Xmlrpc-c client instance has already been initialized "
- "(need to call xmlrpc_client_cleanup() before you can "
- "reinitialize).");
- else {
- const char * transportName;
- const struct xmlrpc_xportparms * transportparmsP;
- size_t transportparm_size;
- getTransportInfo(envP, clientparmsP, parm_size, &transportName,
- &transportparmsP, &transportparm_size);
+static void
+clientCreate(
+ xmlrpc_env * const envP,
+ bool const myTransport,
+ const struct xmlrpc_client_transport_ops * const transportOpsP,
+ struct xmlrpc_client_transport * const transportP,
+ xmlrpc_dialect const dialect,
+ xmlrpc_client ** const clientPP) {
+
+ XMLRPC_ASSERT_PTR_OK(transportOpsP);
+ XMLRPC_ASSERT_PTR_OK(transportP);
+ XMLRPC_ASSERT_PTR_OK(clientPP);
+
+ if (constSetupCount == 0) {
+ xmlrpc_faultf(envP,
+ "You have not called "
+ "xmlrpc_client_setup_global_const().");
+ /* Impl note: We can't just call it now because it isn't
+ thread-safe.
+ */
+ } else {
+ xmlrpc_client * clientP;
+
+ MALLOCVAR(clientP);
+ if (clientP == NULL)
+ xmlrpc_faultf(envP, "Unable to allocate memory for "
+ "client descriptor.");
+ else {
+ clientP->myTransport = myTransport;
+ clientP->transportOps = *transportOpsP;
+ clientP->transportP = transportP;
+ clientP->dialect = dialect;
+
+ *clientPP = clientP;
+ }
+ }
+}
+
+
+
+static void
+createTransportAndClient(
+ xmlrpc_env * const envP,
+ const char * const transportName,
+ const void * const transportparmsP,
+ size_t const transportparmSize,
+ int const flags,
+ const char * const appname,
+ const char * const appversion,
+ xmlrpc_dialect const dialect,
+ xmlrpc_client ** const clientPP) {
+
+ const struct xmlrpc_client_transport_ops * transportOpsP;
+
+ getTransportOps(envP, transportName, &transportOpsP);
+ if (!envP->fault_occurred) {
+ xmlrpc_client_transport * transportP;
+
+ /* The following call is not thread-safe */
+ transportOpsP->create(
+ envP, flags, appname, appversion,
+ transportparmsP, transportparmSize,
+ &transportP);
if (!envP->fault_occurred) {
- setupTransport(envP, transportName);
- if (!envP->fault_occurred) {
- client.clientTransportOps.create(
- envP, flags, appname, appversion,
- transportparmsP, transportparm_size,
- &client.transportP);
- if (!envP->fault_occurred)
- clientInitialized = TRUE;
+ bool const myTransportTrue = true;
+
+ clientCreate(envP, myTransportTrue, transportOpsP, transportP,
+ dialect, clientPP);
+
+ if (envP->fault_occurred)
+ transportOpsP->destroy(transportP);
+ }
+ }
+}
+
+
+
+void
+xmlrpc_client_create(xmlrpc_env * const envP,
+ int const flags,
+ const char * const appname,
+ const char * const appversion,
+ const struct xmlrpc_clientparms * const clientparmsP,
+ unsigned int const parmSize,
+ xmlrpc_client ** const clientPP) {
+
+ XMLRPC_ASSERT_PTR_OK(clientPP);
+
+ if (constSetupCount == 0) {
+ xmlrpc_faultf(envP,
+ "You have not called "
+ "xmlrpc_client_setup_global_const().");
+ /* Impl note: We can't just call it now because it isn't
+ thread-safe.
+ */
+ } else {
+ const char * transportName;
+ struct xportParms transportparms;
+ const struct xmlrpc_client_transport_ops * transportOpsP;
+ xmlrpc_client_transport * transportP;
+ xmlrpc_dialect dialect;
+
+ getTransportInfo(envP, clientparmsP, parmSize, &transportName,
+ &transportparms, &transportOpsP, &transportP);
+
+ getDialectFromClientParms(clientparmsP, parmSize, &dialect);
+
+ if (!envP->fault_occurred) {
+ if (transportName)
+ createTransportAndClient(envP, transportName,
+ transportparms.parmsP,
+ transportparms.size,
+ flags, appname, appversion, dialect,
+ clientPP);
+ else {
+ bool myTransportFalse = false;
+ clientCreate(envP, myTransportFalse,
+ transportOpsP, transportP, dialect, clientPP);
}
}
}
@@ -251,36 +454,41 @@
void
-xmlrpc_client_cleanup() {
+xmlrpc_client_destroy(xmlrpc_client * const clientP) {
- XMLRPC_ASSERT(clientInitialized);
+ XMLRPC_ASSERT_PTR_OK(clientP);
- client.clientTransportOps.destroy(client.transportP);
-
- clientInitialized = FALSE;
+ if (clientP->myTransport)
+ clientP->transportOps.destroy(clientP->transportP);
+
+ free(clientP);
}
+/*=========================================================================
+ Call/Response Utilities
+=========================================================================*/
+
static void
makeCallXml(xmlrpc_env * const envP,
const char * const methodName,
xmlrpc_value * const paramArrayP,
+ xmlrpc_dialect const dialect,
xmlrpc_mem_block ** const callXmlPP) {
XMLRPC_ASSERT_VALUE_OK(paramArrayP);
XMLRPC_ASSERT_PTR_OK(callXmlPP);
if (methodName == NULL)
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR,
- "method name argument is NULL pointer");
+ xmlrpc_faultf(envP, "method name argument is NULL pointer");
else {
xmlrpc_mem_block * callXmlP;
callXmlP = XMLRPC_MEMBLOCK_NEW(char, envP, 0);
if (!envP->fault_occurred) {
- xmlrpc_serialize_call(envP, callXmlP, methodName, paramArrayP);
+ xmlrpc_serialize_call2(envP, callXmlP, methodName, paramArrayP,
+ dialect);
*callXmlPP = callXmlP;
@@ -292,49 +500,75 @@
+/*=========================================================================
+ Synchronous Call
+=========================================================================*/
+
void
-xmlrpc_client_transport_call(
+xmlrpc_client_transport_call2(
xmlrpc_env * const envP,
- void * const reserved ATTR_UNUSED,
- /* for client handle */
+ xmlrpc_client * const clientP,
const xmlrpc_server_info * const serverP,
xmlrpc_mem_block * const callXmlP,
xmlrpc_mem_block ** const respXmlPP) {
- if (!clientInitialized)
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR,
- "Xmlrpc-c client instance has not been initialized "
- "(need to call xmlrpc_client_init2()).");
- else {
- struct xmlrpc_client * const clientP = &client;
- /* Some day, the library will be re-entrant and this will be
- passed in.
- */
-
- XMLRPC_ASSERT_PTR_OK(serverP);
- XMLRPC_ASSERT_PTR_OK(callXmlP);
- XMLRPC_ASSERT_PTR_OK(respXmlPP);
-
- clientP->clientTransportOps.call(
- envP, clientP->transportP, serverP, callXmlP,
- respXmlPP);
- }
+ XMLRPC_ASSERT_PTR_OK(clientP);
+ XMLRPC_ASSERT_PTR_OK(serverP);
+ XMLRPC_ASSERT_PTR_OK(callXmlP);
+ XMLRPC_ASSERT_PTR_OK(respXmlPP);
+
+ clientP->transportOps.call(
+ envP, clientP->transportP, serverP, callXmlP,
+ respXmlPP);
}
-
+
static void
-clientCallServerParams(xmlrpc_env * const envP,
- struct xmlrpc_client * const clientP,
- const xmlrpc_server_info * const serverP,
- const char * const methodName,
- xmlrpc_value * const paramArrayP,
- xmlrpc_value ** const resultPP) {
+parseResponse(xmlrpc_env * const envP,
+ xmlrpc_mem_block * const respXmlP,
+ xmlrpc_value ** const resultPP,
+ int * const faultCodeP,
+ const char ** const faultStringP) {
+
+ xmlrpc_env respEnv;
+
+ xmlrpc_env_init(&respEnv);
+
+ xmlrpc_parse_response2(
+ &respEnv,
+ XMLRPC_MEMBLOCK_CONTENTS(char, respXmlP),
+ XMLRPC_MEMBLOCK_SIZE(char, respXmlP),
+ resultPP, faultCodeP, faultStringP);
+
+ if (respEnv.fault_occurred)
+ xmlrpc_env_set_fault_formatted(
+ envP, respEnv.fault_code,
+ "Unable to make sense of XML-RPC response from server. "
+ "%s. Use XMLRPC_TRACE_XML to see for yourself",
+ respEnv.fault_string);
+
+ xmlrpc_env_clean(&respEnv);
+}
+
+
+
+void
+xmlrpc_client_call2(xmlrpc_env * const envP,
+ struct xmlrpc_client * const clientP,
+ const xmlrpc_server_info * const serverInfoP,
+ const char * const methodName,
+ xmlrpc_value * const paramArrayP,
+ xmlrpc_value ** const resultPP) {
xmlrpc_mem_block * callXmlP;
- makeCallXml(envP, methodName, paramArrayP, &callXmlP);
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT_PTR_OK(clientP);
+ XMLRPC_ASSERT_PTR_OK(serverInfoP);
+ XMLRPC_ASSERT_PTR_OK(paramArrayP);
+
+ makeCallXml(envP, methodName, paramArrayP, clientP->dialect, &callXmlP);
if (!envP->fault_occurred) {
xmlrpc_mem_block * respXmlP;
@@ -343,17 +577,27 @@
XMLRPC_MEMBLOCK_CONTENTS(char, callXmlP),
XMLRPC_MEMBLOCK_SIZE(char, callXmlP));
- clientP->clientTransportOps.call(
- envP, clientP->transportP, serverP, callXmlP, &respXmlP);
+ clientP->transportOps.call(
+ envP, clientP->transportP, serverInfoP, callXmlP, &respXmlP);
if (!envP->fault_occurred) {
+ int faultCode;
+ const char * faultString;
+
xmlrpc_traceXml("XML-RPC RESPONSE",
XMLRPC_MEMBLOCK_CONTENTS(char, respXmlP),
XMLRPC_MEMBLOCK_SIZE(char, respXmlP));
- *resultPP = xmlrpc_parse_response(
- envP,
- XMLRPC_MEMBLOCK_CONTENTS(char, respXmlP),
- XMLRPC_MEMBLOCK_SIZE(char, respXmlP));
+ parseResponse(envP, respXmlP, resultPP, &faultCode, &faultString);
+
+ if (!envP->fault_occurred) {
+ if (faultString) {
+ xmlrpc_env_set_fault_formatted(
+ envP, faultCode,
+ "RPC failed at server. %s", faultString);
+ xmlrpc_strfree(faultString);
+ } else
+ XMLRPC_ASSERT_VALUE_OK(*resultPP);
+ }
XMLRPC_MEMBLOCK_FREE(char, respXmlP);
}
XMLRPC_MEMBLOCK_FREE(char, callXmlP);
@@ -362,425 +606,142 @@
-xmlrpc_value *
-xmlrpc_client_call_params(xmlrpc_env * const envP,
- const char * const serverUrl,
- const char * const methodName,
- xmlrpc_value * const paramArrayP) {
-
- xmlrpc_value *retval;
-
- XMLRPC_ASSERT_ENV_OK(envP);
- XMLRPC_ASSERT_PTR_OK(serverUrl);
-
- if (!clientInitialized)
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR,
- "Xmlrpc-c client instance has not been initialized "
- "(need to call xmlrpc_client_init2()).");
- else {
- struct xmlrpc_client * const clientP = &client;
- /* Some day, the library will be re-entrant and this will be
- passed in.
- */
-
- xmlrpc_server_info * serverP;
-
- /* Build a server info object and make our call. */
- serverP = xmlrpc_server_info_new(envP, serverUrl);
- if (!envP->fault_occurred) {
- clientCallServerParams(envP, clientP, serverP,
- methodName, paramArrayP,
- &retval);
-
- xmlrpc_server_info_free(serverP);
- }
- }
-
- if (!envP->fault_occurred)
- XMLRPC_ASSERT_VALUE_OK(retval);
-
- return retval;
-}
-
-
-
-xmlrpc_value *
-xmlrpc_client_call_server_params(
- xmlrpc_env * const envP,
- const xmlrpc_server_info * const serverP,
- const char * const methodName,
- xmlrpc_value * const paramArrayP) {
-
- xmlrpc_value *retval;
-
- XMLRPC_ASSERT_ENV_OK(envP);
- XMLRPC_ASSERT_PTR_OK(serverP);
-
- if (!clientInitialized)
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR,
- "Xmlrpc-c client instance has not been initialized "
- "(need to call xmlrpc_client_init2()).");
- else {
- struct xmlrpc_client * const clientP = &client;
- /* Some day, the library will be re-entrant and this will be
- passed in.
- */
-
- clientCallServerParams(envP, clientP, serverP, methodName, paramArrayP,
- &retval);
- }
- if (!envP->fault_occurred)
- XMLRPC_ASSERT_VALUE_OK(retval);
-
- return retval;
-}
-
-
-
-static xmlrpc_value *
-xmlrpc_client_call_va(xmlrpc_env * const envP,
- const char * const server_url,
- const char * const methodName,
- const char * const format,
- va_list args) {
+static void
+clientCall2f_va(xmlrpc_env * const envP,
+ xmlrpc_client * const clientP,
+ const char * const serverUrl,
+ const char * const methodName,
+ const char * const format,
+ xmlrpc_value ** const resultPP,
+ va_list args) {
xmlrpc_value * argP;
- xmlrpc_value * retval;
xmlrpc_env argenv;
const char * suffix;
XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT_PTR_OK(serverUrl);
+ XMLRPC_ASSERT_PTR_OK(methodName);
XMLRPC_ASSERT_PTR_OK(format);
+ XMLRPC_ASSERT_PTR_OK(resultPP);
/* Build our argument value. */
xmlrpc_env_init(&argenv);
xmlrpc_build_value_va(&argenv, format, args, &argP, &suffix);
- if (argenv.fault_occurred) {
+ if (argenv.fault_occurred)
xmlrpc_env_set_fault_formatted(
envP, argenv.fault_code, "Invalid RPC arguments. "
"The format argument must indicate a single array, and the "
"following arguments must correspond to that format argument. "
"The failure is: %s",
argenv.fault_string);
- retval = NULL; /* just to quiet compiler warning */
- } else {
+ else {
XMLRPC_ASSERT_VALUE_OK(argP);
- if (*suffix != '\0') {
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR, "Junk after the argument "
- "specifier: '%s'. There must be exactly one arument.",
- suffix);
- retval = NULL; /* just to quiet compiler warning */
- } else {
- /* Perform the actual XML-RPC call. */
- retval = xmlrpc_client_call_params(
- envP, server_url, methodName, argP);
- if (!envP->fault_occurred)
- XMLRPC_ASSERT_VALUE_OK(retval);
+ if (*suffix != '\0')
+ xmlrpc_faultf(envP, "Junk after the argument specifier: '%s'. "
+ "There must be exactly one argument.",
+ suffix);
+ else {
+ xmlrpc_server_info * serverInfoP;
+
+ serverInfoP = xmlrpc_server_info_new(envP, serverUrl);
+
+ if (!envP->fault_occurred) {
+ /* Perform the actual XML-RPC call. */
+ xmlrpc_client_call2(envP, clientP,
+ serverInfoP, methodName, argP, resultPP);
+ if (!envP->fault_occurred)
+ XMLRPC_ASSERT_VALUE_OK(*resultPP);
+ xmlrpc_server_info_free(serverInfoP);
+ }
}
xmlrpc_DECREF(argP);
}
xmlrpc_env_clean(&argenv);
- return retval;
}
-xmlrpc_value *
-xmlrpc_client_call(xmlrpc_env * const envP,
- const char * const serverUrl,
- const char * const methodName,
- const char * const format,
- ...) {
+void
+xmlrpc_client_call2f(xmlrpc_env * const envP,
+ xmlrpc_client * const clientP,
+ const char * const serverUrl,
+ const char * const methodName,
+ xmlrpc_value ** const resultPP,
+ const char * const format,
+ ...) {
- xmlrpc_value * result;
va_list args;
va_start(args, format);
- result = xmlrpc_client_call_va(envP, serverUrl,
- methodName, format, args);
+ clientCall2f_va(envP, clientP, serverUrl,
+ methodName, format, resultPP, args);
va_end(args);
-
- return result;
}
-xmlrpc_value *
-xmlrpc_client_call_server(xmlrpc_env * const envP,
- const xmlrpc_server_info * const serverP,
- const char * const methodName,
- const char * const format,
- ...) {
-
- va_list args;
- xmlrpc_value * paramArrayP;
- xmlrpc_value * retval;
- const char * suffix;
-
- XMLRPC_ASSERT_ENV_OK(envP);
- XMLRPC_ASSERT_PTR_OK(format);
+/*=========================================================================
+ Asynchronous Call
+=========================================================================*/
- if (!clientInitialized)
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR,
- "Xmlrpc-c client instance has not been initialized "
- "(need to call xmlrpc_client_init2()).");
+static void
+callInfoSetCompletion(xmlrpc_env * const envP,
+ struct xmlrpc_call_info * const callInfoP,
+ const char * const serverUrl,
+ const char * const methodName,
+ xmlrpc_value * const paramArrayP,
+ xmlrpc_response_handler completionFn,
+ void * const userData) {
+
+ callInfoP->completionFn = completionFn;
+ callInfoP->completionArgs.userData = userData;
+ callInfoP->completionArgs.serverUrl = strdup(serverUrl);
+ if (callInfoP->completionArgs.serverUrl == NULL)
+ xmlrpc_faultf(envP, "Couldn't get memory to store server URL");
else {
- struct xmlrpc_client * const clientP = &client;
- /* Some day, the library will be re-entrant and this will be
- passed in.
- */
-
- /* Build our argument */
- va_start(args, format);
- xmlrpc_build_value_va(envP, format, args, ¶mArrayP, &suffix);
- va_end(args);
-
- if (!envP->fault_occurred) {
- if (*suffix != '\0')
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR, "Junk after the argument "
- "specifier: '%s'. There must be exactly one arument.",
- suffix);
- else
- clientCallServerParams(envP, clientP, serverP,
- methodName, paramArrayP,
- &retval);
-
- xmlrpc_DECREF(paramArrayP);
+ callInfoP->completionArgs.methodName = strdup(methodName);
+ if (callInfoP->completionArgs.methodName == NULL)
+ xmlrpc_faultf(envP, "Couldn't get memory to store method name");
+ else {
+ callInfoP->completionArgs.paramArrayP = paramArrayP;
+ xmlrpc_INCREF(paramArrayP);
}
+ if (envP->fault_occurred)
+ xmlrpc_strfree(callInfoP->completionArgs.serverUrl);
}
- return retval;
-}
-
-
-void
-xmlrpc_client_event_loop_finish_asynch(void) {
- XMLRPC_ASSERT(clientInitialized);
- client.clientTransportOps.finish_asynch(
- client.transportP, timeout_no, 0);
-}
-
-
-
-void
-xmlrpc_client_event_loop_finish_asynch_timeout(xmlrpc_timeout const timeout) {
- XMLRPC_ASSERT(clientInitialized);
- client.clientTransportOps.finish_asynch(
- client.transportP, timeout_yes, timeout);
-}
-
-
-
-static void
-call_info_set_asynch_data(xmlrpc_env * const env,
- xmlrpc_call_info * const info,
- const char * const server_url,
- const char * const method_name,
- xmlrpc_value * const argP,
- xmlrpc_response_handler callback,
- void * const user_data) {
-
- xmlrpc_value *holder;
-
- /* Error-handling preconditions. */
- holder = NULL;
-
- XMLRPC_ASSERT_ENV_OK(env);
- XMLRPC_ASSERT_PTR_OK(info);
- XMLRPC_ASSERT(info->_asynch_data_holder == NULL);
- XMLRPC_ASSERT_PTR_OK(server_url);
- XMLRPC_ASSERT_PTR_OK(method_name);
- XMLRPC_ASSERT_VALUE_OK(argP);
-
- /* Install our callback and user_data.
- ** (We're not responsible for destroying the user_data.) */
- info->callback = callback;
- info->user_data = user_data;
-
- /* Build an XML-RPC data structure to hold our other data. This makes
- ** copies of server_url and method_name, and increments the reference
- ** to the argument *argP. */
- holder = xmlrpc_build_value(env, "(ssV)",
- server_url, method_name, argP);
- XMLRPC_FAIL_IF_FAULT(env);
-
- /* Parse the newly-allocated structure into our public member variables.
- ** This doesn't make any new references, so we can dispose of the whole
- ** thing by DECREF'ing the one master reference. Nifty, huh? */
- xmlrpc_parse_value(env, holder, "(ssV)",
- &info->server_url,
- &info->method_name,
- &info->param_array);
- XMLRPC_FAIL_IF_FAULT(env);
-
- /* Hand over ownership of the holder to the call_info struct. */
- info->_asynch_data_holder = holder;
- holder = NULL;
-
- cleanup:
- if (env->fault_occurred) {
- if (holder)
- xmlrpc_DECREF(holder);
- }
-}
-
-/*=========================================================================
-** xmlrpc_server_info
-**=========================================================================
-*/
-
-xmlrpc_server_info *
-xmlrpc_server_info_new (xmlrpc_env * const env,
- const char * const server_url) {
-
- xmlrpc_server_info *server;
- char *url_copy;
-
- /* Error-handling preconditions. */
- server = NULL;
- url_copy = NULL;
-
- XMLRPC_ASSERT_ENV_OK(env);
- XMLRPC_ASSERT_PTR_OK(server_url);
-
- /* Allocate our memory blocks. */
- server = (xmlrpc_server_info*) malloc(sizeof(xmlrpc_server_info));
- XMLRPC_FAIL_IF_NULL(server, env, XMLRPC_INTERNAL_ERROR,
- "Couldn't allocate memory for xmlrpc_server_info");
- memset(server, 0, sizeof(xmlrpc_server_info));
- url_copy = (char*) malloc(strlen(server_url) + 1);
- XMLRPC_FAIL_IF_NULL(url_copy, env, XMLRPC_INTERNAL_ERROR,
- "Couldn't allocate memory for server URL");
-
- /* Build our object. */
- strcpy(url_copy, server_url);
- server->_server_url = url_copy;
- server->_http_basic_auth = NULL;
-
- cleanup:
- if (env->fault_occurred) {
- if (url_copy)
- free(url_copy);
- if (server)
- free(server);
- return NULL;
- }
- return server;
-}
-
-xmlrpc_server_info * xmlrpc_server_info_copy(xmlrpc_env *env,
- xmlrpc_server_info *aserver)
-{
- xmlrpc_server_info *server;
- char *url_copy, *auth_copy;
-
- XMLRPC_ASSERT_ENV_OK(env);
- XMLRPC_ASSERT_PTR_OK(aserver);
-
- /* Error-handling preconditions. */
- server = NULL;
- url_copy = NULL;
- auth_copy = NULL;
-
- /* Allocate our memory blocks. */
- server = (xmlrpc_server_info*) malloc(sizeof(xmlrpc_server_info));
- XMLRPC_FAIL_IF_NULL(server, env, XMLRPC_INTERNAL_ERROR,
- "Couldn't allocate memory for xmlrpc_server_info");
- url_copy = (char*) malloc(strlen(aserver->_server_url) + 1);
- XMLRPC_FAIL_IF_NULL(url_copy, env, XMLRPC_INTERNAL_ERROR,
- "Couldn't allocate memory for server URL");
- auth_copy = (char*) malloc(strlen(aserver->_http_basic_auth) + 1);
- XMLRPC_FAIL_IF_NULL(auth_copy, env, XMLRPC_INTERNAL_ERROR,
- "Couldn't allocate memory for authentication info");
-
- /* Build our object. */
- strcpy(url_copy, aserver->_server_url);
- server->_server_url = url_copy;
- strcpy(auth_copy, aserver->_http_basic_auth);
- server->_http_basic_auth = auth_copy;
-
- cleanup:
- if (env->fault_occurred) {
- if (url_copy)
- free(url_copy);
- if (auth_copy)
- free(auth_copy);
- if (server)
- free(server);
- return NULL;
- }
- return server;
-
-}
-
-void xmlrpc_server_info_free (xmlrpc_server_info *server)
-{
- XMLRPC_ASSERT_PTR_OK(server);
- XMLRPC_ASSERT(server->_server_url != XMLRPC_BAD_POINTER);
-
- if (server->_http_basic_auth)
- free(server->_http_basic_auth);
- free(server->_server_url);
- server->_server_url = XMLRPC_BAD_POINTER;
- free(server);
-}
-
-/*=========================================================================
-** xmlrpc_client_call_asynch
-**=========================================================================
-*/
-
-static void
-call_info_free(xmlrpc_call_info * const callInfoP) {
-
- /* Assume the worst.. That only parts of the call_info are valid. */
-
- XMLRPC_ASSERT_PTR_OK(callInfoP);
-
- /* If this has been allocated, we're responsible for destroying it. */
- if (callInfoP->_asynch_data_holder)
- xmlrpc_DECREF(callInfoP->_asynch_data_holder);
-
- /* Now we can blow away the XML data. */
- if (callInfoP->serialized_xml)
- xmlrpc_mem_block_free(callInfoP->serialized_xml);
-
- free(callInfoP);
}
static void
-call_info_new(xmlrpc_env * const envP,
- const char * const methodName,
- xmlrpc_value * const paramArrayP,
- xmlrpc_call_info ** const callInfoPP) {
+callInfoCreate(xmlrpc_env * const envP,
+ const char * const methodName,
+ xmlrpc_value * const paramArrayP,
+ xmlrpc_dialect const dialect,
+ const char * const serverUrl,
+ xmlrpc_response_handler completionFn,
+ void * const userData,
+ struct xmlrpc_call_info ** const callInfoPP) {
/*----------------------------------------------------------------------------
Create a call_info object. A call_info object represents an XML-RPC
call.
-----------------------------------------------------------------------------*/
struct xmlrpc_call_info * callInfoP;
- XMLRPC_ASSERT_PTR_OK(paramArrayP);
+ XMLRPC_ASSERT_PTR_OK(serverUrl);
+ XMLRPC_ASSERT_PTR_OK(methodName);
+ XMLRPC_ASSERT_VALUE_OK(paramArrayP);
XMLRPC_ASSERT_PTR_OK(callInfoPP);
MALLOCVAR(callInfoP);
if (callInfoP == NULL)
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR,
- "Couldn't allocate memory for xmlrpc_call_info");
+ xmlrpc_faultf(envP, "Couldn't allocate memory for xmlrpc_call_info");
else {
xmlrpc_mem_block * callXmlP;
- /* Clear contents. */
- memset(callInfoP, 0, sizeof(*callInfoP));
-
- makeCallXml(envP, methodName, paramArrayP, &callXmlP);
+ makeCallXml(envP, methodName, paramArrayP, dialect, &callXmlP);
if (!envP->fault_occurred) {
xmlrpc_traceXml("XML-RPC CALL",
@@ -791,6 +752,9 @@
*callInfoPP = callInfoP;
+ callInfoSetCompletion(envP, callInfoP, serverUrl, methodName,
+ paramArrayP, completionFn, userData);
+
if (envP->fault_occurred)
free(callInfoP);
}
@@ -799,145 +763,43 @@
-void
-xmlrpc_client_call_asynch(const char * const serverUrl,
- const char * const methodName,
- xmlrpc_response_handler callback,
- void * const userData,
- const char * const format,
- ...) {
-
- xmlrpc_env env;
- va_list args;
- xmlrpc_value * paramArrayP;
- const char * suffix;
-
- xmlrpc_env_init(&env);
+static void
+callInfoDestroy(struct xmlrpc_call_info * const callInfoP) {
- XMLRPC_ASSERT_PTR_OK(serverUrl);
- XMLRPC_ASSERT_PTR_OK(format);
+ XMLRPC_ASSERT_PTR_OK(callInfoP);
- /* Build our argument array. */
- va_start(args, format);
- xmlrpc_build_value_va(&env, format, args, ¶mArrayP, &suffix);
- va_end(args);
- if (env.fault_occurred) {
- /* Unfortunately, we have no way to return an error and the
- regular callback for a failed RPC is designed to have the
- parameter array passed to it. This was probably an oversight
- of the original asynch design, but now we have to be as
- backward compatible as possible, so we do this:
- */
- (*callback)(serverUrl, methodName, NULL, userData, &env, NULL);
- } else {
- if (*suffix != '\0')
- xmlrpc_env_set_fault_formatted(
- &env, XMLRPC_INTERNAL_ERROR, "Junk after the argument "
- "specifier: '%s'. There must be exactly one arument.",
- suffix);
- else {
- xmlrpc_server_info * serverP;
- serverP = xmlrpc_server_info_new(&env, serverUrl);
- if (!env.fault_occurred) {
- xmlrpc_client_call_server_asynch_params(
- serverP, methodName, callback, userData,
- paramArrayP);
- }
- xmlrpc_server_info_free(serverP);
- }
- if (env.fault_occurred)
- (*callback)(serverUrl, methodName, paramArrayP, userData,
- &env, NULL);
- xmlrpc_DECREF(paramArrayP);
+ if (callInfoP->completionFn) {
+ xmlrpc_DECREF(callInfoP->completionArgs.paramArrayP);
+ xmlrpc_strfree(callInfoP->completionArgs.methodName);
+ xmlrpc_strfree(callInfoP->completionArgs.serverUrl);
}
+ if (callInfoP->serialized_xml)
+ xmlrpc_mem_block_free(callInfoP->serialized_xml);
- xmlrpc_env_clean(&env);
+ free(callInfoP);
}
-void
-xmlrpc_client_call_asynch_params(const char * const serverUrl,
- const char * const methodName,
- xmlrpc_response_handler callback,
- void * const userData,
- xmlrpc_value * const paramArrayP) {
-
- xmlrpc_env env;
- xmlrpc_server_info *serverP;
-
- xmlrpc_env_init(&env);
-
- XMLRPC_ASSERT_PTR_OK(serverUrl);
-
- serverP = xmlrpc_server_info_new(&env, serverUrl);
- if (!env.fault_occurred) {
- xmlrpc_client_call_server_asynch_params(
- serverP, methodName, callback, userData, paramArrayP);
-
- xmlrpc_server_info_free(serverP);
- }
+void
+xmlrpc_client_event_loop_finish(xmlrpc_client * const clientP) {
- if (env.fault_occurred)
- /* We have no way to return failure; we report the failure
- as it happened after we successfully started the RPC.
- */
- (*callback)(serverUrl, methodName, paramArrayP, userData,
- &env, NULL);
+ XMLRPC_ASSERT_PTR_OK(clientP);
- xmlrpc_env_clean(&env);
+ clientP->transportOps.finish_asynch(
+ clientP->transportP, timeout_no, 0);
}
void
-xmlrpc_client_call_server_asynch(xmlrpc_server_info * const serverP,
- const char * const methodName,
- xmlrpc_response_handler callback,
- void * const userData,
- const char * const format,
- ...) {
+xmlrpc_client_event_loop_finish_timeout(xmlrpc_client * const clientP,
+ xmlrpc_timeout const timeout) {
- xmlrpc_env env;
- va_list args;
- xmlrpc_value * paramArrayP;
- const char * suffix;
+ XMLRPC_ASSERT_PTR_OK(clientP);
- xmlrpc_env_init(&env);
-
- XMLRPC_ASSERT_PTR_OK(format);
-
- /* Build our parameter array. */
- va_start(args, format);
- xmlrpc_build_value_va(&env, format, args, ¶mArrayP, &suffix);
- va_end(args);
- if (env.fault_occurred) {
- /* Unfortunately, we have no way to return an error and the
- regular callback for a failed RPC is designed to have the
- parameter array passed to it. This was probably an oversight
- of the original asynch design, but now we have to be as
- backward compatible as possible, so we do this:
- */
- (*callback)(serverP->_server_url, methodName, NULL, userData,
- &env, NULL);
- } else {
- if (*suffix != '\0')
- xmlrpc_env_set_fault_formatted(
- &env, XMLRPC_INTERNAL_ERROR, "Junk after the argument "
- "specifier: '%s'. There must be exactly one arument.",
- suffix);
- else {
- xmlrpc_client_call_server_asynch_params(
- serverP, methodName, callback, userData, paramArrayP);
- }
- xmlrpc_DECREF(paramArrayP);
- }
-
- if (env.fault_occurred)
- (*callback)(serverP->_server_url, methodName, paramArrayP, userData,
- &env, NULL);
-
- xmlrpc_env_clean(&env);
+ clientP->transportOps.finish_asynch(
+ clientP->transportP, timeout_yes, timeout);
}
@@ -959,190 +821,178 @@
failed the request.
-----------------------------------------------------------------------------*/
xmlrpc_env env;
- xmlrpc_value * responseP;
+ xmlrpc_value * resultP;
xmlrpc_env_init(&env);
+ resultP = NULL; /* Just to quiet compiler warning */
+
if (transportEnv.fault_occurred)
xmlrpc_env_set_fault_formatted(
&env, transportEnv.fault_code,
"Client transport failed to execute the RPC. %s",
transportEnv.fault_string);
- if (!env.fault_occurred)
- responseP = xmlrpc_parse_response(
- &env,
- XMLRPC_MEMBLOCK_CONTENTS(char, responseXmlP),
- XMLRPC_MEMBLOCK_SIZE(char, responseXmlP));
- else
- responseP = NULL;
- /* just to quiet compiler warning; value undefined when env
- indicates an error.
- */
+ if (!env.fault_occurred) {
+ int faultCode;
+ const char * faultString;
- /* Call the user's callback function with the result */
- (*callInfoP->callback)(callInfoP->server_url,
- callInfoP->method_name,
- callInfoP->param_array,
- callInfoP->user_data, &env, responseP);
+ xmlrpc_parse_response2(&env,
+ XMLRPC_MEMBLOCK_CONTENTS(char, responseXmlP),
+ XMLRPC_MEMBLOCK_SIZE(char, responseXmlP),
+ &resultP, &faultCode, &faultString);
+
+ if (!env.fault_occurred) {
+ if (faultString) {
+ xmlrpc_env_set_fault_formatted(
+ &env, faultCode,
+ "RPC failed at server. %s", faultString);
+ xmlrpc_strfree(faultString);
+ }
+ }
+ }
+ /* Call the user's completion function with the RPC result */
+ (*callInfoP->completionFn)(callInfoP->completionArgs.serverUrl,
+ callInfoP->completionArgs.methodName,
+ callInfoP->completionArgs.paramArrayP,
+ callInfoP->completionArgs.userData,
+ &env, resultP);
if (!env.fault_occurred)
- xmlrpc_DECREF(responseP);
+ xmlrpc_DECREF(resultP);
- call_info_free(callInfoP);
+ callInfoDestroy(callInfoP);
xmlrpc_env_clean(&env);
}
-static void
-sendRequest(xmlrpc_env * const envP,
- struct xmlrpc_client * const clientP,
- xmlrpc_server_info * const serverP,
- const char * const methodName,
- xmlrpc_response_handler responseHandler,
- void * const userData,
- xmlrpc_value * const argP) {
+void
+xmlrpc_client_start_rpc(xmlrpc_env * const envP,
+ struct xmlrpc_client * const clientP,
+ xmlrpc_server_info * const serverInfoP,
+ const char * const methodName,
+ xmlrpc_value * const argP,
+ xmlrpc_response_handler completionFn,
+ void * const userData) {
+
+ struct xmlrpc_call_info * callInfoP;
- xmlrpc_call_info * callInfoP;
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT_PTR_OK(clientP);
+ XMLRPC_ASSERT_PTR_OK(serverInfoP);
+ XMLRPC_ASSERT_PTR_OK(methodName);
+ XMLRPC_ASSERT_VALUE_OK(argP);
- call_info_new(envP, methodName, argP, &callInfoP);
- if (!envP->fault_occurred) {
- call_info_set_asynch_data(envP, callInfoP,
- serverP->_server_url, methodName,
- argP, responseHandler, userData);
- if (!envP->fault_occurred)
- clientP->clientTransportOps.send_request(
- envP, clientP->transportP, serverP, callInfoP->serialized_xml,
- &asynchComplete, callInfoP);
+ callInfoCreate(envP, methodName, argP, clientP->dialect,
+ serverInfoP->serverUrl, completionFn, userData,
+ &callInfoP);
- if (envP->fault_occurred)
- call_info_free(callInfoP);
- else {
- /* asynchComplete() will free *callInfoP */
- }
- }
- if (envP->fault_occurred) {
- /* Transport did not start the call. Report the call complete
- (with error) now.
- */
- (*responseHandler)(serverP->_server_url, methodName, argP, userData,
- envP, NULL);
- } else {
- /* The transport will call *responseHandler() when it has completed
- the call
- */
+ if (!envP->fault_occurred)
+ clientP->transportOps.send_request(
+ envP, clientP->transportP, serverInfoP,
+ callInfoP->serialized_xml,
+ &asynchComplete, callInfoP);
+
+ if (envP->fault_occurred)
+ callInfoDestroy(callInfoP);
+ else {
+ /* asynchComplete() will destroy *callInfoP */
}
}
void
-xmlrpc_client_call_server_asynch_params(
- xmlrpc_server_info * const serverP,
- const char * const methodName,
- xmlrpc_response_handler responseHandler,
- void * const userData,
- xmlrpc_value * const argP) {
- xmlrpc_env env;
+xmlrpc_client_start_rpcf(xmlrpc_env * const envP,
+ xmlrpc_client * const clientP,
+ const char * const serverUrl,
+ const char * const methodName,
+ xmlrpc_response_handler responseHandler,
+ void * const userData,
+ const char * const format,
+ ...) {
- xmlrpc_env_init(&env);
+ va_list args;
+ xmlrpc_value * paramArrayP;
+ const char * suffix;
- XMLRPC_ASSERT_PTR_OK(serverP);
- XMLRPC_ASSERT_PTR_OK(methodName);
- XMLRPC_ASSERT_PTR_OK(responseHandler);
- XMLRPC_ASSERT_VALUE_OK(argP);
+ XMLRPC_ASSERT_PTR_OK(serverUrl);
+ XMLRPC_ASSERT_PTR_OK(format);
- if (!clientInitialized)
- xmlrpc_env_set_fault_formatted(
- &env, XMLRPC_INTERNAL_ERROR,
- "Xmlrpc-c client instance has not been initialized "
- "(need to call xmlrpc_client_init2()).");
- else {
- struct xmlrpc_client * const clientP = &client;
- /* Some day, the library will be re-entrant and this will be
- passed in.
- */
-
- sendRequest(&env, clientP, serverP,
- methodName, responseHandler, userData,
- argP);
+ /* Build our argument array. */
+ va_start(args, format);
+ xmlrpc_build_value_va(envP, format, args, ¶mArrayP, &suffix);
+ va_end(args);
+ if (!envP->fault_occurred) {
+ if (*suffix != '\0')
+ xmlrpc_faultf(envP, "Junk after the argument "
+ "specifier: '%s'. "
+ "There must be exactly one arument.",
+ suffix);
+ else {
+ xmlrpc_server_info * serverInfoP;
+ serverInfoP = xmlrpc_server_info_new(envP, serverUrl);
+ if (!envP->fault_occurred) {
+ xmlrpc_client_start_rpc(
+ envP, clientP,
+ serverInfoP, methodName, paramArrayP,
+ responseHandler, userData);
+ }
+ xmlrpc_server_info_free(serverInfoP);
+ }
+ xmlrpc_DECREF(paramArrayP);
}
- xmlrpc_env_clean(&env);
}
-void
-xmlrpc_server_info_set_basic_auth(xmlrpc_env * const envP,
- xmlrpc_server_info * const serverP,
- const char * const username,
- const char * const password) {
-
- size_t username_len, password_len, raw_token_len;
- char *raw_token;
- xmlrpc_mem_block *token;
- char *token_data, *auth_type, *auth_header;
- size_t token_len, auth_type_len, auth_header_len;
-
- /* Error-handling preconditions. */
- raw_token = NULL;
- token = NULL;
- token_data = auth_type = auth_header = NULL;
+/*=========================================================================
+ Miscellaneous
+=========================================================================*/
- XMLRPC_ASSERT_ENV_OK(envP);
- XMLRPC_ASSERT_PTR_OK(serverP);
- XMLRPC_ASSERT_PTR_OK(username);
- XMLRPC_ASSERT_PTR_OK(password);
+const char *
+xmlrpc_client_get_default_transport(xmlrpc_env * const envP ATTR_UNUSED) {
- /* Calculate some lengths. */
- username_len = strlen(username);
- password_len = strlen(password);
- raw_token_len = username_len + password_len + 1;
-
- /* Build a raw token of the form 'username:password'. */
- raw_token = (char*) malloc(raw_token_len + 1);
- XMLRPC_FAIL_IF_NULL(raw_token, envP, XMLRPC_INTERNAL_ERROR,
- "Couldn't allocate memory for auth token");
- strcpy(raw_token, username);
- raw_token[username_len] = ':';
- strcpy(&raw_token[username_len + 1], password);
-
- /* Encode our raw token using Base64. */
- token = xmlrpc_base64_encode_without_newlines(envP,
- (unsigned char*) raw_token,
- raw_token_len);
- XMLRPC_FAIL_IF_FAULT(envP);
- token_data = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, token);
- token_len = XMLRPC_TYPED_MEM_BLOCK_SIZE(char, token);
-
- /* Build our actual header value. (I hate string processing in C.) */
- auth_type = "Basic ";
- auth_type_len = strlen(auth_type);
- auth_header_len = auth_type_len + token_len;
- auth_header = (char*) malloc(auth_header_len + 1);
- XMLRPC_FAIL_IF_NULL(auth_header, envP, XMLRPC_INTERNAL_ERROR,
- "Couldn't allocate memory for auth header");
- memcpy(auth_header, auth_type, auth_type_len);
- memcpy(&auth_header[auth_type_len], token_data, token_len);
- auth_header[auth_header_len] = '\0';
-
- /* Clean up any pre-existing authentication information, and install
- ** the new value. */
- if (serverP->_http_basic_auth)
- free(serverP->_http_basic_auth);
- serverP->_http_basic_auth = auth_header;
-
- cleanup:
- if (raw_token)
- free(raw_token);
- if (token)
- xmlrpc_mem_block_free(token);
- if (envP->fault_occurred) {
- if (auth_header)
- free(auth_header);
- }
+ return XMLRPC_DEFAULT_TRANSPORT;
}
+
+
+void
+xmlrpc_client_set_interrupt(xmlrpc_client * const clientP,
+ int * const interruptP) {
+
+ if (clientP->transportOps.set_interrupt)
+ clientP->transportOps.set_interrupt(clientP->transportP, interruptP);
+}
+
+
+
+/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR 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.
+*/
Added: freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_client_global.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_client_global.c Fri May 23 16:56:24 2008
@@ -0,0 +1,414 @@
+#include <stdarg.h>
+
+#include "xmlrpc_config.h"
+
+#include "bool.h"
+
+#include <xmlrpc-c/base.h>
+#include <xmlrpc-c/client.h>
+#include <xmlrpc-c/client_int.h>
+#include <xmlrpc-c/client_global.h>
+
+/*=========================================================================
+ Global Client
+=========================================================================*/
+
+static struct xmlrpc_client * globalClientP;
+static bool globalClientExists = false;
+
+
+void
+xmlrpc_client_init2(xmlrpc_env * const envP,
+ int const flags,
+ const char * const appname,
+ const char * const appversion,
+ const struct xmlrpc_clientparms * const clientparmsP,
+ unsigned int const parmSize) {
+/*----------------------------------------------------------------------------
+ This function is not thread-safe.
+-----------------------------------------------------------------------------*/
+ if (globalClientExists)
+ xmlrpc_faultf(
+ envP,
+ "Xmlrpc-c global client instance has already been created "
+ "(need to call xmlrpc_client_cleanup() before you can "
+ "reinitialize).");
+ else {
+ /* The following call is not thread-safe */
+ xmlrpc_client_setup_global_const(envP);
+ if (!envP->fault_occurred) {
+ xmlrpc_client_create(envP, flags, appname, appversion,
+ clientparmsP, parmSize, &globalClientP);
+ if (!envP->fault_occurred)
+ globalClientExists = true;
+
+ if (envP->fault_occurred)
+ xmlrpc_client_teardown_global_const();
+ }
+ }
+}
+
+
+
+void
+xmlrpc_client_init(int const flags,
+ const char * const appname,
+ const char * const appversion) {
+/*----------------------------------------------------------------------------
+ This function is not thread-safe.
+-----------------------------------------------------------------------------*/
+ struct xmlrpc_clientparms clientparms;
+
+ /* As our interface does not allow for failure, we just fail silently ! */
+
+ xmlrpc_env env;
+ xmlrpc_env_init(&env);
+
+ clientparms.transport = NULL;
+
+ /* The following call is not thread-safe */
+ xmlrpc_client_init2(&env, flags,
+ appname, appversion,
+ &clientparms, XMLRPC_CPSIZE(transport));
+
+ xmlrpc_env_clean(&env);
+}
+
+
+
+void
+xmlrpc_client_cleanup() {
+/*----------------------------------------------------------------------------
+ This function is not thread-safe
+-----------------------------------------------------------------------------*/
+ XMLRPC_ASSERT(globalClientExists);
+
+ xmlrpc_client_destroy(globalClientP);
+
+ globalClientExists = false;
+
+ /* The following call is not thread-safe */
+ xmlrpc_client_teardown_global_const();
+}
+
+
+
+static void
+validateGlobalClientExists(xmlrpc_env * const envP) {
+
+ if (!globalClientExists)
+ xmlrpc_faultf(envP,
+ "Xmlrpc-c global client instance "
+ "has not been created "
+ "(need to call xmlrpc_client_init2()).");
+}
+
+
+
+void
+xmlrpc_client_transport_call(
+ xmlrpc_env * const envP,
+ void * const reserved ATTR_UNUSED,
+ /* for client handle */
+ const xmlrpc_server_info * const serverP,
+ xmlrpc_mem_block * const callXmlP,
+ xmlrpc_mem_block ** const respXmlPP) {
+
+ validateGlobalClientExists(envP);
+ if (!envP->fault_occurred)
+ xmlrpc_client_transport_call2(envP, globalClientP, serverP,
+ callXmlP, respXmlPP);
+}
+
+
+
+static void
+clientCall_va(xmlrpc_env * const envP,
+ const xmlrpc_server_info * const serverInfoP,
+ const char * const methodName,
+ const char * const format,
+ va_list args,
+ xmlrpc_value ** const resultPP) {
+
+ validateGlobalClientExists(envP);
+ if (!envP->fault_occurred) {
+ xmlrpc_value * paramArrayP;
+ const char * suffix;
+
+ xmlrpc_build_value_va(envP, format, args, ¶mArrayP, &suffix);
+
+ if (!envP->fault_occurred) {
+ if (*suffix != '\0')
+ xmlrpc_faultf(envP, "Junk after the argument "
+ "specifier: '%s'. "
+ "There must be exactly one arument.",
+ suffix);
+ else
+ xmlrpc_client_call2(envP, globalClientP, serverInfoP,
+ methodName, paramArrayP, resultPP);
+
+ xmlrpc_DECREF(paramArrayP);
+ }
+ }
+}
+
+
+
+xmlrpc_value *
+xmlrpc_client_call(xmlrpc_env * const envP,
+ const char * const serverUrl,
+ const char * const methodName,
+ const char * const format,
+ ...) {
+
+ xmlrpc_value * resultP;
+
+ xmlrpc_server_info * serverInfoP;
+
+ serverInfoP = xmlrpc_server_info_new(envP, serverUrl);
+
+ if (!envP->fault_occurred) {
+ va_list args;
+ va_start(args, format);
+
+ clientCall_va(envP, serverInfoP, methodName, format, args, &resultP);
+
+ va_end(args);
+ xmlrpc_server_info_free(serverInfoP);
+ }
+
+ return resultP;
+}
+
+
+
+xmlrpc_value *
+xmlrpc_client_call_server(xmlrpc_env * const envP,
+ const xmlrpc_server_info * const serverP,
+ const char * const methodName,
+ const char * const format,
+ ...) {
+
+ va_list args;
+ xmlrpc_value * resultP;
+
+ va_start(args, format);
+ clientCall_va(envP, serverP, methodName, format, args, &resultP);
+ va_end(args);
+
+ return resultP;
+}
+
+
+
+xmlrpc_value *
+xmlrpc_client_call_server_params(
+ xmlrpc_env * const envP,
+ const xmlrpc_server_info * const serverInfoP,
+ const char * const methodName,
+ xmlrpc_value * const paramArrayP) {
+
+ xmlrpc_value * resultP;
+
+ validateGlobalClientExists(envP);
+
+ if (!envP->fault_occurred)
+ xmlrpc_client_call2(envP, globalClientP,
+ serverInfoP, methodName, paramArrayP,
+ &resultP);
+
+ return resultP;
+}
+
+
+
+xmlrpc_value *
+xmlrpc_client_call_params(xmlrpc_env * const envP,
+ const char * const serverUrl,
+ const char * const methodName,
+ xmlrpc_value * const paramArrayP) {
+
+ xmlrpc_value * resultP;
+
+ validateGlobalClientExists(envP);
+
+ if (!envP->fault_occurred) {
+ xmlrpc_server_info * serverInfoP;
+
+ serverInfoP = xmlrpc_server_info_new(envP, serverUrl);
+
+ if (!envP->fault_occurred) {
+ xmlrpc_client_call2(envP, globalClientP,
+ serverInfoP, methodName, paramArrayP,
+ &resultP);
+
+ xmlrpc_server_info_free(serverInfoP);
+ }
+ }
+ return resultP;
+}
+
+
+
+void
+xmlrpc_client_call_server_asynch_params(
+ xmlrpc_server_info * const serverInfoP,
+ const char * const methodName,
+ xmlrpc_response_handler responseHandler,
+ void * const userData,
+ xmlrpc_value * const paramArrayP) {
+
+ xmlrpc_env env;
+
+ xmlrpc_env_init(&env);
+
+ validateGlobalClientExists(&env);
+
+ if (!env.fault_occurred)
+ xmlrpc_client_start_rpc(&env, globalClientP,
+ serverInfoP, methodName, paramArrayP,
+ responseHandler, userData);
+
+ if (env.fault_occurred) {
+ /* Unfortunately, we have no way to return an error and the
+ regular callback for a failed RPC is designed to have the
+ parameter array passed to it. This was probably an oversight
+ of the original asynch design, but now we have to be as
+ backward compatible as possible, so we do this:
+ */
+ (*responseHandler)(serverInfoP->serverUrl,
+ methodName, paramArrayP, userData,
+ &env, NULL);
+ }
+ xmlrpc_env_clean(&env);
+}
+
+
+
+void
+xmlrpc_client_call_asynch(const char * const serverUrl,
+ const char * const methodName,
+ xmlrpc_response_handler responseHandler,
+ void * const userData,
+ const char * const format,
+ ...) {
+
+ xmlrpc_env env;
+
+ xmlrpc_env_init(&env);
+
+ validateGlobalClientExists(&env);
+
+ if (!env.fault_occurred) {
+ xmlrpc_value * paramArrayP;
+ const char * suffix;
+ va_list args;
+
+ va_start(args, format);
+ xmlrpc_build_value_va(&env, format, args, ¶mArrayP, &suffix);
+ va_end(args);
+
+ if (!env.fault_occurred) {
+ if (*suffix != '\0')
+ xmlrpc_faultf(&env, "Junk after the argument "
+ "specifier: '%s'. "
+ "There must be exactly one arument.",
+ suffix);
+ else
+ xmlrpc_client_call_asynch_params(
+ serverUrl, methodName, responseHandler, userData,
+ paramArrayP);
+ }
+ }
+ if (env.fault_occurred)
+ (*responseHandler)(serverUrl, methodName, NULL, userData, &env, NULL);
+
+ xmlrpc_env_clean(&env);
+}
+
+
+
+void
+xmlrpc_client_call_asynch_params(const char * const serverUrl,
+ const char * const methodName,
+ xmlrpc_response_handler responseHandler,
+ void * const userData,
+ xmlrpc_value * const paramArrayP) {
+ xmlrpc_env env;
+ xmlrpc_server_info * serverInfoP;
+
+ xmlrpc_env_init(&env);
+
+ serverInfoP = xmlrpc_server_info_new(&env, serverUrl);
+
+ if (!env.fault_occurred) {
+ xmlrpc_client_call_server_asynch_params(
+ serverInfoP, methodName, responseHandler, userData, paramArrayP);
+
+ xmlrpc_server_info_free(serverInfoP);
+ }
+ if (env.fault_occurred)
+ (*responseHandler)(serverUrl, methodName, paramArrayP, userData,
+ &env, NULL);
+ xmlrpc_env_clean(&env);
+}
+
+
+
+void
+xmlrpc_client_call_server_asynch(xmlrpc_server_info * const serverInfoP,
+ const char * const methodName,
+ xmlrpc_response_handler responseHandler,
+ void * const userData,
+ const char * const format,
+ ...) {
+
+ xmlrpc_env env;
+ xmlrpc_value * paramArrayP;
+ const char * suffix;
+ va_list args;
+
+ xmlrpc_env_init(&env);
+
+ va_start(args, format);
+ xmlrpc_build_value_va(&env, format, args, ¶mArrayP, &suffix);
+ va_end(args);
+
+ if (!env.fault_occurred) {
+ if (*suffix != '\0')
+ xmlrpc_faultf(&env, "Junk after the argument "
+ "specifier: '%s'. "
+ "There must be exactly one arument.",
+ suffix);
+ else
+ xmlrpc_client_call_server_asynch_params(
+ serverInfoP, methodName, responseHandler, userData,
+ paramArrayP);
+
+ xmlrpc_DECREF(paramArrayP);
+ }
+ if (env.fault_occurred)
+ (*responseHandler)(serverInfoP->serverUrl, methodName, NULL,
+ userData, &env, NULL);
+
+ xmlrpc_env_clean(&env);
+}
+
+
+
+void
+xmlrpc_client_event_loop_finish_asynch(void) {
+
+ XMLRPC_ASSERT(globalClientExists);
+ xmlrpc_client_event_loop_finish(globalClientP);
+}
+
+
+
+void
+xmlrpc_client_event_loop_finish_asynch_timeout(
+ unsigned long const milliseconds) {
+
+ XMLRPC_ASSERT(globalClientExists);
+ xmlrpc_client_event_loop_finish_timeout(globalClientP, milliseconds);
+}
Modified: freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_data.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_data.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_data.c Fri May 23 16:56:24 2008
@@ -14,7 +14,6 @@
#include "xmlrpc-c/base_int.h"
-
static void
destroyValue(xmlrpc_value * const valueP) {
@@ -34,11 +33,7 @@
break;
case XMLRPC_TYPE_STRING:
-#ifdef HAVE_UNICODE_WCHAR
- if (valueP->_wcs_block)
- xmlrpc_mem_block_free(valueP->_wcs_block);
-#endif /* HAVE_UNICODE_WCHAR */
- xmlrpc_mem_block_clean(&valueP->_block);
+ xmlrpc_destroyString(valueP);
break;
case XMLRPC_TYPE_BASE64:
@@ -59,11 +54,14 @@
case XMLRPC_TYPE_NIL:
break;
+ case XMLRPC_TYPE_I8:
+ break;
+
case XMLRPC_TYPE_DEAD:
- XMLRPC_ASSERT(FALSE); /* Can't happen, per entry conditions */
+ XMLRPC_ASSERT(false); /* Can't happen, per entry conditions */
default:
- XMLRPC_ASSERT(FALSE); /* There are no other possible values */
+ XMLRPC_ASSERT(false); /* There are no other possible values */
}
/* Next, we mark this value as invalid, to help catch refcount
@@ -115,9 +113,9 @@
=========================================================================*/
const char *
-xmlrpc_typeName(xmlrpc_type const type) {
+xmlrpc_type_name(xmlrpc_type const type) {
- switch(type) {
+ switch (type) {
case XMLRPC_TYPE_INT: return "INT";
case XMLRPC_TYPE_BOOL: return "BOOL";
@@ -129,53 +127,12 @@
case XMLRPC_TYPE_STRUCT: return "STRUCT";
case XMLRPC_TYPE_C_PTR: return "C_PTR";
case XMLRPC_TYPE_NIL: return "NIL";
+ case XMLRPC_TYPE_I8: return "I8";
case XMLRPC_TYPE_DEAD: return "DEAD";
default: return "???";
- }
-}
-
-
-
-static void
-verifyNoNulls(xmlrpc_env * const envP,
- const char * const contents,
- unsigned int const len) {
-/*----------------------------------------------------------------------------
- Verify that the character array 'contents', which is 'len' bytes long,
- does not contain any NUL characters, which means it can be made into
- a passable ASCIIZ string just by adding a terminating NUL.
-
- Fail if the array contains a NUL.
------------------------------------------------------------------------------*/
- unsigned int i;
-
- for (i = 0; i < len && !envP->fault_occurred; i++)
- if (contents[i] == '\0')
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_TYPE_ERROR,
- "String must not contain NUL characters");
-}
-
-
-
-#ifdef HAVE_UNICODE_WCHAR
-
-static void
-verifyNoNullsW(xmlrpc_env * const envP,
- const wchar_t * const contents,
- unsigned int const len) {
-/*----------------------------------------------------------------------------
- Same as verifyNoNulls(), but for wide characters.
------------------------------------------------------------------------------*/
- unsigned int i;
- for (i = 0; i < len && !envP->fault_occurred; i++)
- if (contents[i] == '\0')
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_TYPE_ERROR,
- "String must not contain NUL characters");
+ }
}
-#endif
@@ -188,7 +145,7 @@
xmlrpc_env_set_fault_formatted(
envP, XMLRPC_TYPE_ERROR, "Value of type %s supplied where "
"type %s was expected.",
- xmlrpc_typeName(valueP->_type), xmlrpc_typeName(expectedType));
+ xmlrpc_type_name(valueP->_type), xmlrpc_type_name(expectedType));
}
}
@@ -239,270 +196,10 @@
}
-/* datetime stuff is in xmlrpc_datetime.c */
-
-static void
-accessStringValue(xmlrpc_env * const envP,
- const xmlrpc_value * const valueP,
- size_t * const lengthP,
- const char ** const contentsP) {
-
- validateType(envP, valueP, XMLRPC_TYPE_STRING);
- if (!envP->fault_occurred) {
- unsigned int const size =
- XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block);
- const char * const contents =
- XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block);
- unsigned int const len = size - 1;
- /* The memblock has a null character added to the end */
-
- verifyNoNulls(envP, contents, len);
-
- *lengthP = len;
- *contentsP = contents;
- }
-}
-
-
-
-void
-xmlrpc_read_string(xmlrpc_env * const envP,
- const xmlrpc_value * const valueP,
- const char ** const stringValueP) {
-/*----------------------------------------------------------------------------
- Read the value of an XML-RPC string as an ASCIIZ string.
-
- Return the string in newly malloc'ed storage that Caller must free.
-
- Fail if the string contains null characters (which means it wasn't
- really a string, but XML-RPC doesn't seem to understand what a string
- is, and such values are possible).
------------------------------------------------------------------------------*/
- size_t length;
- const char * contents;
-
- accessStringValue(envP, valueP, &length, &contents);
-
- if (!envP->fault_occurred) {
- char * stringValue;
-
- stringValue = malloc(length+1);
- if (stringValue == NULL)
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR, "Unable to allocate space "
- "for %u-character string", length);
- else {
- memcpy(stringValue, contents, length);
- stringValue[length] = '\0';
-
- *stringValueP = stringValue;
- }
- }
-}
-
-
-
-void
-xmlrpc_read_string_old(xmlrpc_env * const envP,
- const xmlrpc_value * const valueP,
- const char ** const stringValueP) {
-
- size_t length;
- accessStringValue(envP, valueP, &length, stringValueP);
-}
-
-
-
-void
-xmlrpc_read_string_lp(xmlrpc_env * const envP,
- const xmlrpc_value * const valueP,
- size_t * const lengthP,
- const char ** const stringValueP) {
-
- validateType(envP, valueP, XMLRPC_TYPE_STRING);
- if (!envP->fault_occurred) {
- unsigned int const size =
- XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block);
- const char * const contents =
- XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block);
-
- char * stringValue;
-
- stringValue = malloc(size);
- if (stringValue == NULL)
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR, "Unable to allocate %u bytes "
- "for string.", size);
- else {
- memcpy(stringValue, contents, size);
- *stringValueP = stringValue;
- *lengthP = size - 1; /* Size includes terminating NUL */
- }
- }
-}
-
-
-
-void
-xmlrpc_read_string_lp_old(xmlrpc_env * const envP,
- const xmlrpc_value * const valueP,
- size_t * const lengthP,
- const char ** const stringValueP) {
-
- validateType(envP, valueP, XMLRPC_TYPE_STRING);
- if (!envP->fault_occurred) {
- *lengthP = XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block) - 1;
- *stringValueP = XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block);
- }
-}
-
-
-
-#ifdef HAVE_UNICODE_WCHAR
-static void
-setupWcsBlock(xmlrpc_env * const envP,
- xmlrpc_value * const valueP) {
-/*----------------------------------------------------------------------------
- Add a wcs block (wchar_t string) to the indicated xmlrpc_value if it
- doesn't have one already.
------------------------------------------------------------------------------*/
- if (!valueP->_wcs_block) {
- char * const contents =
- XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block);
- size_t const len =
- XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block) - 1;
- valueP->_wcs_block =
- xmlrpc_utf8_to_wcs(envP, contents, len + 1);
- }
-}
-
-
-
-static void
-accessStringValueW(xmlrpc_env * const envP,
- xmlrpc_value * const valueP,
- size_t * const lengthP,
- const wchar_t ** const stringValueP) {
-
- validateType(envP, valueP, XMLRPC_TYPE_STRING);
- if (!envP->fault_occurred) {
- setupWcsBlock(envP, valueP);
-
- if (!envP->fault_occurred) {
- wchar_t * const wcontents =
- XMLRPC_MEMBLOCK_CONTENTS(wchar_t, valueP->_wcs_block);
- size_t const len =
- XMLRPC_MEMBLOCK_SIZE(wchar_t, valueP->_wcs_block) - 1;
-
- verifyNoNullsW(envP, wcontents, len);
-
- *lengthP = len;
- *stringValueP = wcontents;
- }
- }
-}
-
-
-
-void
-xmlrpc_read_string_w(xmlrpc_env * const envP,
- xmlrpc_value * const valueP,
- const wchar_t ** const stringValueP) {
-
- size_t length;
- const wchar_t * wcontents;
-
- accessStringValueW(envP, valueP, &length, &wcontents);
-
- if (!envP->fault_occurred) {
- wchar_t * stringValue;
- stringValue = malloc((length + 1) * sizeof(wchar_t));
- if (stringValue == NULL)
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR,
- "Unable to allocate space for %u-byte string",
- length);
- else {
- memcpy(stringValue, wcontents, length * sizeof(wchar_t));
- stringValue[length] = '\0';
-
- *stringValueP = stringValue;
- }
- }
-}
-
-
-
-void
-xmlrpc_read_string_w_old(xmlrpc_env * const envP,
- xmlrpc_value * const valueP,
- const wchar_t ** const stringValueP) {
-
- size_t length;
-
- accessStringValueW(envP, valueP, &length, stringValueP);
-}
-
-
-
-void
-xmlrpc_read_string_w_lp(xmlrpc_env * const envP,
- xmlrpc_value * const valueP,
- size_t * const lengthP,
- const wchar_t ** const stringValueP) {
-
- validateType(envP, valueP, XMLRPC_TYPE_STRING);
- if (!envP->fault_occurred) {
- setupWcsBlock(envP, valueP);
-
- if (!envP->fault_occurred) {
- wchar_t * const wcontents =
- XMLRPC_MEMBLOCK_CONTENTS(wchar_t, valueP->_wcs_block);
- size_t const size =
- XMLRPC_MEMBLOCK_SIZE(wchar_t, valueP->_wcs_block);
-
- wchar_t * stringValue;
-
- stringValue = malloc(size * sizeof(wchar_t));
- if (stringValue == NULL)
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR,
- "Unable to allocate space for %u-byte string",
- size);
- else {
- memcpy(stringValue, wcontents, size * sizeof(wchar_t));
-
- *lengthP = size - 1; /* size includes terminating NUL */
- *stringValueP = stringValue;
- }
- }
- }
-}
-
+/* datetime stuff is in xmlrpc_datetime.c */
-void
-xmlrpc_read_string_w_lp_old(xmlrpc_env * const envP,
- xmlrpc_value * const valueP,
- size_t * const lengthP,
- const wchar_t ** const stringValueP) {
-
- validateType(envP, valueP, XMLRPC_TYPE_STRING);
- if (!envP->fault_occurred) {
- setupWcsBlock(envP, valueP);
-
- if (!envP->fault_occurred) {
- wchar_t * const wcontents =
- XMLRPC_MEMBLOCK_CONTENTS(wchar_t, valueP->_wcs_block);
- size_t const size =
- XMLRPC_MEMBLOCK_SIZE(wchar_t, valueP->_wcs_block);
-
- *lengthP = size - 1; /* size includes terminatnig NUL */
- *stringValueP = wcontents;
- }
- }
-}
-#endif
+/* string stuff is in xmlrpc_string.c */
@@ -566,6 +263,18 @@
void
+xmlrpc_read_cptr(xmlrpc_env * const envP,
+ const xmlrpc_value * const valueP,
+ void ** const ptrValueP) {
+
+ validateType(envP, valueP, XMLRPC_TYPE_C_PTR);
+ if (!envP->fault_occurred)
+ *ptrValueP = valueP->_value.c_ptr;
+}
+
+
+
+void
xmlrpc_read_nil(xmlrpc_env * const envP,
xmlrpc_value * const valueP) {
/*----------------------------------------------------------------------------
@@ -578,19 +287,19 @@
-void
-xmlrpc_read_cptr(xmlrpc_env * const envP,
- const xmlrpc_value * const valueP,
- void ** const ptrValueP) {
+void
+xmlrpc_read_i8(xmlrpc_env * const envP,
+ const xmlrpc_value * const valueP,
+ xmlrpc_int64 * const intValueP) {
- validateType(envP, valueP, XMLRPC_TYPE_C_PTR);
+ validateType(envP, valueP, XMLRPC_TYPE_I8);
if (!envP->fault_occurred)
- *ptrValueP = valueP->_value.c_ptr;
+ *intValueP = valueP->_value.i8;
}
-xmlrpc_type xmlrpc_value_type (xmlrpc_value* value)
+xmlrpc_type xmlrpc_value_type (xmlrpc_value* const value)
{
XMLRPC_ASSERT_VALUE_OK(value);
return value->_type;
@@ -638,16 +347,16 @@
xmlrpc_value *
-xmlrpc_bool_new(xmlrpc_env * const envP,
- xmlrpc_bool const value) {
+xmlrpc_i8_new(xmlrpc_env * const envP,
+ xmlrpc_int64 const value) {
xmlrpc_value * valP;
xmlrpc_createXmlrpcValue(envP, &valP);
if (!envP->fault_occurred) {
- valP->_type = XMLRPC_TYPE_BOOL;
- valP->_value.b = value;
+ valP->_type = XMLRPC_TYPE_I8;
+ valP->_value.i8 = value;
}
return valP;
}
@@ -655,51 +364,16 @@
xmlrpc_value *
-xmlrpc_double_new(xmlrpc_env * const envP,
- double const value) {
-
- xmlrpc_value * valP;
-
- xmlrpc_createXmlrpcValue(envP, &valP);
-
- if (!envP->fault_occurred) {
- valP->_type = XMLRPC_TYPE_DOUBLE;
- valP->_value.d = value;
- }
- return valP;
-}
-
-
-
-#ifdef HAVE_UNICODE_WCHAR
-#define MAKE_WCS_BLOCK_NULL(val) ((val)->_wcs_block = NULL)
-#else
-#define MAKE_WCS_BLOCK_NULL(val) while (0) do {};
-#endif
-
-
-
-xmlrpc_value *
-xmlrpc_string_new_lp(xmlrpc_env * const envP,
- size_t const length,
- const char * const value) {
+xmlrpc_bool_new(xmlrpc_env * const envP,
+ xmlrpc_bool const value) {
xmlrpc_value * valP;
xmlrpc_createXmlrpcValue(envP, &valP);
if (!envP->fault_occurred) {
- valP->_type = XMLRPC_TYPE_STRING;
- MAKE_WCS_BLOCK_NULL(valP);
- XMLRPC_MEMBLOCK_INIT(char, envP, &valP->_block, length + 1);
- if (!envP->fault_occurred) {
- char * const contents =
- XMLRPC_MEMBLOCK_CONTENTS(char, &valP->_block);
- memcpy(contents, value, length);
- contents[length] = '\0';
- }
- if (envP->fault_occurred)
- free(valP);
+ valP->_type = XMLRPC_TYPE_BOOL;
+ valP->_value.b = value;
}
return valP;
}
@@ -707,60 +381,16 @@
xmlrpc_value *
-xmlrpc_string_new(xmlrpc_env * const envP,
- const char * const value) {
-
- return xmlrpc_string_new_lp(envP, strlen(value), value);
-}
-
-
-#ifdef HAVE_UNICODE_WCHAR
-xmlrpc_value *
-xmlrpc_string_w_new_lp(xmlrpc_env * const envP,
- size_t const length,
- const wchar_t * const value) {
+xmlrpc_double_new(xmlrpc_env * const envP,
+ double const value) {
xmlrpc_value * valP;
- /* Initialize our XML-RPC value. */
xmlrpc_createXmlrpcValue(envP, &valP);
if (!envP->fault_occurred) {
- valP->_type = XMLRPC_TYPE_STRING;
-
- /* Build our wchar_t block first. */
- valP->_wcs_block =
- XMLRPC_MEMBLOCK_NEW(wchar_t, envP, length + 1);
- if (!envP->fault_occurred) {
- wchar_t * const wcs_contents =
- XMLRPC_MEMBLOCK_CONTENTS(wchar_t, valP->_wcs_block);
-
- xmlrpc_mem_block * utf8_block;
-
- memcpy(wcs_contents, value, length * sizeof(wchar_t));
- wcs_contents[length] = '\0';
-
- /* Convert the wcs block to UTF-8. */
- utf8_block = xmlrpc_wcs_to_utf8(envP, wcs_contents, length + 1);
- if (!envP->fault_occurred) {
- char * const utf8_contents =
- XMLRPC_MEMBLOCK_CONTENTS(char, utf8_block);
- size_t const utf8_len = XMLRPC_MEMBLOCK_SIZE(char, utf8_block);
-
- /* XXX - We need an extra memcopy to initialize _block. */
- XMLRPC_MEMBLOCK_INIT(char, envP, &valP->_block, utf8_len);
- if (!envP->fault_occurred) {
- char * contents;
- contents = XMLRPC_MEMBLOCK_CONTENTS(char, &valP->_block);
- memcpy(contents, utf8_contents, utf8_len);
- }
- XMLRPC_MEMBLOCK_FREE(char, utf8_block);
- }
- if (envP->fault_occurred)
- XMLRPC_MEMBLOCK_FREE(wchar_t, valP->_wcs_block);
- }
- if (envP->fault_occurred)
- free(valP);
+ valP->_type = XMLRPC_TYPE_DOUBLE;
+ valP->_value.d = value;
}
return valP;
}
@@ -768,13 +398,6 @@
xmlrpc_value *
-xmlrpc_string_w_new(xmlrpc_env * const envP,
- const wchar_t * const value) {
- return xmlrpc_string_w_new_lp(envP, wcslen(value), value);
-}
-#endif
-
-xmlrpc_value *
xmlrpc_base64_new(xmlrpc_env * const envP,
size_t const length,
const unsigned char * const value) {
Modified: freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_datetime.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_datetime.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_datetime.c Fri May 23 16:56:24 2008
@@ -5,15 +5,21 @@
#include <string.h>
#include <ctype.h>
#include <assert.h>
+#if MSVCRT
+#include <windows.h>
+#endif
#include "bool.h"
+
#include "xmlrpc-c/base.h"
#include "xmlrpc-c/base_int.h"
+#include "xmlrpc-c/string_int.h"
+#include "xmlrpc-c/time_int.h"
/* Future work: the XMLRPC_TYPE_DATETIME xmlrpc_value should store the
datetime as something computation-friendly, not as a string. The
- client library should parse the string value and reject the XML if
+ XML-RPC XML parser should parse the string value and reject the XML if
it isn't valid.
But this file should remain the authority on datetimes, so the XML
@@ -24,58 +30,70 @@
*/
-#ifdef WIN32
+#if MSVCRT
static const __int64 SECS_BETWEEN_EPOCHS = 11644473600;
static const __int64 SECS_TO_100NS = 10000000; /* 10^7 */
-void UnixTimeToFileTime(const time_t t, LPFILETIME pft)
-{
- // Note that LONGLONG is a 64-bit value
- LONGLONG ll;
- ll = Int32x32To64(t, SECS_TO_100NS) + SECS_BETWEEN_EPOCHS * SECS_TO_100NS;
- pft->dwLowDateTime = (DWORD)ll;
- pft->dwHighDateTime = ll >> 32;
+void
+UnixTimeToFileTime(time_t const t,
+ LPFILETIME const pft) {
+
+ int64_t const ll =
+ Int32x32To64(t, SECS_TO_100NS) + SECS_BETWEEN_EPOCHS * SECS_TO_100NS;
+
+ pft->dwLowDateTime = (DWORD)ll;
+ pft->dwHighDateTime = (DWORD)(ll >> 32);
}
-void UnixTimeToSystemTime(const time_t t, LPSYSTEMTIME pst)
-{
+
+
+void
+UnixTimeToSystemTime(time_t const t,
+ LPSYSTEMTIME const pst) {
FILETIME ft;
UnixTimeToFileTime(t, &ft);
FileTimeToSystemTime(&ft, pst);
}
-static void UnixTimeFromFileTime(xmlrpc_env * const envP, LPFILETIME pft, time_t * const timeValueP)
-{
- LONGLONG ll;
-
- ll = ((LONGLONG)pft->dwHighDateTime << 32) + pft->dwLowDateTime;
- /* convert to the Unix epoch */
- ll -= (SECS_BETWEEN_EPOCHS * SECS_TO_100NS);
- /* now convert to seconds */
- ll /= SECS_TO_100NS;
-
- if ( (time_t)ll != ll )
- {
- //fail - value is too big for a time_t
+
+
+static void
+UnixTimeFromFileTime(xmlrpc_env * const envP,
+ LPFILETIME const pft,
+ time_t * const timeValueP) {
+
+ int64_t const WinEpoch100Ns =
+ ((int64_t)pft->dwHighDateTime << 32) + pft->dwLowDateTime;
+ int64_t const unixEpoch100Ns =
+ WinEpoch100Ns - (SECS_BETWEEN_EPOCHS * SECS_TO_100NS);
+ int64_t const unixEpochSeconds =
+ unixEpoch100Ns / SECS_TO_100NS;
+
+ if ((time_t)unixEpochSeconds != unixEpochSeconds) {
+ /* Value is too big for a time_t; fail. */
xmlrpc_faultf(envP, "Does not indicate a valid date");
- *timeValueP = (time_t)-1;
- return;
- }
- *timeValueP = (time_t)ll;
+ *timeValueP = (time_t)(-1);
+ } else
+ *timeValueP = (time_t)unixEpochSeconds;
}
-static void UnixTimeFromSystemTime(xmlrpc_env * const envP, LPSYSTEMTIME pst, time_t * const timeValueP)
-{
+
+
+static void
+UnixTimeFromSystemTime(xmlrpc_env * const envP,
+ LPSYSTEMTIME const pst,
+ time_t * const timeValueP) {
FILETIME filetime;
SystemTimeToFileTime(pst, &filetime);
UnixTimeFromFileTime(envP, &filetime, timeValueP);
}
-#endif
+#endif /* MSVCRT */
+
static void
@@ -86,8 +104,8 @@
xmlrpc_env_set_fault_formatted(
envP, XMLRPC_TYPE_ERROR, "Value of type %s supplied where "
"type %s was expected.",
- xmlrpc_typeName(valueP->_type),
- xmlrpc_typeName(XMLRPC_TYPE_DATETIME));
+ xmlrpc_type_name(valueP->_type),
+ xmlrpc_type_name(XMLRPC_TYPE_DATETIME));
}
}
@@ -184,125 +202,6 @@
}
-#ifdef HAVE_SETENV
-xmlrpc_bool const haveSetenv = TRUE;
-#else
-xmlrpc_bool const haveSetenv = FALSE;
-static void
-setenv(const char * const name ATTR_UNUSED,
- const char * const value ATTR_UNUSED,
- int const replace ATTR_UNUSED) {
- assert(FALSE);
-}
-#endif
-
-static void
-makeTimezoneUtc(xmlrpc_env * const envP,
- const char ** const oldTzP) {
-
- const char * const tz = getenv("TZ");
-
-#ifdef WIN32
- /* Windows implementation does not exist */
- assert(TRUE);
-#endif
-
- if (haveSetenv) {
- if (tz) {
- *oldTzP = strdup(tz);
- if (*oldTzP == NULL)
- xmlrpc_faultf(envP, "Unable to get memory to save TZ "
- "environment variable.");
- } else
- *oldTzP = NULL;
-
- if (!envP->fault_occurred)
- setenv("TZ", "", 1);
- } else {
- if (tz && strlen(tz) == 0) {
- /* Everything's fine. Nothing to change or restore */
- } else {
- /* Note that putenv() is not sufficient. You can't restore
- the original value with that, because it sets a pointer into
- your own storage.
- */
- xmlrpc_faultf(envP, "Your TZ environment variable is not a "
- "null string and your C library does not have "
- "setenv(), so we can't change it.");
- }
- }
-}
-
-
-
-static void
-restoreTimezone(const char * const oldTz) {
-
- if (haveSetenv) {
- setenv("TZ", oldTz, 1);
- free((char*)oldTz);
- }
-}
-
-
-
-static void
-mkAbsTime(xmlrpc_env * const envP,
- struct tm const brokenTime,
- time_t * const timeValueP) {
-
-#ifdef WIN32
- /* Windows Implementation */
- SYSTEMTIME stbrokenTime;
-
- stbrokenTime.wHour = brokenTime.tm_hour;
- stbrokenTime.wMinute = brokenTime.tm_min;
- stbrokenTime.wSecond = brokenTime.tm_sec;
- stbrokenTime.wMonth = brokenTime.tm_mon;
- stbrokenTime.wDay = brokenTime.tm_mday;
- stbrokenTime.wYear = brokenTime.tm_year;
- stbrokenTime.wMilliseconds = 0;
-
- /* When the date string is parsed into the tm structure, it was
- modified to decrement the month count by one and convert the
- 4 digit year to a two digit year. We undo what the parser
- did to make it a true SYSTEMTIME structure, then convert this
- structure into a UNIX time_t structure
- */
- stbrokenTime.wYear+=1900;
- stbrokenTime.wMonth+=1;
-
- UnixTimeFromSystemTime(envP, &stbrokenTime,timeValueP);
-
-#else
-
- time_t mktimeResult;
- const char * oldTz;
- struct tm mktimeWork;
-
- /* We use mktime() to create the time_t because it's the
- best we have available, but mktime() takes a local time
- argument, and we have absolute time. So we fake it out
- by temporarily setting the timezone to UTC.
- */
- makeTimezoneUtc(envP, &oldTz);
-
- if (!envP->fault_occurred) {
- mktimeWork = brokenTime;
- mktimeResult = mktime(&mktimeWork);
-
- restoreTimezone(oldTz);
-
- if (mktimeResult == (time_t)-1)
- xmlrpc_faultf(envP, "Does not indicate a valid date");
- else
- *timeValueP = mktimeResult;
- }
-#endif
-
-}
-
-
static void
validateFormat(xmlrpc_env * const envP,
@@ -353,6 +252,13 @@
Example of the format we parse: "19980717T14:08:55"
Note that this is not quite ISO 8601. It's a bizarre combination of
two ISO 8601 formats.
+
+ The input is capable of representing datetimes that cannot be expressed
+ as a time_t. In that case, we fail, with fault code
+ XMLRPC_INTERNAL_ERROR.
+
+ And of course the input may not validly represent a datetime at all.
+ In that case too, we fail with fault code XMLRPC_PARSE_ERROR.
-----------------------------------------------------------------------------*/
validateFormat(envP, t);
@@ -361,20 +267,27 @@
parseDateNumbers(t, &Y, &M, &D, &h, &m, &s);
- if (Y < 1900)
- xmlrpc_faultf(envP, "Year is too early to represent as "
- "a standard Unix time");
+ if (Y < 1970)
+ xmlrpc_env_set_fault(envP, XMLRPC_INTERNAL_ERROR,
+ "Year is too early to represent as "
+ "a standard Unix time");
else {
struct tm brokenTime;
+ const char * error;
- brokenTime.tm_sec = s;
- brokenTime.tm_min = m;
- brokenTime.tm_hour = h;
- brokenTime.tm_mday = D;
- brokenTime.tm_mon = M - 1;
- brokenTime.tm_year = Y - 1900;
+ brokenTime.tm_sec = s;
+ brokenTime.tm_min = m;
+ brokenTime.tm_hour = h;
+ brokenTime.tm_mday = D;
+ brokenTime.tm_mon = M - 1;
+ brokenTime.tm_year = Y - 1900;
- mkAbsTime(envP, brokenTime, timeValueP);
+ xmlrpc_timegm(&brokenTime, timeValueP, &error);
+
+ if (error) {
+ xmlrpc_env_set_fault(envP, XMLRPC_PARSE_ERROR, error);
+ xmlrpc_strfree(error);
+ }
}
}
}
@@ -435,7 +348,7 @@
valP->_type = XMLRPC_TYPE_DATETIME;
- gmtime_r(&value, &brokenTime);
+ xmlrpc_gmtime(value, &brokenTime);
/* Note that this format is NOT ISO 8601 -- it's a bizarre
hybrid of two ISO 8601 formats.
Added: freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_decompose.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_decompose.c Fri May 23 16:56:24 2008
@@ -0,0 +1,1151 @@
+/* By Bryan Henderson July 2006.
+
+ Contributed to the public domain.
+*/
+
+#include "xmlrpc_config.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "bool.h"
+#include "c_util.h"
+#include "mallocvar.h"
+#include "stdargx.h"
+
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/base_int.h"
+#include "xmlrpc-c/string_int.h"
+
+
+/* THE DECOMPOSITION TREE
+
+ We execute xmlrpc_decompose_value() in two steps:
+
+ 1) Create a "decomposition tree" that tells how Caller wants the XML-RPC
+ value decomposed.
+
+ 2) Using that tree, decompose the value. I.e. store stuff in the variables
+ in which Caller wants it stored.
+
+ The decomposition tree is composed of information from the format
+ string and the variable arguments that the format string describes.
+ Nothing in the tree is derived from the actual XML-RPC value being
+ decomposed, and the tree may in fact be invalid for the particular
+ XML-RPC value it's meant for.
+
+ If the XML-RPC value is a simple value such as an integer, the
+ decomposition tree is trivial -- it's a single node that says
+ "store the value of an integer via pointer P".
+
+ Where it gets interesting is where the XML-RPC value to be decomposed
+ is a complex value (array or struct). Then, the root node of the tree
+ says, e.g., "decompose a 5-item array according to the following
+ 5 decomposition trees" and it points to 5 additional nodes. Each of
+ those nodes is the root of another decomposition tree (which can also
+ be called a branch in this context). Each of those branches tells
+ how to decompose one of the items of the array.
+
+ Roots, interior nodes, and leaves are all essentially the same data
+ type.
+*/
+
+struct integerDecomp {
+ xmlrpc_int32 * valueP;
+};
+
+struct boolDecomp {
+ xmlrpc_bool * valueP;
+};
+
+struct doubleDecomp {
+ double * valueP;
+};
+
+struct datetimeTDecomp {
+ time_t * valueP;
+};
+
+struct datetime8Decomp {
+ const char ** valueP;
+};
+
+struct stringDecomp {
+ const char ** valueP;
+ size_t * sizeP;
+ /* NULL means don't store a size */
+};
+
+struct wideStringDecomp {
+#if HAVE_UNICODE_WCHAR
+ const wchar_t ** valueP;
+#endif
+ size_t * sizeP;
+ /* NULL means don't store a size */
+};
+
+struct bitStringDecomp {
+ const unsigned char ** valueP;
+ size_t * sizeP;
+};
+
+struct cptrDecomp {
+ void ** valueP;
+};
+
+struct i8Decomp {
+ xmlrpc_int64 * valueP;
+};
+
+struct valueDecomp {
+ xmlrpc_value ** valueP;
+};
+
+struct arrayValDecomp {
+ xmlrpc_value ** valueP;
+};
+
+struct structValDecomp {
+ xmlrpc_value ** valueP;
+};
+
+struct arrayDecomp {
+ unsigned int itemCnt;
+ bool ignoreExcess;
+ /* If there are more that 'itemCnt' items in the array, just
+ extract the first 'itemCnt' and ignore the rest, rather than
+ fail the decomposition.
+ */
+ struct decompTreeNode * itemArray[16];
+ /* Only first 'itemCnt' elements of this array are defined */
+};
+
+struct mbrDecomp {
+ const char * key;
+ /* The key for the member whose value client wants to extract */
+ struct decompTreeNode * decompTreeP;
+ /* Instructions on how to decompose (extract) member's value */
+};
+
+struct structDecomp {
+ unsigned int mbrCnt;
+ struct mbrDecomp mbrArray[16];
+};
+
+
+struct decompTreeNode {
+ char formatSpecChar;
+ /* e.g. 'i', 'b', '8', 'A'. '(' means array; '{' means struct */
+ union {
+ /*------------------------------------------------------------------------
+ 'formatSpecChar' selects among these members.
+ -------------------------------------------------------------------------*/
+ struct integerDecomp Tinteger;
+ struct boolDecomp Tbool;
+ struct doubleDecomp Tdouble;
+ struct datetimeTDecomp TdatetimeT;
+ struct datetime8Decomp Tdatetime8;
+ struct stringDecomp Tstring;
+ struct wideStringDecomp TwideString;
+ struct bitStringDecomp TbitString;
+ struct cptrDecomp Tcptr;
+ struct i8Decomp Ti8;
+ struct valueDecomp Tvalue;
+ struct arrayValDecomp TarrayVal;
+ struct structValDecomp TstructVal;
+ struct arrayDecomp Tarray;
+ struct structDecomp Tstruct;
+ } store;
+
+};
+
+
+
+/* prototype for recursive calls */
+static void
+releaseDecomposition(const struct decompTreeNode * const decompRootP,
+ bool const oldstyleMemMgmt);
+
+
+static void
+releaseDecompArray(struct arrayDecomp const arrayDecomp,
+ bool const oldstyleMemMgmt) {
+
+ unsigned int i;
+ for (i = 0; i < arrayDecomp.itemCnt; ++i) {
+ releaseDecomposition(arrayDecomp.itemArray[i], oldstyleMemMgmt);
+ }
+}
+
+
+static void
+releaseDecompStruct(struct structDecomp const structDecomp,
+ bool const oldstyleMemMgmt) {
+
+ unsigned int i;
+ for (i = 0; i < structDecomp.mbrCnt; ++i) {
+ releaseDecomposition(structDecomp.mbrArray[i].decompTreeP,
+ oldstyleMemMgmt);
+ }
+}
+
+
+
+static void
+releaseDecomposition(const struct decompTreeNode * const decompRootP,
+ bool const oldstyleMemMgmt) {
+/*----------------------------------------------------------------------------
+ Assuming that Caller has decomposed something according to 'decompRootP',
+ release whatever resources the decomposed information occupies.
+
+ E.g. if it's an XML-RPC string, Caller would have allocated memory
+ for the C string that represents the decomposed value of XML-RPC string,
+ and we release that memory.
+-----------------------------------------------------------------------------*/
+ switch (decompRootP->formatSpecChar) {
+ case 'i':
+ case 'b':
+ case 'd':
+ case 'n':
+ case 'I':
+ case 't':
+ case 'p':
+ /* Nothing was allocated; nothing to release */
+ break;
+ case '8':
+ xmlrpc_strfree(*decompRootP->store.Tdatetime8.valueP);
+ break;
+ case 's':
+ xmlrpc_strfree(*decompRootP->store.Tstring.valueP);
+ break;
+ case 'w':
+ free((void*)*decompRootP->store.TwideString.valueP);
+ break;
+ case '6':
+ free((void*)*decompRootP->store.TbitString.valueP);
+ break;
+ case 'V':
+ xmlrpc_DECREF(*decompRootP->store.Tvalue.valueP);
+ break;
+ case 'A':
+ xmlrpc_DECREF(*decompRootP->store.TarrayVal.valueP);
+ break;
+ case 'S':
+ xmlrpc_DECREF(*decompRootP->store.TstructVal.valueP);
+ break;
+ case '(':
+ releaseDecompArray(decompRootP->store.Tarray, oldstyleMemMgmt);
+ break;
+ case '{':
+ releaseDecompStruct(decompRootP->store.Tstruct, oldstyleMemMgmt);
+ break;
+ }
+}
+
+
+
+/* Prototype for recursive invocation: */
+
+static void
+decomposeValueWithTree(xmlrpc_env * const envP,
+ xmlrpc_value * const valueP,
+ bool const oldstyleMemMgmt,
+ const struct decompTreeNode * const decompRootP);
+
+
+
+static void
+validateArraySize(xmlrpc_env * const envP,
+ const xmlrpc_value * const arrayP,
+ struct arrayDecomp const arrayDecomp) {
+
+ unsigned int size;
+
+ size = xmlrpc_array_size(envP, arrayP);
+ if (!envP->fault_occurred) {
+ if (arrayDecomp.itemCnt > size)
+ xmlrpc_env_set_fault_formatted(
+ envP, XMLRPC_INDEX_ERROR,
+ "Format string requests %u items from array, but array "
+ "has only %u items.", arrayDecomp.itemCnt, size);
+ else if (arrayDecomp.itemCnt < size && !arrayDecomp.ignoreExcess)
+ xmlrpc_env_set_fault_formatted(
+ envP, XMLRPC_INDEX_ERROR,
+ "Format string requests exactly %u items from array, "
+ "but array has %u items. (A '*' at the end would avoid "
+ "this failure)", arrayDecomp.itemCnt, size);
+ }
+}
+
+
+
+static void
+parsearray(xmlrpc_env * const envP,
+ const xmlrpc_value * const arrayP,
+ struct arrayDecomp const arrayDecomp,
+ bool const oldstyleMemMgmt) {
+
+ validateArraySize(envP, arrayP, arrayDecomp);
+
+ if (!envP->fault_occurred) {
+ unsigned int doneCnt;
+
+ doneCnt = 0;
+ while(doneCnt < arrayDecomp.itemCnt && !envP->fault_occurred) {
+ xmlrpc_value * itemP;
+
+ xmlrpc_array_read_item(envP, arrayP, doneCnt, &itemP);
+
+ if (!envP->fault_occurred) {
+ XMLRPC_ASSERT(doneCnt < ARRAY_SIZE(arrayDecomp.itemArray));
+ decomposeValueWithTree(envP, itemP, oldstyleMemMgmt,
+ arrayDecomp.itemArray[doneCnt]);
+
+ if (!envP->fault_occurred)
+ ++doneCnt;
+
+ xmlrpc_DECREF(itemP);
+ }
+ }
+ if (envP->fault_occurred) {
+ /* Release the items we completed before we failed. */
+ unsigned int i;
+ for (i = 0; i < doneCnt; ++i)
+ releaseDecomposition(arrayDecomp.itemArray[i],
+ oldstyleMemMgmt);
+ }
+ }
+}
+
+
+
+static void
+parsestruct(xmlrpc_env * const envP,
+ xmlrpc_value * const structP,
+ struct structDecomp const structDecomp,
+ bool const oldstyleMemMgmt) {
+
+ unsigned int doneCount;
+
+ doneCount = 0; /* No members done yet */
+
+ while (doneCount < structDecomp.mbrCnt && !envP->fault_occurred) {
+ const char * const key = structDecomp.mbrArray[doneCount].key;
+
+ xmlrpc_value * valueP;
+
+ xmlrpc_struct_read_value(envP, structP, key, &valueP);
+
+ if (!envP->fault_occurred) {
+ decomposeValueWithTree(
+ envP, valueP, oldstyleMemMgmt,
+ structDecomp.mbrArray[doneCount].decompTreeP);
+
+ if (!envP->fault_occurred)
+ ++doneCount;
+
+ xmlrpc_DECREF(valueP);
+ }
+ }
+
+ if (envP->fault_occurred) {
+ unsigned int i;
+ for (i = 0; i < doneCount; ++i)
+ releaseDecomposition(structDecomp.mbrArray[i].decompTreeP,
+ oldstyleMemMgmt);
+ }
+}
+
+
+
+static void
+readString(xmlrpc_env * const envP,
+ const xmlrpc_value * const valueP,
+ const char ** const stringValueP,
+ bool const oldstyleMemMgmt) {
+
+ if (oldstyleMemMgmt) {
+ xmlrpc_read_string_old(envP, valueP, stringValueP);
+ } else
+ xmlrpc_read_string(envP, valueP, stringValueP);
+}
+
+
+
+static void
+readStringLp(xmlrpc_env * const envP,
+ const xmlrpc_value * const valueP,
+ size_t * const lengthP,
+ const char ** const stringValueP,
+ bool const oldstyleMemMgmt) {
+
+ if (oldstyleMemMgmt) {
+ xmlrpc_read_string_lp_old(envP, valueP, lengthP, stringValueP);
+ } else
+ xmlrpc_read_string_lp(envP, valueP, lengthP, stringValueP);
+}
+
+
+
+#if HAVE_UNICODE_WCHAR
+static void
+readStringW(xmlrpc_env * const envP,
+ xmlrpc_value * const valueP,
+ const wchar_t ** const stringValueP,
+ bool const oldstyleMemMgmt) {
+
+ if (oldstyleMemMgmt) {
+ xmlrpc_read_string_w_old(envP, valueP, stringValueP);
+ } else
+ xmlrpc_read_string_w(envP, valueP, stringValueP);
+}
+
+
+
+static void
+readStringWLp(xmlrpc_env * const envP,
+ xmlrpc_value * const valueP,
+ size_t * const lengthP,
+ const wchar_t ** const stringValueP,
+ bool const oldstyleMemMgmt) {
+
+ if (oldstyleMemMgmt) {
+ xmlrpc_read_string_w_lp_old(envP, valueP, lengthP, stringValueP);
+ } else
+ xmlrpc_read_string_w_lp(envP, valueP, lengthP, stringValueP);
+}
+#endif
+
+
+static void
+readDatetime8Str(xmlrpc_env * const envP,
+ const xmlrpc_value * const valueP,
+ const char ** const stringValueP,
+ bool const oldstyleMemMgmt) {
+
+ if (oldstyleMemMgmt)
+ xmlrpc_read_datetime_str_old(envP, valueP, stringValueP);
+ else
+ xmlrpc_read_datetime_str(envP, valueP, stringValueP);
+}
+
+
+
+static void
+readBase64(xmlrpc_env * const envP,
+ const xmlrpc_value * const valueP,
+ size_t * const lengthP,
+ const unsigned char ** const byteStringValueP,
+ bool const oldstyleMemMgmt) {
+
+ if (oldstyleMemMgmt)
+ xmlrpc_read_base64_old(envP, valueP, lengthP, byteStringValueP);
+ else
+ xmlrpc_read_base64(envP, valueP, lengthP, byteStringValueP);
+}
+
+
+static void
+decomposeValueWithTree(xmlrpc_env * const envP,
+ xmlrpc_value * const valueP,
+ bool const oldstyleMemMgmt,
+ const struct decompTreeNode * const decompRootP) {
+/*----------------------------------------------------------------------------
+ Decompose XML-RPC value *valueP, given the decomposition tree
+ *decompRootP. The decomposition tree tells what structure *valueP
+ is expected to have and where to put the various components of it
+ (e.g. it says "it's an array of 3 integers. Put their values at
+ locations x, y, and z")
+-----------------------------------------------------------------------------*/
+ switch (decompRootP->formatSpecChar) {
+ case '-':
+ /* There's nothing to validate or return */
+ break;
+ case 'i':
+ xmlrpc_read_int(envP, valueP, decompRootP->store.Tinteger.valueP);
+ break;
+
+ case 'b':
+ xmlrpc_read_bool(envP, valueP, decompRootP->store.Tbool.valueP);
+ break;
+
+ case 'd':
+ xmlrpc_read_double(envP, valueP, decompRootP->store.Tdouble.valueP);
+ break;
+
+ case 't':
+ xmlrpc_read_datetime_sec(envP, valueP,
+ decompRootP->store.TdatetimeT.valueP);
+ break;
+
+ case '8':
+ readDatetime8Str(envP, valueP, decompRootP->store.Tdatetime8.valueP,
+ oldstyleMemMgmt);
+ break;
+
+ case 's':
+ if (decompRootP->store.Tstring.sizeP)
+ readStringLp(envP, valueP,
+ decompRootP->store.Tstring.sizeP,
+ decompRootP->store.Tstring.valueP,
+ oldstyleMemMgmt);
+ else
+ readString(envP, valueP, decompRootP->store.Tstring.valueP,
+ oldstyleMemMgmt);
+ break;
+
+ case 'w':
+#if HAVE_UNICODE_WCHAR
+ if (decompRootP->store.Tstring.sizeP)
+ readStringWLp(envP, valueP,
+ decompRootP->store.TwideString.sizeP,
+ decompRootP->store.TwideString.valueP,
+ oldstyleMemMgmt);
+ else
+ readStringW(envP, valueP, decompRootP->store.TwideString.valueP,
+ oldstyleMemMgmt);
+#else
+ XMLRPC_ASSERT(false);
+#endif /* HAVE_UNICODE_WCHAR */
+ break;
+
+ case '6':
+ readBase64(envP, valueP,
+ decompRootP->store.TbitString.sizeP,
+ decompRootP->store.TbitString.valueP,
+ oldstyleMemMgmt);
+ break;
+
+ case 'n':
+ xmlrpc_read_nil(envP, valueP);
+ break;
+
+ case 'I':
+ xmlrpc_read_i8(envP, valueP, decompRootP->store.Ti8.valueP);
+ break;
+
+ case 'p':
+ xmlrpc_read_cptr(envP, valueP, decompRootP->store.Tcptr.valueP);
+ break;
+
+ case 'V':
+ *decompRootP->store.Tvalue.valueP = valueP;
+ if (!oldstyleMemMgmt)
+ xmlrpc_INCREF(valueP);
+ break;
+
+ case 'A':
+ if (xmlrpc_value_type(valueP) != XMLRPC_TYPE_ARRAY)
+ xmlrpc_env_set_fault_formatted(
+ envP, XMLRPC_TYPE_ERROR, "Value to be decomposed is of type "
+ "%s, but the 'A' specifier requires type ARRAY",
+ xmlrpc_type_name(xmlrpc_value_type(valueP)));
+ else {
+ *decompRootP->store.TarrayVal.valueP = valueP;
+ if (!oldstyleMemMgmt)
+ xmlrpc_INCREF(valueP);
+ }
+ break;
+
+ case 'S':
+ if (xmlrpc_value_type(valueP) != XMLRPC_TYPE_STRUCT)
+ xmlrpc_env_set_fault_formatted(
+ envP, XMLRPC_TYPE_ERROR, "Value to be decomposed is of type "
+ "%s, but the 'S' specifier requires type STRUCT.",
+ xmlrpc_type_name(xmlrpc_value_type(valueP)));
+ else {
+ *decompRootP->store.TstructVal.valueP = valueP;
+ if (!oldstyleMemMgmt)
+ xmlrpc_INCREF(valueP);
+ }
+ break;
+
+ case '(':
+ if (xmlrpc_value_type(valueP) != XMLRPC_TYPE_ARRAY)
+ xmlrpc_env_set_fault_formatted(
+ envP, XMLRPC_TYPE_ERROR, "Value to be decomposed is of type "
+ "%s, but the '(...)' specifier requires type ARRAY",
+ xmlrpc_type_name(xmlrpc_value_type(valueP)));
+ else
+ parsearray(envP, valueP, decompRootP->store.Tarray,
+ oldstyleMemMgmt);
+ break;
+
+ case '{':
+ if (xmlrpc_value_type(valueP) != XMLRPC_TYPE_STRUCT)
+ xmlrpc_env_set_fault_formatted(
+ envP, XMLRPC_TYPE_ERROR, "Value to be decomposed is of type "
+ "%s, but the '{...}' specifier requires type STRUCT",
+ xmlrpc_type_name(xmlrpc_value_type(valueP)));
+ else
+ parsestruct(envP, valueP, decompRootP->store.Tstruct,
+ oldstyleMemMgmt);
+ break;
+
+ default:
+ /* Every format character that is allowed in a decomposition tree
+ node is handled above.
+ */
+ XMLRPC_ASSERT(false);
+ }
+}
+
+
+/* Forward declaration for recursive calls */
+
+static void
+createDecompTreeNext(xmlrpc_env * const envP,
+ const char ** const formatP,
+ va_listx * const argsP,
+ struct decompTreeNode ** const decompNodePP);
+
+
+
+static void
+buildWideStringNode(xmlrpc_env * const envP ATTR_UNUSED,
+ const char ** const formatP,
+ va_listx * const argsP,
+ struct decompTreeNode * const decompNodeP) {
+
+#if HAVE_UNICODE_WCHAR
+ decompNodeP->store.TwideString.valueP =
+ (const wchar_t**) va_arg(argsP->v, wchar_t**);
+ if (**formatP == '#') {
+ decompNodeP->store.TwideString.sizeP =
+ (size_t*) va_arg(argsP->v, size_t**);
+ (*formatP)++;
+ } else
+ decompNodeP->store.TwideString.sizeP = NULL;
+#else
+ xmlrpc_faultf(envP,
+ "This XML-RPC For C/C++ library was built without Unicode "
+ "wide character capability. 'w' isn't available.");
+#endif /* HAVE_UNICODE_WCHAR */
+}
+
+
+
+static void
+destroyDecompTree(struct decompTreeNode * const decompRootP) {
+
+ switch (decompRootP->formatSpecChar) {
+ case '(': {
+ unsigned int i;
+ for (i = 0; i < decompRootP->store.Tarray.itemCnt; ++i)
+ destroyDecompTree(decompRootP->store.Tarray.itemArray[i]);
+ } break;
+ case '{': {
+ unsigned int i;
+ for (i = 0; i < decompRootP->store.Tstruct.mbrCnt; ++i)
+ destroyDecompTree(
+ decompRootP->store.Tstruct.mbrArray[i].decompTreeP);
+ } break;
+ }
+
+ free(decompRootP);
+}
+
+
+
+static void
+processArraySpecTail(xmlrpc_env * const envP,
+ const char ** const formatP,
+ bool * const hasTrailingAsteriskP,
+ char const delim) {
+
+ if (**formatP == '*') {
+ *hasTrailingAsteriskP = true;
+
+ ++*formatP;
+
+ if (!**formatP)
+ xmlrpc_faultf(envP, "missing closing delimiter ('%c')", delim);
+ else if (**formatP != delim)
+ xmlrpc_faultf(envP, "character following '*' in array "
+ "specification should be the closing delimiter "
+ "'%c', but is '%c'", delim, **formatP);
+ } else {
+ *hasTrailingAsteriskP = false;
+
+ if (!**formatP)
+ xmlrpc_faultf(envP, "missing closing delimiter ('%c')", delim);
+ }
+ if (!envP->fault_occurred)
+ XMLRPC_ASSERT(**formatP == delim);
+}
+
+
+
+static void
+buildArrayDecompBranch(xmlrpc_env * const envP,
+ const char ** const formatP,
+ char const delim,
+ va_listx * const argsP,
+ struct decompTreeNode * const decompNodeP) {
+/*----------------------------------------------------------------------------
+ Fill in the decomposition tree node *decompNodeP to cover an array
+ whose items are described by *formatP. To wit, they are the values
+ described by successive format specifiers in *formatP up to but not
+ including the next 'delim' character.
+
+ Plus, the last character before the delimiter might be a '*', which
+ means "ignore any additional items in the array."
+
+ We create a node (and whole branch if required) to describe each array
+ item.
+
+ The pointers to where those items are to be stored are given by
+ 'argsP'.
+
+ We advance *formatP to the delimiter character, and advance 'argsP'
+ past whatever arguments we use.
+-----------------------------------------------------------------------------*/
+ unsigned int itemCnt;
+ /* Number of array items in the branch so far */
+
+ itemCnt = 0; /* Branch is empty so far */
+
+ while (**formatP && **formatP != delim && **formatP != '*' &&
+ !envP->fault_occurred) {
+ if (itemCnt >= ARRAY_SIZE(decompNodeP->store.Tarray.itemArray))
+ xmlrpc_faultf(envP, "Too many array items in format string. "
+ "The most items you can have for an array in "
+ "a format string is %u.",
+ ARRAY_SIZE(decompNodeP->store.Tarray.itemArray));
+ else {
+ struct decompTreeNode * itemNodeP;
+
+ createDecompTreeNext(envP, formatP, argsP, &itemNodeP);
+
+ if (!envP->fault_occurred)
+ decompNodeP->store.Tarray.itemArray[itemCnt++] = itemNodeP;
+ }
+ }
+ if (!envP->fault_occurred) {
+ decompNodeP->store.Tarray.itemCnt = itemCnt;
+ processArraySpecTail(envP, formatP,
+ &decompNodeP->store.Tarray.ignoreExcess,
+ delim);
+ }
+ if (envP->fault_occurred) {
+ unsigned int i;
+ for (i = 0; i < itemCnt; ++i)
+ destroyDecompTree(decompNodeP->store.Tarray.itemArray[i]);
+ }
+}
+
+
+
+static void
+doStructValue(xmlrpc_env * const envP,
+ const char ** const formatP,
+ va_listx * const argsP,
+ struct mbrDecomp * const mbrP) {
+
+ struct decompTreeNode * valueNodeP;
+
+ mbrP->key = (const char*) va_arg(argsP->v, char*);
+
+ createDecompTreeNext(envP, formatP, argsP, &valueNodeP);
+
+ if (!envP->fault_occurred)
+ mbrP->decompTreeP = valueNodeP;
+}
+
+
+
+static void
+skipAsterisk(xmlrpc_env * const envP,
+ const char ** const formatP,
+ char const delim) {
+
+ if (**formatP == '*') {
+ ++*formatP;
+
+ if (!**formatP)
+ xmlrpc_faultf(envP, "missing closing delimiter ('%c')", delim);
+ else if (**formatP != delim)
+ xmlrpc_faultf(envP, "junk after '*' in the specifier of an "
+ "array. First character='%c'", **formatP);
+ } else
+ /* Conceptually, one can make it an error to leave some struct
+ members behind, but we have never had code that knows how to
+ recognize that case.
+ */
+ xmlrpc_faultf(envP,
+ "You must put a trailing '*' in the specifiers for "
+ "struct members to signify it's OK if there are "
+ "additional members you didn't get.");
+}
+
+
+
+static void
+skipColon(xmlrpc_env * const envP,
+ const char ** const formatP,
+ char const delim) {
+
+ if (**formatP == '\0')
+ xmlrpc_faultf(envP, "format string ends in the middle of a struct "
+ "member specifier");
+ else if (**formatP == delim)
+ xmlrpc_faultf(envP, "member list ends in the middle of a member");
+ else if (**formatP != ':')
+ xmlrpc_faultf(envP, "In a struct specifier, '%c' found "
+ "where a colon (':') separating key and "
+ "value was expected.", **formatP);
+}
+
+
+
+static void
+skipComma(xmlrpc_env * const envP,
+ const char ** const formatP,
+ char const delim) {
+
+ if (**formatP && **formatP != delim) {
+ if (**formatP == ',')
+ ++*formatP; /* skip over comma */
+ else
+ xmlrpc_faultf(envP, "'%c' where we expected a ',' "
+ "to separate struct members", **formatP);
+ }
+}
+
+
+
+static void
+buildStructDecompBranch(xmlrpc_env * const envP,
+ const char ** const formatP,
+ char const delim,
+ va_listx * const argsP,
+ struct decompTreeNode * const decompNodeP) {
+/*----------------------------------------------------------------------------
+ Fill in the decomposition tree node *decompNodeP to cover a struct
+ whose members are described by *formatP. To wit, they are the values
+ described by successive format specifiers in *formatP up to but not
+ including the next 'delim' character.
+
+ We create a node (and whole branch if required) to describe each
+ struct member value.
+
+ The pointers to where those values are to be stored are given by
+ 'argsP'.
+
+ The names of the members to be extracted are also given by 'argsP'.
+
+ We advance *formatP to the delimiter character, and advance 'argsP'
+ past whatever arguments we use.
+-----------------------------------------------------------------------------*/
+ unsigned int memberCnt;
+ /* Number of struct members in the branch so far */
+
+ memberCnt = 0; /* Branch is empty so far */
+
+ while (**formatP && **formatP != delim && **formatP != '*' &&
+ !envP->fault_occurred) {
+ if (memberCnt >= ARRAY_SIZE(decompNodeP->store.Tstruct.mbrArray))
+ xmlrpc_faultf(envP,
+ "Too many structure members in format string. "
+ "The most members you can specify in "
+ "a format string is %u.",
+ ARRAY_SIZE(decompNodeP->store.Tstruct.mbrArray));
+ else {
+ struct mbrDecomp * const mbrP =
+ &decompNodeP->store.Tstruct.mbrArray[memberCnt];
+
+ if (**formatP != 's')
+ xmlrpc_faultf(envP, "In a struct specifier, the specifier "
+ "for the key is '%c', but it must be 's'.",
+ **formatP);
+ else {
+ ++*formatP;
+
+ skipColon(envP, formatP, delim);
+
+ if (!envP->fault_occurred) {
+ ++*formatP;
+
+ doStructValue(envP, formatP, argsP, mbrP);
+
+ if (!envP->fault_occurred)
+ ++memberCnt;
+
+ skipComma(envP, formatP, delim);
+ }
+ }
+ }
+ }
+ decompNodeP->store.Tstruct.mbrCnt = memberCnt;
+
+ if (!envP->fault_occurred) {
+ skipAsterisk(envP, formatP, delim);
+ if (!envP->fault_occurred)
+ XMLRPC_ASSERT(**formatP == delim);
+ }
+
+ if (envP->fault_occurred) {
+ unsigned int i;
+ for (i = 0; i < memberCnt; ++i)
+ destroyDecompTree(
+ decompNodeP->store.Tstruct.mbrArray[i].decompTreeP);
+ }
+}
+
+
+
+static void
+createDecompTreeNext(xmlrpc_env * const envP,
+ const char ** const formatP,
+ va_listx * const argsP,
+ struct decompTreeNode ** const decompNodePP) {
+/*----------------------------------------------------------------------------
+ Create a branch of a decomposition tree that applies to the first
+ value described by '*formatP', and advance *formatP past the description
+ of that first value. E.g.:
+
+ - If *formatP is "isb", we create a branch consisting of one
+ node -- for an integer. We advance *formatP by one character, so
+ it points to the "s".
+
+ - If *formatP is "(isb)s", we create a branch that represents the
+ array (isb) and advance *formatP past the closing parenthesis to
+ point to the final "s". We return as *decompNodePP a pointer to
+ a node for the array, and that array in turn points to nodes for
+ each of the 3 array items: one for an integer, one for a string,
+ and one for a boolean.
+
+ The locations at which the components of that value are to be
+ stored (which is the main contents of the branch we create) are
+ given by 'argsP'.
+
+ Return as *decompNodeP a pointer to the root node of the branch we
+ generate.
+-----------------------------------------------------------------------------*/
+ struct decompTreeNode * decompNodeP;
+
+ MALLOCVAR(decompNodeP);
+
+ if (decompNodeP == NULL)
+ xmlrpc_faultf(envP, "Could not allocate space for a decomposition "
+ "tree node");
+ else {
+ decompNodeP->formatSpecChar = *(*formatP)++;
+
+ switch (decompNodeP->formatSpecChar) {
+ case '-':
+ /* There's nothing to store */
+ break;
+ case 'i':
+ decompNodeP->store.Tinteger.valueP =
+ (xmlrpc_int32*) va_arg(argsP->v, xmlrpc_int32*);
+ break;
+
+ case 'b':
+ decompNodeP->store.Tbool.valueP =
+ (xmlrpc_bool*) va_arg(argsP->v, xmlrpc_bool*);
+ break;
+
+ case 'd':
+ decompNodeP->store.Tdouble.valueP =
+ (double*) va_arg(argsP->v, double*);
+ break;
+
+ case 't':
+ decompNodeP->store.TdatetimeT.valueP =
+ va_arg(argsP->v, time_t*);
+ break;
+
+ case '8':
+ decompNodeP->store.Tdatetime8.valueP =
+ (const char**) va_arg(argsP->v, char**);
+ break;
+
+ case 's':
+ decompNodeP->store.Tstring.valueP =
+ (const char**) va_arg(argsP->v, char**);
+ if (**formatP == '#') {
+ decompNodeP->store.Tstring.sizeP =
+ (size_t*) va_arg(argsP->v, size_t**);
+ ++*formatP;
+ } else
+ decompNodeP->store.Tstring.sizeP = NULL;
+ break;
+
+ case 'w':
+ buildWideStringNode(envP, formatP, argsP, decompNodeP);
+ break;
+
+ case '6':
+ decompNodeP->store.TbitString.valueP =
+ (const unsigned char**) va_arg(argsP->v, unsigned char**);
+ decompNodeP->store.TbitString.sizeP =
+ (size_t*) va_arg(argsP->v, size_t**);
+ break;
+
+ case 'n':
+ /* There's no value to store */
+ break;
+
+ case 'I':
+ decompNodeP->store.Ti8.valueP =
+ (xmlrpc_int64 *) va_arg(argsP->v, xmlrpc_int64 *);
+ break;
+
+ case 'p':
+ decompNodeP->store.Tcptr.valueP =
+ (void**) va_arg(argsP->v, void**);
+ break;
+
+ case 'V':
+ decompNodeP->store.Tvalue.valueP =
+ (xmlrpc_value**) va_arg(argsP->v, xmlrpc_value**);
+ break;
+
+ case 'A':
+ decompNodeP->store.TarrayVal.valueP =
+ (xmlrpc_value**) va_arg(argsP->v, xmlrpc_value**);
+ break;
+
+ case 'S':
+ decompNodeP->store.TstructVal.valueP =
+ (xmlrpc_value**) va_arg(argsP->v, xmlrpc_value**);
+ break;
+
+ case '(':
+ buildArrayDecompBranch(envP, formatP, ')', argsP, decompNodeP);
+ ++(*formatP); /* skip past closing ')' */
+ break;
+
+ case '{':
+ buildStructDecompBranch(envP, formatP, '}', argsP, decompNodeP);
+ ++(*formatP); /* skip past closing '}' */
+ break;
+
+ default:
+ xmlrpc_faultf(envP, "Invalid format character '%c'",
+ decompNodeP->formatSpecChar);
+ }
+ if (envP->fault_occurred)
+ free(decompNodeP);
+ else
+ *decompNodePP = decompNodeP;
+ }
+}
+
+
+
+static void
+createDecompTree(xmlrpc_env * const envP,
+ const char * const format,
+ va_listx const args,
+ struct decompTreeNode ** const decompRootPP) {
+
+ const char * formatCursor;
+ struct decompTreeNode * decompRootP;
+ va_listx currentArgs;
+
+ currentArgs = args;
+ formatCursor = &format[0];
+ createDecompTreeNext(envP, &formatCursor, ¤tArgs, &decompRootP);
+ if (!envP->fault_occurred) {
+ if (*formatCursor != '\0')
+ xmlrpc_faultf(envP, "format string '%s' has garbage at the end: "
+ "'%s'. It should be a specifier of a single value "
+ "(but that might be a complex value, such as an "
+ "array)", format, formatCursor);
+
+ if (envP->fault_occurred)
+ destroyDecompTree(decompRootP);
+ else
+ *decompRootPP = decompRootP;
+ }
+}
+
+
+
+static void
+decomposeValue(xmlrpc_env * const envP,
+ xmlrpc_value * const valueP,
+ bool const oldstyleMemMgmt,
+ const char * const format,
+ va_listx const args) {
+
+ struct decompTreeNode * decompRootP;
+
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT_VALUE_OK(valueP);
+ XMLRPC_ASSERT(format != NULL);
+
+ createDecompTree(envP, format, args, &decompRootP);
+
+ if (!envP->fault_occurred) {
+ decomposeValueWithTree(envP, valueP, oldstyleMemMgmt, decompRootP);
+
+ destroyDecompTree(decompRootP);
+ }
+}
+
+
+
+void
+xmlrpc_decompose_value_va(xmlrpc_env * const envP,
+ xmlrpc_value * const valueP,
+ const char * const format,
+ va_list const args) {
+
+ bool const oldstyleMemMgtFalse = false;
+ va_listx argsx;
+
+ init_va_listx(&argsx, args);
+
+ decomposeValue(envP, valueP, oldstyleMemMgtFalse, format, argsx);
+}
+
+
+
+void
+xmlrpc_decompose_value(xmlrpc_env * const envP,
+ xmlrpc_value * const value,
+ const char * const format,
+ ...) {
+
+ va_list args;
+
+ va_start(args, format);
+ xmlrpc_decompose_value_va(envP, value, format, args);
+ va_end(args);
+}
+
+
+
+void
+xmlrpc_parse_value_va(xmlrpc_env * const envP,
+ xmlrpc_value * const valueP,
+ const char * const format,
+ va_list const args) {
+
+ bool const oldstyleMemMgmtTrue = true;
+ va_listx argsx;
+
+ init_va_listx(&argsx, args);
+
+ decomposeValue(envP, valueP, oldstyleMemMgmtTrue, format, argsx);
+}
+
+
+
+void
+xmlrpc_parse_value(xmlrpc_env * const envP,
+ xmlrpc_value * const value,
+ const char * const format,
+ ...) {
+
+ va_list args;
+
+ va_start(args, format);
+ xmlrpc_parse_value_va(envP, value, format, args);
+ va_end(args);
+}
Modified: freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_expat.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_expat.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_expat.c Fri May 23 16:56:24 2008
@@ -1,37 +1,18 @@
-/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
-**
-** Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions
-** are met:
-** 1. Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** 2. Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in the
-** documentation and/or other materials provided with the distribution.
-** 3. The name of the author may not be used to endorse or promote products
-** derived from this software without specific prior written permission.
-**
-** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR 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. */
+/* Copyright information is at end of file */
#include "xmlrpc_config.h"
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
-#include <xmlparse.h>
+
+#include <xmlparse.h> /* Expat */
+
+#include "bool.h"
#include "xmlrpc-c/base.h"
#include "xmlrpc-c/base_int.h"
+#include "xmlrpc-c/string_int.h"
#include "xmlrpc-c/xmlparser.h"
/* Define the contents of our internal structure. */
@@ -64,8 +45,10 @@
** arguments are implementation-dependent.
*/
-static xml_element *xml_element_new (xmlrpc_env *env, char *name)
-{
+static xml_element *
+xml_element_new (xmlrpc_env * const env,
+ const char * const name) {
+
xml_element *retval;
int name_valid, cdata_valid, children_valid;
@@ -79,7 +62,7 @@
/* Allocate our xml_element structure. */
retval = (xml_element*) malloc(sizeof(xml_element));
XMLRPC_FAIL_IF_NULL(retval, env, XMLRPC_INTERNAL_ERROR,
- "Couldn't allocate memory for XML element");
+ "Couldn't allocate memory for XML element");
/* Set our parent field to NULL. */
retval->_parent = NULL;
@@ -87,7 +70,7 @@
/* Copy over the element name. */
retval->_name = (char*) malloc(strlen(name) + 1);
XMLRPC_FAIL_IF_NULL(retval->_name, env, XMLRPC_INTERNAL_ERROR,
- "Couldn't allocate memory for XML element");
+ "Couldn't allocate memory for XML element");
name_valid = 1;
strcpy(retval->_name, name);
@@ -103,18 +86,18 @@
cleanup:
if (env->fault_occurred) {
- if (retval) {
- if (name_valid)
- free(retval->_name);
- if (cdata_valid)
- xmlrpc_mem_block_clean(&retval->_cdata);
- if (children_valid)
- xmlrpc_mem_block_clean(&retval->_children);
- free(retval);
- }
- return NULL;
+ if (retval) {
+ if (name_valid)
+ free(retval->_name);
+ if (cdata_valid)
+ xmlrpc_mem_block_clean(&retval->_cdata);
+ if (children_valid)
+ xmlrpc_mem_block_clean(&retval->_children);
+ free(retval);
+ }
+ return NULL;
} else {
- return retval;
+ return retval;
}
}
@@ -124,9 +107,9 @@
**=========================================================================
** Blow away an existing element & all of its child elements.
*/
+void
+xml_element_free(xml_element * const elem) {
-void xml_element_free (xml_element *elem)
-{
xmlrpc_mem_block *children;
int size, i;
xml_element **contents;
@@ -142,7 +125,7 @@
contents = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(xml_element*, children);
size = XMLRPC_TYPED_MEM_BLOCK_SIZE(xml_element*, children);
for (i = 0; i < size; i++)
- xml_element_free(contents[i]);
+ xml_element_free(contents[i]);
xmlrpc_mem_block_clean(&elem->_children);
free(elem);
@@ -156,12 +139,17 @@
** documentation on each function works.
*/
-char *xml_element_name (xml_element *elem)
-{
- XMLRPC_ASSERT_ELEM_OK(elem);
- return elem->_name;
+
+
+const char *
+xml_element_name(const xml_element * const elemP) {
+
+ XMLRPC_ASSERT_ELEM_OK(elemP);
+ return elemP->_name;
}
+
+
/* The result of this function is NOT VALID until the end_element handler
** has been called! */
size_t xml_element_cdata_size (xml_element *elem)
@@ -176,28 +164,33 @@
return XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, &elem->_cdata);
}
-size_t xml_element_children_size (xml_element *elem)
-{
- XMLRPC_ASSERT_ELEM_OK(elem);
- return XMLRPC_TYPED_MEM_BLOCK_SIZE(xml_element*, &elem->_children);
+
+
+size_t
+xml_element_children_size(const xml_element * const elemP) {
+ XMLRPC_ASSERT_ELEM_OK(elemP);
+ return XMLRPC_TYPED_MEM_BLOCK_SIZE(xml_element *, &elemP->_children);
}
-xml_element **xml_element_children (xml_element *elem)
-{
- XMLRPC_ASSERT_ELEM_OK(elem);
- return XMLRPC_TYPED_MEM_BLOCK_CONTENTS(xml_element*, &elem->_children);
+
+
+xml_element **
+xml_element_children(const xml_element * const elemP) {
+ XMLRPC_ASSERT_ELEM_OK(elemP);
+ return XMLRPC_TYPED_MEM_BLOCK_CONTENTS(xml_element *, &elemP->_children);
}
+
/*=========================================================================
** Internal xml_element Utility Functions
**=========================================================================
*/
static void xml_element_append_cdata (xmlrpc_env *env,
- xml_element *elem,
- char *cdata,
- size_t size)
+ xml_element *elem,
+ char *cdata,
+ size_t size)
{
XMLRPC_ASSERT_ENV_OK(env);
XMLRPC_ASSERT_ELEM_OK(elem);
@@ -210,8 +203,8 @@
** WARNING - This is the exact opposite of the usual memory ownership
** rules for xmlrpc_value! So please pay attention. */
static void xml_element_append_child (xmlrpc_env *env,
- xml_element *elem,
- xml_element *child)
+ xml_element *elem,
+ xml_element *child)
{
XMLRPC_ASSERT_ENV_OK(env);
XMLRPC_ASSERT_ELEM_OK(elem);
@@ -221,7 +214,7 @@
XMLRPC_TYPED_MEM_BLOCK_APPEND(xml_element*, env, &elem->_children,
&child, 1);
if (!env->fault_occurred)
- child->_parent = elem;
+ child->_parent = elem;
else
xml_element_free(child);
}
@@ -233,10 +226,10 @@
*/
typedef struct {
- xmlrpc_env *env;
- xml_element *root;
- xml_element *current;
-} parse_context;
+ xmlrpc_env env;
+ xml_element * rootP;
+ xml_element * currentP;
+} parseContext;
/*=========================================================================
@@ -245,151 +238,250 @@
*/
static void
-start_element (void *user_data, XML_Char *name, XML_Char **atts ATTR_UNUSED)
-{
- parse_context *context;
- xml_element *elem, *new_current;
+startElement(void * const userData,
+ XML_Char * const name,
+ XML_Char ** const atts ATTR_UNUSED) {
- XMLRPC_ASSERT(user_data != NULL && name != NULL);
+ parseContext * const contextP = userData;
- /* Get our context and see if an error has already occured. */
- context = (parse_context*) user_data;
- if (!context->env->fault_occurred) {
-
- /* Set up our error-handling preconditions. */
- elem = NULL;
-
- /* Build a new element. */
- elem = xml_element_new(context->env, name);
- XMLRPC_FAIL_IF_FAULT(context->env);
-
- /* Insert it in the appropriate place. */
- if (!context->root) {
- context->root = elem;
- context->current = elem;
- elem = NULL;
- } else {
- XMLRPC_ASSERT(context->current != NULL);
-
- /* (We need to watch our error handling invariants very carefully
- ** here. Read the docs for xml_element_append_child. */
- new_current = elem;
- xml_element_append_child(context->env, context->current, elem);
- elem = NULL;
- XMLRPC_FAIL_IF_FAULT(context->env);
- context->current = new_current;
- }
+ XMLRPC_ASSERT(contextP != NULL);
+ XMLRPC_ASSERT(name != NULL);
- cleanup:
- if (elem)
- xml_element_free(elem);
+ if (!contextP->env.fault_occurred) {
+ xml_element * elemP;
+
+ elemP = xml_element_new(&contextP->env, name);
+ if (!contextP->env.fault_occurred) {
+ XMLRPC_ASSERT(elemP != NULL);
+
+ /* Insert the new element in the appropriate place. */
+ if (!contextP->rootP) {
+ /* No root yet, so this element must be the root. */
+ contextP->rootP = elemP;
+ contextP->currentP = elemP;
+ } else {
+ XMLRPC_ASSERT(contextP->currentP != NULL);
+
+ /* (We need to watch our error handling invariants
+ very carefully here. Read the docs for
+ xml_element_append_child.
+ */
+ xml_element_append_child(&contextP->env, contextP->currentP,
+ elemP);
+ if (!contextP->env.fault_occurred)
+ contextP->currentP = elemP;
+ }
+ if (contextP->env.fault_occurred)
+ xml_element_free(elemP);
+ }
+ if (contextP->env.fault_occurred) {
+ /* Having changed *contextP to reflect failure, we are responsible
+ for undoing everything that has been done so far in this
+ context.
+ */
+ if (contextP->rootP)
+ xml_element_free(contextP->rootP);
+ }
}
}
-static void end_element (void *user_data, XML_Char *name)
-{
- parse_context *context;
- XMLRPC_ASSERT(user_data != NULL && name != NULL);
- /* Get our context and see if an error has already occured. */
- context = (parse_context*) user_data;
- if (!context->env->fault_occurred) {
-
- /* XXX - I think expat enforces these facts, but I want to be sure.
- ** If one of these assertion ever fails, it should be replaced by a
- ** non-assertion runtime error check. */
- XMLRPC_ASSERT(strcmp(name, context->current->_name) == 0);
- XMLRPC_ASSERT(context->current->_parent != NULL ||
- context->current == context->root);
-
- /* Add a trailing '\0' to our cdata. */
- xml_element_append_cdata(context->env, context->current, "\0", 1);
- XMLRPC_FAIL_IF_FAULT(context->env);
+static void
+endElement(void * const userData,
+ XML_Char * const name ATTR_UNUSED) {
+
+ parseContext * const contextP = userData;
- /* Pop our "stack" of elements. */
- context->current = context->current->_parent;
+ XMLRPC_ASSERT(contextP != NULL);
+ XMLRPC_ASSERT(name != NULL);
- cleanup:
- return;
+ if (!contextP->env.fault_occurred) {
+ /* I think Expat enforces these facts: */
+ XMLRPC_ASSERT(xmlrpc_streq(name, contextP->currentP->_name));
+ XMLRPC_ASSERT(contextP->currentP->_parent != NULL ||
+ contextP->currentP == contextP->rootP);
+
+ /* Add a trailing NUL to our cdata. */
+ xml_element_append_cdata(&contextP->env, contextP->currentP, "\0", 1);
+ if (!contextP->env.fault_occurred)
+ /* Pop our "stack" of elements. */
+ contextP->currentP = contextP->currentP->_parent;
+
+ if (contextP->env.fault_occurred) {
+ /* Having changed *contextP to reflect failure, we are responsible
+ for undoing everything that has been done so far in this
+ context.
+ */
+ if (contextP->rootP)
+ xml_element_free(contextP->rootP);
+ }
}
}
-static void character_data (void *user_data, XML_Char *s, int len)
-{
- parse_context *context;
- XMLRPC_ASSERT(user_data != NULL && s != NULL && len >= 0);
- /* Get our context and see if an error has already occured. */
- context = (parse_context*) user_data;
- if (!context->env->fault_occurred) {
-
- XMLRPC_ASSERT(context->current != NULL);
-
- xml_element_append_cdata(context->env, context->current, s, len);
- XMLRPC_FAIL_IF_FAULT(context->env);
+static void
+characterData(void * const userData,
+ XML_Char * const s,
+ int const len) {
+/*----------------------------------------------------------------------------
+ This is an Expat character data (cdata) handler. When an Expat
+ parser comes across cdata, he calls one of these with the cdata as
+ argument. He can call it multiple times for consecutive cdata.
+
+ We simply append the cdata to the cdata buffer for whatever XML
+ element the parser is presently parsing.
+-----------------------------------------------------------------------------*/
+ parseContext * const contextP = userData;
+
+ XMLRPC_ASSERT(contextP != NULL);
+ XMLRPC_ASSERT(s != NULL);
+ XMLRPC_ASSERT(len >= 0);
- cleanup:
- return;
+ if (!contextP->env.fault_occurred) {
+ XMLRPC_ASSERT(contextP->currentP != NULL);
+
+ xml_element_append_cdata(&contextP->env, contextP->currentP, s, len);
}
}
-/*=========================================================================
-** Expat Driver
-**=========================================================================
-** XXX - We should allow the user to specify the encoding of our xml_data.
-*/
-xml_element *xml_parse (xmlrpc_env *env, const char *xml_data, int xml_len)
-{
- parse_context context;
+static void
+createParser(xmlrpc_env * const envP,
+ parseContext * const contextP,
+ XML_Parser * const parserP) {
+/*----------------------------------------------------------------------------
+ Create an Expat parser to parse our XML.
+-----------------------------------------------------------------------------*/
XML_Parser parser;
- int ok;
- XMLRPC_ASSERT_ENV_OK(env);
- XMLRPC_ASSERT(xml_data != NULL && xml_len >= 0);
+ parser = xmlrpc_XML_ParserCreate(NULL);
+ if (parser == NULL)
+ xmlrpc_faultf(envP, "Could not create expat parser");
+ else {
+ /* Initialize our parse context. */
+ xmlrpc_env_init(&contextP->env);
+ contextP->rootP = NULL;
+ contextP->currentP = NULL;
+
+ xmlrpc_XML_SetUserData(parser, contextP);
+ xmlrpc_XML_SetElementHandler(
+ parser,
+ (XML_StartElementHandler) startElement,
+ (XML_EndElementHandler) endElement);
+ xmlrpc_XML_SetCharacterDataHandler(
+ parser,
+ (XML_CharacterDataHandler) characterData);
+
+ *parserP = parser;
+ }
+}
- /* Set up our error-handling preconditions. */
- parser = NULL;
- context.root = NULL;
-
- /* Set up the rest of our parse context. */
- context.env = env;
- context.current = NULL;
-
- /* Set up our XML parser. */
- parser = XML_ParserCreate(NULL);
- XMLRPC_FAIL_IF_NULL(parser, env, XMLRPC_INTERNAL_ERROR,
- "Could not create expat parser");
- XML_SetUserData(parser, &context);
- XML_SetElementHandler(parser,
- (XML_StartElementHandler) start_element,
- (XML_EndElementHandler) end_element);
- XML_SetCharacterDataHandler(parser,
- (XML_CharacterDataHandler) character_data);
-
- /* Parse our data. */
- ok = XML_Parse(parser, xml_data, xml_len, 1);
- if (!ok)
- XMLRPC_FAIL(env, XMLRPC_PARSE_ERROR,
- (char*) XML_ErrorString(XML_GetErrorCode(parser)));
- XMLRPC_FAIL_IF_FAULT(env);
- /* Perform some sanity checks. */
- XMLRPC_ASSERT(context.root != NULL);
- XMLRPC_ASSERT(context.current == NULL);
- cleanup:
- if (parser)
- XML_ParserFree(parser);
+static void
+destroyParser(XML_Parser const parser,
+ parseContext * const contextP) {
- if (env->fault_occurred) {
- if (context.root)
- xml_element_free(context.root);
- return NULL;
- } else {
- return context.root;
+ xmlrpc_env_clean(&contextP->env);
+
+ xmlrpc_XML_ParserFree(parser);
+}
+
+
+
+void
+xml_parse(xmlrpc_env * const envP,
+ const char * const xmlData,
+ size_t const xmlDataLen,
+ xml_element ** const resultPP) {
+/*----------------------------------------------------------------------------
+ Parse the XML text 'xmlData', of length 'xmlDataLen'. Return the
+ description of the element that the XML text contains as *resultPP.
+-----------------------------------------------------------------------------*/
+ /*
+ This is an Expat driver.
+
+ We set up event-based parser handlers for Expat and set Expat loose
+ on the XML. Expat walks through the XML, calling our handlers along
+ the way. Our handlers build up the element description in our
+ 'context' variable, so that when Expat is finished, our results are
+ in 'context' and we just have to pluck them out.
+
+ We should allow the user to specify the encoding in 'xmlData', but
+ we don't.
+ */
+ XML_Parser parser;
+ parseContext context;
+
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT(xmlData != NULL);
+
+ createParser(envP, &context, &parser);
+
+ if (!envP->fault_occurred) {
+ bool ok;
+
+ ok = xmlrpc_XML_Parse(parser, xmlData, xmlDataLen, 1);
+ /* sets 'context', *envP */
+ if (!ok) {
+ /* Expat failed on its own to parse it -- this is not an error
+ that our handlers detected.
+ */
+ xmlrpc_env_set_fault(
+ envP, XMLRPC_PARSE_ERROR,
+ xmlrpc_XML_GetErrorString(parser));
+ if (!context.env.fault_occurred) {
+ /* Have to clean up what our handlers built before Expat
+ barfed.
+ */
+ if (context.rootP)
+ xml_element_free(context.rootP);
+ }
+ } else {
+ /* Expat got through the XML OK, but when it called our handlers,
+ they might have detected a problem. They would have noted
+ such a problem in *contextP.
+ */
+ if (context.env.fault_occurred)
+ xmlrpc_env_set_fault_formatted(
+ envP, context.env.fault_code,
+ "XML doesn't parse. %s", context.env.fault_string);
+ else {
+ XMLRPC_ASSERT(context.rootP != NULL);
+ XMLRPC_ASSERT(context.currentP == NULL);
+
+ *resultPP = context.rootP;
+ }
+ }
+ destroyParser(parser, &context);
}
}
+
+
+/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR 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. */
Modified: freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_libxml2.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_libxml2.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_libxml2.c Fri May 23 16:56:24 2008
@@ -30,7 +30,11 @@
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
+#ifdef WIN32
+#include <xmlparser.h>
+#else
#include <libxml/parser.h>
+#endif
#include "xmlrpc-c/base.h"
#include "xmlrpc-c/base_int.h"
@@ -147,7 +151,7 @@
** documentation on each function works.
*/
-char *xml_element_name (xml_element *elem)
+const char *xml_element_name (const xml_element * const elem)
{
XMLRPC_ASSERT_ELEM_OK(elem);
return elem->_name;
@@ -167,13 +171,13 @@
return XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, &elem->_cdata);
}
-size_t xml_element_children_size (xml_element *elem)
+size_t xml_element_children_size (const xml_element *const elem)
{
XMLRPC_ASSERT_ELEM_OK(elem);
return XMLRPC_TYPED_MEM_BLOCK_SIZE(xml_element*, &elem->_children);
}
-xml_element **xml_element_children (xml_element *elem)
+xml_element **xml_element_children (const xml_element *const elem)
{
XMLRPC_ASSERT_ELEM_OK(elem);
return XMLRPC_TYPED_MEM_BLOCK_CONTENTS(xml_element*, &elem->_children);
@@ -372,47 +376,52 @@
NULL /* serror */
};
-xml_element *xml_parse (xmlrpc_env *env, const char *xml_data, int xml_len)
-{
+
+
+void
+xml_parse(xmlrpc_env * const envP,
+ const char * const xmlData,
+ size_t const xmlDataLen,
+ xml_element ** const resultPP) {
+
parse_context context;
xmlParserCtxt *parser;
int err;
- XMLRPC_ASSERT_ENV_OK(env);
- XMLRPC_ASSERT(xml_data != NULL && xml_len >= 0);
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT(xmlData != NULL && xmlDataLen >= 0);
/* Set up our error-handling preconditions. */
parser = NULL;
context.root = NULL;
/* Set up the rest of our parse context. */
- context.env = env;
+ context.env = envP;
context.current = NULL;
/* Set up our XML parser. */
parser = xmlCreatePushParserCtxt(&sax_handler, &context, NULL, 0, NULL);
- XMLRPC_FAIL_IF_NULL(parser, env, XMLRPC_INTERNAL_ERROR,
- "Could not create expat parser");
+ XMLRPC_FAIL_IF_NULL(parser, envP, XMLRPC_INTERNAL_ERROR,
+ "Could not create expat parser");
/* Parse our data. */
- err = xmlParseChunk(parser, xml_data, xml_len, 1);
+ err = xmlParseChunk(parser, xmlData, xmlDataLen, 1);
if (err)
- XMLRPC_FAIL(env, XMLRPC_PARSE_ERROR, "XML parsing failed");
- XMLRPC_FAIL_IF_FAULT(env);
+ XMLRPC_FAIL(envP, XMLRPC_PARSE_ERROR, "XML parsing failed");
+ XMLRPC_FAIL_IF_FAULT(envP);
/* Perform some sanity checks. */
XMLRPC_ASSERT(context.root != NULL);
XMLRPC_ASSERT(context.current == NULL);
+ *resultPP = context.root;
+
cleanup:
if (parser)
xmlFreeParserCtxt(parser);
- if (env->fault_occurred) {
+ if (envP->fault_occurred) {
if (context.root)
xml_element_free(context.root);
- return NULL;
- } else {
- return context.root;
}
}
Modified: freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_parse.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_parse.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_parse.c Fri May 23 16:56:24 2008
@@ -1,27 +1,4 @@
-/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
-**
-** Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions
-** are met:
-** 1. Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** 2. Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in the
-** documentation and/or other materials provided with the distribution.
-** 3. The name of the author may not be used to endorse or promote products
-** derived from this software without specific prior written permission.
-**
-** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR 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. */
+/* Copyright information is at end of file. */
#include "xmlrpc_config.h"
@@ -30,44 +7,34 @@
#include <string.h>
#include <errno.h>
#include <ctype.h>
+#include <limits.h>
+
+#include "bool.h"
#include "xmlrpc-c/base.h"
#include "xmlrpc-c/base_int.h"
+#include "xmlrpc-c/string_int.h"
+#include "xmlrpc-c/util.h"
#include "xmlrpc-c/xmlparser.h"
+#include "parse_value.h"
-/*=========================================================================
-** Data Format
-**=========================================================================
-** All XML-RPC documents contain a single methodCall or methodResponse
-** element.
-**
-** methodCall methodName, params
-** methodResponse (params|fault)
-** params param*
-** param value
-** fault value
-** value (i4|int|boolean|string|double|dateTime.iso8601|base64|
-** nil|struct|array)
-** array data
-** data value*
-** struct member*
-** member name, value
-**
-** Contain CDATA: methodName, i4, int, boolean, string, double,
-** dateTime.iso8601, base64, name
-**
-** We attempt to validate the structure of the XML document carefully.
-** We also try *very* hard to handle malicious data gracefully, and without
-** leaking memory.
-**
-** The CHECK_NAME and CHECK_CHILD_COUNT macros examine an XML element, and
-** invoke XMLRPC_FAIL if something looks wrong.
+/* Notes about XML-RPC XML documents:
+
+ Contain CDATA: methodName, i4, int, boolean, string, double,
+ dateTime.iso8601, base64, name
+
+ We attempt to validate the structure of the XML document carefully.
+ We also try *very* hard to handle malicious data gracefully, and without
+ leaking memory.
+
+ The CHECK_NAME and CHECK_CHILD_COUNT macros examine an XML element, and
+ invoke XMLRPC_FAIL if something looks wrong.
*/
#define CHECK_NAME(env,elem,name) \
do \
- if (strcmp((name), xml_element_name(elem)) != 0) \
+ if (!xmlrpc_streq((name), xml_element_name(elem))) \
XMLRPC_FAIL2(env, XMLRPC_PARSE_ERROR, \
"Expected element of type <%s>, found <%s>", \
(name), xml_element_name(elem)); \
@@ -91,7 +58,7 @@
children = xml_element_children(parent);
child_count = xml_element_children_size(parent);
for (i = 0; i < child_count; i++) {
- if (0 == strcmp(xml_element_name(children[i]), name))
+ if (xmlrpc_streq(xml_element_name(children[i]), name))
return children[i];
}
@@ -102,694 +69,565 @@
}
+
+static void
+setParseFault(xmlrpc_env * const envP,
+ const char * const format,
+ ...) {
+
+ va_list args;
+ va_start(args, format);
+ xmlrpc_set_fault_formatted_v(envP, XMLRPC_PARSE_ERROR, format, args);
+ va_end(args);
+}
+
+
+
/*=========================================================================
-** Number-Parsing Functions
+** convert_params
**=========================================================================
-** These functions mirror atoi, atof, etc., but provide better
-** error-handling. These routines may reset errno to zero.
+** Convert an XML element representing a list of params into an
+** xmlrpc_value (of type array).
*/
-static xmlrpc_int32
-xmlrpc_atoi(xmlrpc_env *env, char *str, size_t strlen,
- xmlrpc_int32 min, xmlrpc_int32 max)
-{
- long i;
- char *end;
+static xmlrpc_value *
+convert_params(xmlrpc_env * const envP,
+ const xml_element * const elemP) {
+/*----------------------------------------------------------------------------
+ Convert an XML element representing a list of parameters (i.e. a
+ <params> element) to an xmlrpc_value of type array. Note that an
+ array is normally represented in XML by a <value> element. We use
+ type xmlrpc_value to represent the parameter list just for convenience.
+-----------------------------------------------------------------------------*/
+ xmlrpc_value *array, *item;
+ int size, i;
+ xml_element **params, *param, *value;
- XMLRPC_ASSERT_ENV_OK(env);
- XMLRPC_ASSERT_PTR_OK(str);
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT(elemP != NULL);
- /* Suppress compiler warnings. */
- i = 0;
+ /* Set up our error-handling preconditions. */
+ array = item = NULL;
- /* Check for leading white space. */
- if (isspace(str[0]))
- XMLRPC_FAIL1(env, XMLRPC_PARSE_ERROR,
- "\"%s\" must not contain whitespace", str);
-
- /* Convert the value. */
- end = str + strlen;
- errno = 0;
- i = strtol(str, &end, 10);
-
- /* Look for ERANGE. */
- if (errno != 0)
- /* XXX - Do all operating systems have thread-safe strerror? */
- XMLRPC_FAIL3(env, XMLRPC_PARSE_ERROR,
- "error parsing \"%s\": %s (%d)",
- str, strerror(errno), errno);
-
- /* Look for out-of-range errors which didn't produce ERANGE. */
- if (i < min || i > max)
- XMLRPC_FAIL3(env, XMLRPC_PARSE_ERROR,
- "\"%s\" must be in range %d to %d", str, min, max);
-
- /* Check for unused characters. */
- if (end != str + strlen)
- XMLRPC_FAIL1(env, XMLRPC_PARSE_ERROR,
- "\"%s\" contained trailing data", str);
-
- cleanup:
- errno = 0;
- if (env->fault_occurred)
- return 0;
- return (xmlrpc_int32) i;
-}
+ /* Allocate an array to hold our parameters. */
+ array = xmlrpc_build_value(envP, "()");
+ XMLRPC_FAIL_IF_FAULT(envP);
+ /* We're responsible for checking our own element name. */
+ CHECK_NAME(envP, elemP, "params");
+ /* Iterate over our children. */
+ size = xml_element_children_size(elemP);
+ params = xml_element_children(elemP);
+ for (i = 0; i < size; ++i) {
+ unsigned int const maxNest = xmlrpc_limit_get(XMLRPC_NESTING_LIMIT_ID);
-static double
-xmlrpc_atod(xmlrpc_env *env, char *str, size_t strlen)
-{
- double d;
- char *end;
+ param = params[i];
+ CHECK_NAME(envP, param, "param");
+ CHECK_CHILD_COUNT(envP, param, 1);
- XMLRPC_ASSERT_ENV_OK(env);
- XMLRPC_ASSERT_PTR_OK(str);
+ value = xml_element_children(param)[0];
- /* Suppress compiler warnings. */
- d = 0.0;
+ CHECK_NAME(envP, value, "value");
- /* Check for leading white space. */
- if (isspace(str[0]))
- XMLRPC_FAIL1(env, XMLRPC_PARSE_ERROR,
- "\"%s\" must not contain whitespace", str);
-
- /* Convert the value. */
- end = str + strlen;
- errno = 0;
- d = strtod(str, &end);
-
- /* Look for ERANGE. */
- if (errno != 0)
- /* XXX - Do all operating systems have thread-safe strerror? */
- XMLRPC_FAIL3(env, XMLRPC_PARSE_ERROR,
- "error parsing \"%s\": %s (%d)",
- str, strerror(errno), errno);
-
- /* Check for unused characters. */
- if (end != str + strlen)
- XMLRPC_FAIL1(env, XMLRPC_PARSE_ERROR,
- "\"%s\" contained trailing data", str);
+ xmlrpc_parseValue(envP, maxNest, value, &item);
+ XMLRPC_FAIL_IF_FAULT(envP);
+
+ xmlrpc_array_append_item(envP, array, item);
+ xmlrpc_DECREF(item);
+ item = NULL;
+ XMLRPC_FAIL_IF_FAULT(envP);
+ }
cleanup:
- errno = 0;
- if (env->fault_occurred)
- return 0.0;
- return d;
+ if (envP->fault_occurred) {
+ if (array)
+ xmlrpc_DECREF(array);
+ if (item)
+ xmlrpc_DECREF(item);
+ return NULL;
+ }
+ return array;
}
-/*=========================================================================
-** make_string
-**=========================================================================
-** Make an XML-RPC string.
-**
-** SECURITY: We validate our UTF-8 first. This incurs a performance
-** penalty, but ensures that we will never pass maliciously malformed
-** UTF-8 data back up to the user layer, where it could wreak untold
-** damange. Don't comment out this check unless you know *exactly* what
-** you're doing. (Win32 developers who remove this check are *begging*
-** to wind up on BugTraq, because many of the Win32 filesystem routines
-** rely on an insecure UTF-8 decoder.)
-**
-** XXX - This validation is redundant if the user chooses to convert
-** UTF-8 data into a wchar_t string.
-*/
-static xmlrpc_value *
-make_string(xmlrpc_env *env, char *cdata, size_t cdata_size)
-{
-#ifdef HAVE_UNICODE_WCHAR
- xmlrpc_validate_utf8(env, cdata, cdata_size);
-#endif
+static void
+parseCallXml(xmlrpc_env * const envP,
+ const char * const xmlData,
+ size_t const xmlLen,
+ xml_element ** const callElemPP) {
+/*----------------------------------------------------------------------------
+ Parse the XML of an XML-RPC call.
+-----------------------------------------------------------------------------*/
+ xml_element * callElemP;
+ xmlrpc_env env;
- if (env->fault_occurred)
- return NULL;
- return xmlrpc_build_value(env, "s#", cdata, cdata_size);
-}
+ xmlrpc_env_init(&env);
+ xml_parse(&env, xmlData, xmlLen, &callElemP);
+ if (env.fault_occurred)
+ xmlrpc_env_set_fault_formatted(
+ envP, env.fault_code, "Call is not valid XML. %s",
+ env.fault_string);
+ else {
+ if (!xmlrpc_streq(xml_element_name(callElemP), "methodCall"))
+ setParseFault(envP,
+ "XML-RPC call should be a <methodCall> element. "
+ "Instead, we have a <%s> element.",
+ xml_element_name(callElemP));
+ if (!envP->fault_occurred)
+ *callElemPP = callElemP;
+ if (envP->fault_occurred)
+ xml_element_free(callElemP);
+ }
+ xmlrpc_env_clean(&env);
+}
-/*=========================================================================
-** convert_value
-**=======================================================================*/
-static xmlrpc_value *
-convert_array (xmlrpc_env *env, unsigned *depth, xml_element *elem);
-static xmlrpc_value *
-convert_struct(xmlrpc_env *env, unsigned *depth, xml_element *elem);
+
+static void
+parseMethodNameElement(xmlrpc_env * const envP,
+ xml_element * const nameElemP,
+ const char ** const methodNameP) {
+
+ XMLRPC_ASSERT(xmlrpc_streq(xml_element_name(nameElemP), "methodName"));
+
+ if (xml_element_children_size(nameElemP) > 0)
+ setParseFault(envP, "A <methodName> element should not have "
+ "children. This one has %u of them.",
+ xml_element_children_size(nameElemP));
+ else {
+ const char * const cdata = xml_element_cdata(nameElemP);
+
+ xmlrpc_validate_utf8(envP, cdata, strlen(cdata));
+
+ if (!envP->fault_occurred) {
+ *methodNameP = strdup(cdata);
+ if (*methodNameP == NULL)
+ xmlrpc_faultf(envP,
+ "Could not allocate memory for method name");
+ }
+ }
+}
static void
-convertBase64(xmlrpc_env * const envP,
- const char * const cdata,
- size_t const cdata_size,
- xmlrpc_value ** const valuePP) {
+parseCallChildren(xmlrpc_env * const envP,
+ xml_element * const callElemP,
+ const char ** const methodNameP,
+ xmlrpc_value ** const paramArrayPP ) {
+/*----------------------------------------------------------------------------
+ Parse the children of a <methodCall> XML element *callElemP. They should
+ be <methodName> and <params>.
+-----------------------------------------------------------------------------*/
+ size_t const callChildCount = xml_element_children_size(callElemP);
+
+ xml_element * nameElemP;
+
+ XMLRPC_ASSERT(xmlrpc_streq(xml_element_name(callElemP), "methodCall"));
- xmlrpc_mem_block *decoded;
+ nameElemP = get_child_by_name(envP, callElemP, "methodName");
- decoded = xmlrpc_base64_decode(envP, cdata, cdata_size);
if (!envP->fault_occurred) {
- unsigned char * const asciiData =
- XMLRPC_MEMBLOCK_CONTENTS(unsigned char, decoded);
- size_t const asciiLen =
- XMLRPC_MEMBLOCK_SIZE(unsigned char, decoded);
-
- *valuePP = xmlrpc_build_value(envP, "6", asciiData, asciiLen);
-
- XMLRPC_MEMBLOCK_FREE(unsigned char, decoded);
+ parseMethodNameElement(envP, nameElemP, methodNameP);
+
+ if (!envP->fault_occurred) {
+ /* Convert our parameters. */
+ if (callChildCount > 1) {
+ xml_element * paramsElemP;
+
+ paramsElemP = get_child_by_name(envP, callElemP, "params");
+
+ if (!envP->fault_occurred)
+ *paramArrayPP = convert_params(envP, paramsElemP);
+ } else {
+ /* Workaround for Ruby XML-RPC and old versions of
+ xmlrpc-epi. Future improvement: Instead of looking
+ at child count, we should just check for existence
+ of <params>.
+ */
+ *paramArrayPP = xmlrpc_array_new(envP);
+ }
+ if (!envP->fault_occurred) {
+ if (callChildCount > 2)
+ setParseFault(envP, "<methodCall> has extraneous "
+ "children, other than <methodName> and "
+ "<params>. Total child count = %u",
+ callChildCount);
+
+ if (envP->fault_occurred)
+ xmlrpc_DECREF(*paramArrayPP);
+ }
+ if (envP->fault_occurred)
+ xmlrpc_strfree(*methodNameP);
+ }
}
}
-static xmlrpc_value *
-convert_value(xmlrpc_env * const envP,
- unsigned * const depthP,
- xml_element * const elem) {
+void
+xmlrpc_parse_call(xmlrpc_env * const envP,
+ const char * const xmlData,
+ size_t const xmlLen,
+ const char ** const methodNameP,
+ xmlrpc_value ** const paramArrayPP) {
/*----------------------------------------------------------------------------
- Compute the xmlrpc_value represented by the XML <value> element 'elem'.
- Return that xmlrpc_value.
-
- Assume we are running at recursion depth *depthP. (TODO: this is a
- modularity violation. We have to replace this with a "maximum
- depth" argument that tells how much additional recursion depth
- we're allowed to use).
+ Given some XML text, attempt to parse it as an XML-RPC call.
+ Return as *methodNameP the name of the method identified in the call
+ and as *paramArrayPP the parameter list as an XML-RPC array.
+ Caller must free() and xmlrpc_DECREF() these, respectively).
-----------------------------------------------------------------------------*/
- int child_count;
- char * child_name;
- xmlrpc_value *retval;
-
XMLRPC_ASSERT_ENV_OK(envP);
- XMLRPC_ASSERT(elem != NULL);
+ XMLRPC_ASSERT(xmlData != NULL);
+ XMLRPC_ASSERT(methodNameP != NULL && paramArrayPP != NULL);
- /* Error-handling precoditions.
- ** If we haven't changed any of these from their default state, we're
- ** allowed to tail-call xmlrpc_build_value. */
- retval = NULL;
-
- /* Make sure we haven't recursed too deeply. */
- if (*depthP > xmlrpc_limit_get(XMLRPC_NESTING_LIMIT_ID))
- XMLRPC_FAIL(envP, XMLRPC_PARSE_ERROR,
- "Nested data structure too deep.");
-
- /* Validate our structure, and see whether we have a child element. */
- CHECK_NAME(envP, elem, "value");
- child_count = xml_element_children_size(elem);
-
- if (child_count == 0) {
- /* We have no type element, so treat the value as a string. */
- char * const cdata = xml_element_cdata(elem);
- size_t const cdata_size = xml_element_cdata_size(elem);
- retval = make_string(envP, cdata, cdata_size);
- } else {
- /* We should have a type tag inside our value tag. */
- xml_element *child;
-
- CHECK_CHILD_COUNT(envP, elem, 1);
- child = xml_element_children(elem)[0];
-
- /* Parse our value-containing element. */
- child_name = xml_element_name(child);
- if (strcmp(child_name, "struct") == 0) {
- retval = convert_struct(envP, depthP, child);
- } else if (strcmp(child_name, "array") == 0) {
- CHECK_CHILD_COUNT(envP, child, 1);
- retval = convert_array(envP, depthP, child);
- } else {
- char * cdata;
- size_t cdata_size;
-
- CHECK_CHILD_COUNT(envP, child, 0);
- cdata = xml_element_cdata(child);
- cdata_size = xml_element_cdata_size(child);
- if (strcmp(child_name, "i4") == 0 ||
- strcmp(child_name, "int") == 0) {
- xmlrpc_int32 const i =
- xmlrpc_atoi(envP, cdata, strlen(cdata),
- XMLRPC_INT32_MIN, XMLRPC_INT32_MAX);
- XMLRPC_FAIL_IF_FAULT(envP);
- retval = xmlrpc_build_value(envP, "i", i);
- } else if (strcmp(child_name, "string") == 0) {
- retval = make_string(envP, cdata, cdata_size);
- } else if (strcmp(child_name, "boolean") == 0) {
- xmlrpc_int32 const i =
- xmlrpc_atoi(envP, cdata, strlen(cdata), 0, 1);
- XMLRPC_FAIL_IF_FAULT(envP);
- retval = xmlrpc_build_value(envP, "b", (xmlrpc_bool) i);
- } else if (strcmp(child_name, "double") == 0) {
- double const d = xmlrpc_atod(envP, cdata, strlen(cdata));
- XMLRPC_FAIL_IF_FAULT(envP);
- retval = xmlrpc_build_value(envP, "d", d);
- } else if (strcmp(child_name, "dateTime.iso8601") == 0) {
- retval = xmlrpc_build_value(envP, "8", cdata);
- } else if (strcmp(child_name, "nil") == 0) {
- retval = xmlrpc_build_value(envP, "n");
- } else if (strcmp(child_name, "base64") == 0) {
- /* No more tail calls once we do this! */
+ /* SECURITY: Last-ditch attempt to make sure our content length is
+ legal. XXX - This check occurs too late to prevent an attacker
+ from creating an enormous memory block, so you should try to
+ enforce it *before* reading any data off the network.
+ */
+ if (xmlLen > xmlrpc_limit_get(XMLRPC_XML_SIZE_LIMIT_ID))
+ xmlrpc_env_set_fault_formatted(
+ envP, XMLRPC_LIMIT_EXCEEDED_ERROR,
+ "XML-RPC request too large. Max allowed is %u bytes",
+ xmlrpc_limit_get(XMLRPC_XML_SIZE_LIMIT_ID));
+ else {
+ xml_element * callElemP;
+ parseCallXml(envP, xmlData, xmlLen, &callElemP);
+ if (!envP->fault_occurred) {
+ parseCallChildren(envP, callElemP, methodNameP, paramArrayPP);
- convertBase64(envP, cdata, cdata_size, &retval);
- if (envP->fault_occurred)
- /* Just for cleanup code: */
- retval = NULL;
- } else {
- XMLRPC_FAIL1(envP, XMLRPC_PARSE_ERROR,
- "Unknown value type -- XML element is named "
- "<%s>", child_name);
- }
+ xml_element_free(callElemP);
}
}
-
- cleanup:
if (envP->fault_occurred) {
- if (retval)
- xmlrpc_DECREF(retval);
- retval = NULL;
+ /* Should not be necessary, but for backward compatibility: */
+ *methodNameP = NULL;
+ *paramArrayPP = NULL;
}
- return retval;
}
-/*=========================================================================
-** convert_array
-**=========================================================================
-** Convert an XML element representing an array into an xmlrpc_value.
-*/
-
-static xmlrpc_value *
-convert_array(xmlrpc_env *env, unsigned *depth, xml_element *elem)
-{
- xml_element *data, **values, *value;
- xmlrpc_value *array, *item;
- int size, i;
-
- XMLRPC_ASSERT_ENV_OK(env);
- XMLRPC_ASSERT(elem != NULL);
-
- /* Set up our error-handling preconditions. */
- array = item = NULL;
- (*depth)++;
-
- /* Allocate an array to hold our values. */
- array = xmlrpc_build_value(env, "()");
- XMLRPC_FAIL_IF_FAULT(env);
-
- /* We don't need to check our element name--our callers do that. */
- CHECK_CHILD_COUNT(env, elem, 1);
- data = xml_element_children(elem)[0];
- CHECK_NAME(env, data, "data");
-
- /* Iterate over our children. */
- values = xml_element_children(data);
- size = xml_element_children_size(data);
- for (i = 0; i < size; i++) {
- value = values[i];
- item = convert_value(env, depth, value);
- XMLRPC_FAIL_IF_FAULT(env);
-
- xmlrpc_array_append_item(env, array, item);
- xmlrpc_DECREF(item);
- item = NULL;
- XMLRPC_FAIL_IF_FAULT(env);
- }
+static void
+interpretFaultCode(xmlrpc_env * const envP,
+ xmlrpc_value * const faultCodeVP,
+ int * const faultCodeP) {
+
+ xmlrpc_env fcEnv;
+ xmlrpc_env_init(&fcEnv);
+
+ xmlrpc_read_int(&fcEnv, faultCodeVP, faultCodeP);
+ if (fcEnv.fault_occurred)
+ xmlrpc_faultf(envP, "Invalid value for 'faultCode' member. %s",
+ fcEnv.fault_string);
- cleanup:
- (*depth)--;
- if (item)
- xmlrpc_DECREF(item);
- if (env->fault_occurred) {
- if (array)
- xmlrpc_DECREF(array);
- return NULL;
- }
- return array;
+ xmlrpc_env_clean(&fcEnv);
}
-/*=========================================================================
-** convert_struct
-**=========================================================================
-** Convert an XML element representing a struct into an xmlrpc_value.
-*/
+static void
+interpretFaultString(xmlrpc_env * const envP,
+ xmlrpc_value * const faultStringVP,
+ const char ** const faultStringP) {
-static xmlrpc_value *
-convert_struct(xmlrpc_env *env, unsigned *depth, xml_element *elem)
-{
- xmlrpc_value *strct, *key, *value;
- xml_element **members, *member, *name_elem, *value_elem;
- int size, i;
- char *cdata;
- size_t cdata_size;
+ xmlrpc_env fsEnv;
+ xmlrpc_env_init(&fsEnv);
- XMLRPC_ASSERT_ENV_OK(env);
- XMLRPC_ASSERT(elem != NULL);
+ xmlrpc_read_string(&fsEnv, faultStringVP, faultStringP);
- /* Set up our error-handling preconditions. */
- strct = key = value = NULL;
- (*depth)++;
+ if (fsEnv.fault_occurred)
+ xmlrpc_faultf(envP, "Invalid value for 'faultString' member. %s",
+ fsEnv.fault_string);
- /* Allocate an array to hold our members. */
- strct = xmlrpc_struct_new(env);
- XMLRPC_FAIL_IF_FAULT(env);
-
- /* Iterate over our children, extracting key/value pairs. */
- /* We don't need to check our element name--our callers do that. */
- members = xml_element_children(elem);
- size = xml_element_children_size(elem);
- for (i = 0; i < size; i++) {
- member = members[i];
- CHECK_NAME(env, member, "member");
- CHECK_CHILD_COUNT(env, member, 2);
-
- /* Get our key. */
- name_elem = get_child_by_name(env, member, "name");
- XMLRPC_FAIL_IF_FAULT(env);
- CHECK_CHILD_COUNT(env, name_elem, 0);
- cdata = xml_element_cdata(name_elem);
- cdata_size = xml_element_cdata_size(name_elem);
- key = make_string(env, cdata, cdata_size);
- XMLRPC_FAIL_IF_FAULT(env);
-
- /* Get our value. */
- value_elem = get_child_by_name(env, member, "value");
- XMLRPC_FAIL_IF_FAULT(env);
- value = convert_value(env, depth, value_elem);
- XMLRPC_FAIL_IF_FAULT(env);
-
- /* Add the key/value pair to our struct. */
- xmlrpc_struct_set_value_v(env, strct, key, value);
- XMLRPC_FAIL_IF_FAULT(env);
-
- /* Release our references & memory, and restore our invariants. */
- xmlrpc_DECREF(key);
- key = NULL;
- xmlrpc_DECREF(value);
- value = NULL;
- }
-
- cleanup:
- (*depth)--;
- if (key)
- xmlrpc_DECREF(key);
- if (value)
- xmlrpc_DECREF(value);
- if (env->fault_occurred) {
- if (strct)
- xmlrpc_DECREF(strct);
- return NULL;
- }
- return strct;
+ xmlrpc_env_clean(&fsEnv);
}
-/*=========================================================================
-** convert_params
-**=========================================================================
-** Convert an XML element representing a list of params into an
-** xmlrpc_value (of type array).
-*/
-
-static xmlrpc_value *
-convert_params(xmlrpc_env *env, unsigned *depth, xml_element *elem)
-{
- xmlrpc_value *array, *item;
- int size, i;
- xml_element **params, *param, *value;
-
- XMLRPC_ASSERT_ENV_OK(env);
- XMLRPC_ASSERT(elem != NULL);
-
- /* Set up our error-handling preconditions. */
- array = item = NULL;
+static void
+interpretFaultValue(xmlrpc_env * const envP,
+ xmlrpc_value * const faultVP,
+ int * const faultCodeP,
+ const char ** const faultStringP) {
+
+ if (faultVP->_type != XMLRPC_TYPE_STRUCT)
+ setParseFault(envP,
+ "<value> element of <fault> response is not "
+ "of structure type");
+ else {
+ xmlrpc_value * faultCodeVP;
+ xmlrpc_env fvEnv;
+
+ xmlrpc_env_init(&fvEnv);
+
+ xmlrpc_struct_read_value(&fvEnv, faultVP, "faultCode", &faultCodeVP);
+ if (!fvEnv.fault_occurred) {
+ interpretFaultCode(&fvEnv, faultCodeVP, faultCodeP);
+
+ if (!fvEnv.fault_occurred) {
+ xmlrpc_value * faultStringVP;
+
+ xmlrpc_struct_read_value(&fvEnv, faultVP, "faultString",
+ &faultStringVP);
+ if (!fvEnv.fault_occurred) {
+ interpretFaultString(&fvEnv, faultStringVP, faultStringP);
- /* Allocate an array to hold our parameters. */
- array = xmlrpc_build_value(env, "()");
- XMLRPC_FAIL_IF_FAULT(env);
+ xmlrpc_DECREF(faultStringVP);
+ }
+ }
+ xmlrpc_DECREF(faultCodeVP);
+ }
+ if (fvEnv.fault_occurred)
+ setParseFault(envP, "Invalid struct for <fault> value. %s",
+ fvEnv.fault_string);
- /* We're responsible for checking our own element name. */
- CHECK_NAME(env, elem, "params");
+ xmlrpc_env_clean(&fvEnv);
+ }
+}
- /* Iterate over our children. */
- size = xml_element_children_size(elem);
- params = xml_element_children(elem);
- for (i = 0; i < size; i++) {
- param = params[i];
- CHECK_NAME(env, param, "param");
- CHECK_CHILD_COUNT(env, param, 1);
- value = xml_element_children(param)[0];
- item = convert_value(env, depth, value);
- XMLRPC_FAIL_IF_FAULT(env);
- xmlrpc_array_append_item(env, array, item);
- xmlrpc_DECREF(item);
- item = NULL;
- XMLRPC_FAIL_IF_FAULT(env);
- }
+static void
+parseFaultElement(xmlrpc_env * const envP,
+ const xml_element * const faultElement,
+ int * const faultCodeP,
+ const char ** const faultStringP) {
+
+ unsigned int const maxRecursion =
+ xmlrpc_limit_get(XMLRPC_NESTING_LIMIT_ID);
+
+ XMLRPC_ASSERT(xmlrpc_streq(xml_element_name(faultElement), "fault"));
+
+ if (xml_element_children_size(faultElement) != 1)
+ setParseFault(envP, "<fault> element should have 1 child, "
+ "but it has %u.",
+ xml_element_children_size(faultElement));
+ else {
+ xml_element * const faultValueP =
+ xml_element_children(faultElement)[0];
+ const char * const elemName = xml_element_name(faultValueP);
+
+ if (!xmlrpc_streq(elemName, "value"))
+ setParseFault(envP,
+ "<fault> contains a <%s> element. "
+ "Only <value> makes sense.",
+ elemName);
+ else {
+ xmlrpc_value * faultVP;
- cleanup:
- if (env->fault_occurred) {
- if (array)
- xmlrpc_DECREF(array);
- if (item)
- xmlrpc_DECREF(item);
- return NULL;
+ xmlrpc_parseValue(envP, maxRecursion, faultValueP, &faultVP);
+
+ if (!envP->fault_occurred) {
+ interpretFaultValue(envP, faultVP, faultCodeP, faultStringP);
+
+ xmlrpc_DECREF(faultVP);
+ }
+ }
}
- return array;
}
static void
-parseCallXml(xmlrpc_env * const envP,
- const char * const xmlData,
- size_t const xmlLen,
- xml_element ** const callElemP) {
+parseParamsElement(xmlrpc_env * const envP,
+ const xml_element * const paramsElementP,
+ xmlrpc_value ** const resultPP) {
+ xmlrpc_value * paramsVP;
xmlrpc_env env;
xmlrpc_env_init(&env);
- *callElemP = xml_parse(&env, xmlData, xmlLen);
- if (env.fault_occurred)
- xmlrpc_env_set_fault_formatted(
- envP, env.fault_code, "Call is not valid XML. %s",
- env.fault_string);
- xmlrpc_env_clean(&env);
-}
+ XMLRPC_ASSERT(xmlrpc_streq(xml_element_name(paramsElementP), "params"));
+ paramsVP = convert_params(envP, paramsElementP);
-/*=========================================================================
-** xmlrpc_parse_call
-**=========================================================================
-** Given some XML text, attempt to parse it as an XML-RPC call. Return
-** a newly allocated xmlrpc_call structure (or NULL, if an error occurs).
-** The two output variables will contain either valid values (which
-** must free() and xmlrpc_DECREF(), respectively) or NULLs (if an error
-** occurs).
-*/
-
-void
-xmlrpc_parse_call(xmlrpc_env * const envP,
- const char * const xml_data,
- size_t const xml_len,
- const char ** const out_method_nameP,
- xmlrpc_value ** const out_param_arrayPP) {
-
- xml_element *call_elem, *name_elem, *params_elem;
- char *cdata;
- unsigned depth;
- size_t call_child_count;
- char * outMethodName;
- xmlrpc_value * outParamArrayP;
+ if (!envP->fault_occurred) {
+ int arraySize;
+ xmlrpc_env sizeEnv;
- XMLRPC_ASSERT_ENV_OK(envP);
- XMLRPC_ASSERT(xml_data != NULL);
- XMLRPC_ASSERT(out_method_nameP != NULL && out_param_arrayPP != NULL);
+ XMLRPC_ASSERT_ARRAY_OK(paramsVP);
+
+ xmlrpc_env_init(&sizeEnv);
- /* Set up our error-handling preconditions. */
- outMethodName = NULL;
- outParamArrayP = NULL;
- call_elem = NULL;
+ arraySize = xmlrpc_array_size(&sizeEnv, paramsVP);
+ /* Since it's a valid array, as asserted above, can't fail */
+ XMLRPC_ASSERT(!sizeEnv.fault_occurred);
+
+ if (arraySize != 1)
+ setParseFault(envP, "Contains %d items. It should have 1.",
+ arraySize);
+ else {
+ xmlrpc_array_read_item(envP, paramsVP, 0, resultPP);
+ }
+ xmlrpc_DECREF(paramsVP);
+ xmlrpc_env_clean(&sizeEnv);
+ }
+ if (env.fault_occurred)
+ xmlrpc_env_set_fault_formatted(
+ envP, env.fault_code,
+ "Invalid <params> element. %s", env.fault_string);
- /* SECURITY: Last-ditch attempt to make sure our content length is legal.
- ** XXX - This check occurs too late to prevent an attacker from creating
- ** an enormous memory block in RAM, so you should try to enforce it
- ** *before* reading any data off the network. */
- if (xml_len > xmlrpc_limit_get(XMLRPC_XML_SIZE_LIMIT_ID))
- XMLRPC_FAIL(envP, XMLRPC_LIMIT_EXCEEDED_ERROR,
- "XML-RPC request too large");
+ xmlrpc_env_clean(&env);
+}
- parseCallXml(envP, xml_data, xml_len, &call_elem);
- XMLRPC_FAIL_IF_FAULT(envP);
- /* Pick apart and verify our structure. */
- CHECK_NAME(envP, call_elem, "methodCall");
- call_child_count = xml_element_children_size(call_elem);
- if (call_child_count != 2 && call_child_count != 1)
- XMLRPC_FAIL1(envP, XMLRPC_PARSE_ERROR,
- "Expected <methodCall> to have 1 or 2 children, found %d",
- call_child_count);
-
- /* Extract the method name.
- ** SECURITY: We make sure the method name is valid UTF-8. */
- name_elem = get_child_by_name(envP, call_elem, "methodName");
- XMLRPC_FAIL_IF_FAULT(envP);
- CHECK_CHILD_COUNT(envP, name_elem, 0);
- cdata = xml_element_cdata(name_elem);
-#ifdef HAVE_UNICODE_WCHAR
- xmlrpc_validate_utf8(envP, cdata, strlen(cdata));
- XMLRPC_FAIL_IF_FAULT(envP);
-#endif /* HAVE_UNICODE_WCHAR */
- outMethodName = malloc(strlen(cdata) + 1);
- XMLRPC_FAIL_IF_NULL(outMethodName, envP, XMLRPC_INTERNAL_ERROR,
- "Could not allocate memory for method name");
- strcpy(outMethodName, cdata);
-
- /* Convert our parameters. */
- if (call_child_count == 1) {
- /* Workaround for Ruby XML-RPC and old versions of xmlrpc-epi. */
- outParamArrayP = xmlrpc_build_value(envP, "()");
- XMLRPC_FAIL_IF_FAULT(envP);
- } else {
- params_elem = get_child_by_name(envP, call_elem, "params");
- XMLRPC_FAIL_IF_FAULT(envP);
- depth = 0;
- outParamArrayP = convert_params(envP, &depth, params_elem);
- XMLRPC_ASSERT(depth == 0);
- XMLRPC_FAIL_IF_FAULT(envP);
- }
-cleanup:
- if (call_elem)
- xml_element_free(call_elem);
- if (envP->fault_occurred) {
- if (outMethodName)
- free(outMethodName);
- if (outParamArrayP)
- xmlrpc_DECREF(outParamArrayP);
- outMethodName = NULL;
- outParamArrayP = NULL;
- }
- *out_method_nameP = outMethodName;
- *out_param_arrayPP = outParamArrayP;
+static void
+parseMethodResponseElt(xmlrpc_env * const envP,
+ const xml_element * const methodResponseEltP,
+ xmlrpc_value ** const resultPP,
+ int * const faultCodeP,
+ const char ** const faultStringP) {
+
+ XMLRPC_ASSERT(xmlrpc_streq(xml_element_name(methodResponseEltP),
+ "methodResponse"));
+
+ if (xml_element_children_size(methodResponseEltP) == 1) {
+ xml_element * const child =
+ xml_element_children(methodResponseEltP)[0];
+
+ if (xmlrpc_streq(xml_element_name(child), "params")) {
+ /* It's a successful response */
+ parseParamsElement(envP, child, resultPP);
+ *faultStringP = NULL;
+ } else if (xmlrpc_streq(xml_element_name(child), "fault")) {
+ /* It's a failure response */
+ parseFaultElement(envP, child, faultCodeP, faultStringP);
+ } else
+ setParseFault(envP,
+ "<methodResponse> must contain <params> or <fault>, "
+ "but contains <%s>.", xml_element_name(child));
+ } else
+ setParseFault(envP,
+ "<methodResponse> has %u children, should have 1.",
+ xml_element_children_size(methodResponseEltP));
}
-/*=========================================================================
-** xmlrpc_parse_response
-**=========================================================================
-** Given some XML text, attempt to parse it as an XML-RPC response.
-** If the response is a regular, valid response, return a new reference
-** to the appropriate value. If the response is a fault, or an error
-** occurs during processing, return NULL and set up env appropriately.
-*/
+void
+xmlrpc_parse_response2(xmlrpc_env * const envP,
+ const char * const xmlData,
+ size_t const xmlDataLen,
+ xmlrpc_value ** const resultPP,
+ int * const faultCodeP,
+ const char ** const faultStringP) {
+/*----------------------------------------------------------------------------
+ Given some XML text, attempt to parse it as an XML-RPC response.
-xmlrpc_value *
-xmlrpc_parse_response(xmlrpc_env *env,
- const char *xml_data,
- size_t xml_len) {
-
- xml_element *response, *child, *value;
- unsigned depth;
- xmlrpc_value *params, *retval, *fault;
- int retval_incremented;
-
- xmlrpc_value *fault_code_value, *fault_str_value;
- xmlrpc_int32 fault_code;
- char *fault_str;
+ If the response is a regular, valid response, return a new reference
+ to the appropriate value as *resultP and return NULL as
+ *faultStringP and nothing as *faultCodeP.
+
+ If the response is valid, but indicates a failure of the RPC, return the
+ fault string in newly malloc'ed space as *faultStringP and the fault
+ code as *faultCodeP and nothing as *resultP.
- XMLRPC_ASSERT_ENV_OK(env);
- XMLRPC_ASSERT(xml_data != NULL);
+ If the XML text is not a valid response or something prevents us from
+ parsing it, return a description of the error as *envP and nothing else.
+-----------------------------------------------------------------------------*/
+ xml_element * response;
- /* Set up our error-handling preconditions. */
- response = NULL;
- params = fault = NULL;
- retval_incremented = 0;
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT(xmlData != NULL);
/* SECURITY: Last-ditch attempt to make sure our content length is legal.
** XXX - This check occurs too late to prevent an attacker from creating
- ** an enormous memory block in RAM, so you should try to enforce it
+ ** an enormous memory block, so you should try to enforce it
** *before* reading any data off the network. */
- if (xml_len > xmlrpc_limit_get(XMLRPC_XML_SIZE_LIMIT_ID))
- XMLRPC_FAIL(env, XMLRPC_LIMIT_EXCEEDED_ERROR,
- "XML-RPC response too large");
-
- /* SECURITY: Set up our recursion depth counter. */
- depth = 0;
-
- /* Parse our XML data. */
- response = xml_parse(env, xml_data, xml_len);
- XMLRPC_FAIL_IF_FAULT(env);
-
- /* Pick apart and verify our structure. */
- CHECK_NAME(env, response, "methodResponse");
- CHECK_CHILD_COUNT(env, response, 1);
- child = xml_element_children(response)[0];
-
- /* Parse the response itself. */
- if (strcmp("params", xml_element_name(child)) == 0) {
-
- /* Convert our parameter list. */
- params = convert_params(env, &depth, child);
- XMLRPC_FAIL_IF_FAULT(env);
-
- /* Extract the return value, and jiggle our reference counts. */
- xmlrpc_parse_value(env, params, "(V)", &retval);
- XMLRPC_FAIL_IF_FAULT(env);
- xmlrpc_INCREF(retval);
- retval_incremented = 1;
-
- } else if (strcmp("fault", xml_element_name(child)) == 0) {
-
- /* Convert our fault structure. */
- CHECK_CHILD_COUNT(env, child, 1);
- value = xml_element_children(child)[0];
- fault = convert_value(env, &depth, value);
- XMLRPC_FAIL_IF_FAULT(env);
- XMLRPC_TYPE_CHECK(env, fault, XMLRPC_TYPE_STRUCT);
-
- /* Get our fault code. */
- fault_code_value = xmlrpc_struct_get_value(env, fault, "faultCode");
- XMLRPC_FAIL_IF_FAULT(env);
- xmlrpc_parse_value(env, fault_code_value, "i", &fault_code);
- XMLRPC_FAIL_IF_FAULT(env);
-
- /* Get our fault string. */
- fault_str_value = xmlrpc_struct_get_value(env, fault, "faultString");
- XMLRPC_FAIL_IF_FAULT(env);
- xmlrpc_parse_value(env, fault_str_value, "s", &fault_str);
- XMLRPC_FAIL_IF_FAULT(env);
-
- /* Return our fault. */
- XMLRPC_FAIL(env, fault_code, fault_str);
-
- } else {
- XMLRPC_FAIL(env, XMLRPC_PARSE_ERROR,
- "Expected <params> or <fault> in <methodResponse>");
+ if (xmlDataLen > xmlrpc_limit_get(XMLRPC_XML_SIZE_LIMIT_ID))
+ xmlrpc_env_set_fault_formatted(
+ envP, XMLRPC_LIMIT_EXCEEDED_ERROR,
+ "XML-RPC response too large. Our limit is %u characters. "
+ "We got %u characters",
+ xmlrpc_limit_get(XMLRPC_XML_SIZE_LIMIT_ID), xmlDataLen);
+ else {
+ xmlrpc_env env;
+ xmlrpc_env_init(&env);
+
+ xml_parse(&env, xmlData, xmlDataLen, &response);
+
+ if (env.fault_occurred)
+ setParseFault(envP, "Not valid XML. %s", env.fault_string);
+ else {
+ /* Pick apart and verify our structure. */
+ if (xmlrpc_streq(xml_element_name(response), "methodResponse")) {
+ parseMethodResponseElt(envP, response,
+ resultPP, faultCodeP, faultStringP);
+ } else
+ setParseFault(envP, "XML-RPC response must consist of a "
+ "<methodResponse> element. "
+ "This has a <%s> instead.",
+ xml_element_name(response));
+
+ xml_element_free(response);
+ }
+ xmlrpc_env_clean(&env);
}
+}
+
+
- /* Sanity-check our depth-counting code. */
- XMLRPC_ASSERT(depth == 0);
+xmlrpc_value *
+xmlrpc_parse_response(xmlrpc_env * const envP,
+ const char * const xmlData,
+ size_t const xmlDataLen) {
+/*----------------------------------------------------------------------------
+ This exists for backward compatibility. It is like
+ xmlrpc_parse_response2(), except that it merges the concepts of a
+ failed RPC and an error in executing the RPC.
+-----------------------------------------------------------------------------*/
+ xmlrpc_value * retval;
+ xmlrpc_value * result;
+ const char * faultString;
+ int faultCode;
+
+ xmlrpc_parse_response2(envP, xmlData, xmlDataLen,
+ &result, &faultCode, &faultString);
-cleanup:
- if (response)
- xml_element_free(response);
- if (params)
- xmlrpc_DECREF(params);
- if (fault)
- xmlrpc_DECREF(fault);
-
- if (env->fault_occurred) {
- if (retval_incremented)
- xmlrpc_DECREF(retval);
- return NULL;
+ if (envP->fault_occurred)
+ retval = NULL;
+ else {
+ if (faultString) {
+ xmlrpc_env_set_fault(envP, faultCode, faultString);
+ xmlrpc_strfree(faultString);
+ retval = NULL;
+ } else
+ retval = result; /* transfer reference */
}
return retval;
}
+
+
+
+/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR 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. */
Modified: freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_serialize.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_serialize.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_serialize.c Fri May 23 16:56:24 2008
@@ -1,246 +1,246 @@
-/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
-**
-** Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions
-** are met:
-** 1. Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** 2. Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in the
-** documentation and/or other materials provided with the distribution.
-** 3. The name of the author may not be used to endorse or promote products
-** derived from this software without specific prior written permission.
-**
-** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR 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. */
+/* Copyright information is at end of file */
+
+/* Implementation note:
+
+ The printf format specifiers we use appear to be entirely standard,
+ except for the "long long" one, which is %I64 on Windows and %lld
+ everywhere else. So for that, we use the C99 standard macro PRId64,
+ which is defined by inttypes.h. Ironically, Windows doesn't have
+ inttypes.h either, but we have int.h instead.
+*/
#include "xmlrpc_config.h"
+#include <assert.h>
#include <stddef.h>
#include <stdarg.h>
+#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <float.h>
+#include "int.h"
#include "xmlrpc-c/base.h"
#include "xmlrpc-c/base_int.h"
+#include "xmlrpc-c/string_int.h"
+#include "double.h"
#define CRLF "\015\012"
#define SMALL_BUFFER_SZ (128)
#define XML_PROLOGUE "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"CRLF
-/*=========================================================================
-** format_out
-**=========================================================================
-** A lightweight print routine for use with various serialization
-** functions. Only use this routine for printing small objects--it uses
-** a fixed-size internal buffer and returns an error on overflow.
-** In particular, do NOT use this routine to print XML-RPC string values!
-*/
+static void
+addString(xmlrpc_env * const envP,
+ xmlrpc_mem_block * const outputP,
+ const char * const string) {
+
+ XMLRPC_MEMBLOCK_APPEND(char, envP, outputP, string, strlen(string));
+}
+
+
static void
-format_out(xmlrpc_env *env,
- xmlrpc_mem_block *output,
- char *format_string,
- ...) {
+formatOut(xmlrpc_env * const envP,
+ xmlrpc_mem_block * const outputP,
+ const char * const formatString,
+ ...) {
+/*----------------------------------------------------------------------------
+ A lightweight print routine for use with various serialization
+ functions.
+ Use this routine only for printing small objects -- it uses a
+ fixed-size internal buffer and returns an error on overflow. In
+ particular, do NOT use this routine to print XML-RPC string values!
+-----------------------------------------------------------------------------*/
va_list args;
char buffer[SMALL_BUFFER_SZ];
int count;
- XMLRPC_ASSERT_ENV_OK(env);
+ XMLRPC_ASSERT_ENV_OK(envP);
- va_start(args, format_string);
+ va_start(args, formatString);
- /* We assume that this function is present and works correctly. Right. */
- count = vsnprintf(buffer, SMALL_BUFFER_SZ, format_string, args);
+ count = XMLRPC_VSNPRINTF(buffer, SMALL_BUFFER_SZ, formatString, args);
/* Old C libraries return -1 if vsnprintf overflows its buffer.
** New C libraries return the number of characters which *would* have
** been printed if the error did not occur. This is impressively vile.
** Thank the C99 committee for this bright idea. But wait! We also
- ** need to keep track of the trailing NULL. */
- if (count < 0 || count >= (SMALL_BUFFER_SZ - 1))
- XMLRPC_FAIL(env, XMLRPC_INTERNAL_ERROR,
- "format_out overflowed internal buffer");
+ ** need to keep track of the trailing NUL. */
- /* Append our new data to our output. */
- XMLRPC_TYPED_MEM_BLOCK_APPEND(char, env, output, buffer, count);
- XMLRPC_FAIL_IF_FAULT(env);
+ if (count < 0 || count >= (SMALL_BUFFER_SZ - 1))
+ xmlrpc_faultf(envP, "formatOut() overflowed internal buffer");
+ else
+ XMLRPC_MEMBLOCK_APPEND(char, envP, outputP, buffer, count);
-cleanup:
va_end(args);
}
-/*=========================================================================
-** Warnings About Invalid UTF-8
-**=========================================================================
-** We claim to send UTF-8 data to the network. But we rely on application
-** programs to pass us correctly-formed UTF-8 data, which is very naive
-** and optimistic.
-**
-** In debudding mode, we call this routine to issue dire-sounding
-** warnings. For the sake of safety, this routine never exits the
-** program or does anything else drastic.
-**
-** This routine almost certainly slows down our output.
-*/
-
-#if !defined NDEBUG && defined HAVE_UNICODE_WCHAR
static void
-sanity_check_utf8(const char * const str,
- size_t const len) {
-
+assertValidUtf8(const char * const str ATTR_UNUSED,
+ size_t const len ATTR_UNUSED) {
+/*----------------------------------------------------------------------------
+ Assert that the string 'str' of length 'len' is valid UTF-8.
+-----------------------------------------------------------------------------*/
+#if !defined NDEBUG
+ /* Check the assertion; if it's false, issue a message to
+ Standard Error, but otherwise ignore it.
+ */
xmlrpc_env env;
xmlrpc_env_init(&env);
xmlrpc_validate_utf8(&env, str, len);
if (env.fault_occurred)
fprintf(stderr, "*** xmlrpc-c WARNING ***: %s (%s)\n",
- "Application sending corrupted UTF-8 data to network",
+ "Xmlrpc-c sending corrupted UTF-8 data to network",
env.fault_string);
xmlrpc_env_clean(&env);
-}
#endif
+}
-/*=========================================================================
-** Escaping Strings
-**=========================================================================
-*/
+static size_t
+escapedSize(const char * const chars,
+ size_t const len) {
+
+ size_t size;
+ size_t i;
-static xmlrpc_mem_block *
-escape_string(xmlrpc_env * const env,
- const char * const str,
- size_t const len) {
-
- xmlrpc_mem_block *retval;
- size_t i, needed;
- char *out;
-
- XMLRPC_ASSERT_ENV_OK(env);
- XMLRPC_ASSERT(str != NULL);
-
- /* Set up our error-handling preconditions. */
- retval = NULL;
-
- /* Sanity-check this string before we print it. */
-#if !defined NDEBUG && defined HAVE_UNICODE_WCHAR
- sanity_check_utf8(str, len);
-#endif
-
- /* Calculate the amount of space we'll need. */
- needed = 0;
- for (i = 0; i < len; i++) {
- if (str[i] == '<')
- needed += 4; /* < */
- else if (str[i] == '>')
- needed += 4; /* > */
- else if (str[i] == '&')
- needed += 5; /* & */
+ size = 0;
+ for (i = 0; i < len; ++i) {
+ if (chars[i] == '<')
+ size += 4; /* < */
+ else if (chars[i] == '>')
+ size += 4; /* > */
+ else if (chars[i] == '&')
+ size += 5; /* & */
+ else if (chars[i] == '\r')
+ size += 6; /* 
 */
else
- needed++;
+ size += 1;
}
+ return size;
+}
- /* Allocate our memory block. */
- retval = XMLRPC_TYPED_MEM_BLOCK_NEW(char, env, needed);
- XMLRPC_FAIL_IF_FAULT(env);
-
- /* Copy over the newly-allocated data. */
- out = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, retval);
- for (i = 0; i < len; i++) {
- if (str[i] == '<') {
- *out++ = '&';
- *out++ = 'l';
- *out++ = 't';
- *out++ = ';';
- } else if (str[i] == '>') {
- *out++ = '&';
- *out++ = 'g';
- *out++ = 't';
- *out++ = ';';
- } else if (str[i] == '&') {
- *out++ = '&';
- *out++ = 'a';
- *out++ = 'm';
- *out++ = 'p';
- *out++ = ';';
- } else {
- *out++ = str[i];
- }
- }
- cleanup:
- if (env->fault_occurred) {
- if (retval)
- XMLRPC_TYPED_MEM_BLOCK_FREE(char, retval);
- retval = NULL;
- }
- return retval;
-}
+static void
+escapeForXml(xmlrpc_env * const envP,
+ const char * const chars,
+ size_t const len,
+ xmlrpc_mem_block ** const outputPP) {
+/*----------------------------------------------------------------------------
+ Escape & and < in a UTF-8 string so as to make it suitable for the
+ content of an XML element. I.e. turn them into entity references
+ & and <.
+
+ Also change > to >, even though not required for XML, for
+ symmetry.
+
+ < etc. are known in XML as "entity references."
+
+ Also Escape CR as 
 . While raw CR _is_ allowed in the content
+ of an XML element, it has a special meaning -- it means line ending.
+ Our input uses LF for for line endings. Since it also means line ending
+ in XML, we just pass it through to our output like it were a regular
+ character.
+
+ 
 is known in XML as a "character reference."
+
+ We assume chars[] is is ASCII. That isn't right -- we should
+ handle all valid UTF-8. Someday, we must do something more complex
+ and copy over multibyte characters verbatim. (The code here could
+ erroneously find that e.g. the 2nd byte of a UTF-8 character is a
+ CR).
+-----------------------------------------------------------------------------*/
+ xmlrpc_mem_block * outputP;
+ size_t outputSize;
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT(chars != NULL);
-static xmlrpc_mem_block*
-escape_block (xmlrpc_env *env,
- xmlrpc_mem_block *block) {
+ assertValidUtf8(chars, len);
- XMLRPC_ASSERT_ENV_OK(env);
- XMLRPC_ASSERT(block != NULL);
+ /* Note that in UTF-8, any byte that has high bit of zero is a
+ character all by itself (every byte of a multi-byte UTF-8 character
+ has the high bit set). Also, the Unicode code points < 128 are
+ identical to the ASCII ones.
+ */
- return escape_string(env,
- XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, block),
- XMLRPC_TYPED_MEM_BLOCK_SIZE(char, block));
-}
+ outputSize = escapedSize(chars, len);
+ outputP = XMLRPC_MEMBLOCK_NEW(char, envP, outputSize);
+ if (!envP->fault_occurred) {
+ char * p;
+ size_t i;
+ p = XMLRPC_MEMBLOCK_CONTENTS(char, outputP); /* Start at beginning */
+
+ for (i = 0; i < len; i++) {
+ if (chars[i] == '<') {
+ memcpy(p, "<", 4);
+ p += 4;
+ } else if (chars[i] == '>') {
+ memcpy(p, ">", 4);
+ p += 4;
+ } else if (chars[i] == '&') {
+ memcpy(p, "&", 5);
+ p += 5;
+ } else if (chars[i] == '\r') {
+ memcpy(p, "
", 6);
+ p += 6;
+ } else {
+ /* Either a plain character or a LF line delimiter */
+ *p = chars[i];
+ p += 1;
+ }
+ }
+ *outputPP = outputP;
+ assert(p == XMLRPC_MEMBLOCK_CONTENTS(char, outputP) + outputSize);
+
+ if (envP->fault_occurred)
+ XMLRPC_MEMBLOCK_FREE(char, outputP);
+ }
+}
-/*=========================================================================
-** xmlrpc_serialize_string_data
-**=========================================================================
-** Escape and print the contents of a string.
-*/
static void
-xmlrpc_serialize_string_data(xmlrpc_env *env,
- xmlrpc_mem_block *output,
- xmlrpc_value *string) {
+serializeUtf8MemBlock(xmlrpc_env * const envP,
+ xmlrpc_mem_block * const outputP,
+ xmlrpc_mem_block * const inputP) {
+/*----------------------------------------------------------------------------
+ Append the characters in *inputP to the XML stream in *outputP.
- xmlrpc_mem_block *escaped;
- char *contents;
- size_t size;
+ *inputP contains Unicode characters in UTF-8.
- /* Since this routine can only be called internally, we only need
- ** an assertion here, not a runtime type check.
- ** XXX - Temporarily disabled because we're using this code to
- ** print <dateTime.iso8601> values as well. */
- /* XMLRPC_ASSERT(string->_type == XMLRPC_TYPE_STRING); */
-
- /* Escape any '&' and '<' characters in the string. */
- escaped = escape_block(env, &string->_block);
- XMLRPC_FAIL_IF_FAULT(env);
- contents = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, escaped);
- size = XMLRPC_TYPED_MEM_BLOCK_SIZE(char, escaped) - 1;
-
- /* Print the string. */
- XMLRPC_TYPED_MEM_BLOCK_APPEND(char, env, output, contents, size);
- XMLRPC_FAIL_IF_FAULT(env);
+ We assume *inputP ends with a NUL character that marks end of
+ string, and we ignore that. (There might also be NUL characters
+ inside the string, though).
+-----------------------------------------------------------------------------*/
+ xmlrpc_mem_block * escapedP;
+
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT(outputP != NULL);
+ XMLRPC_ASSERT(inputP != NULL);
+
+ escapeForXml(envP,
+ XMLRPC_MEMBLOCK_CONTENTS(const char, inputP),
+ XMLRPC_MEMBLOCK_SIZE(const char, inputP) - 1,
+ /* -1 is for the terminating NUL */
+ &escapedP);
+ if (!envP->fault_occurred) {
+ const char * const contents =
+ XMLRPC_MEMBLOCK_CONTENTS(const char, escapedP);
+ size_t const size = XMLRPC_MEMBLOCK_SIZE(char, escapedP);
- cleanup:
- if (escaped)
- XMLRPC_TYPED_MEM_BLOCK_FREE(char, escaped);
+ XMLRPC_MEMBLOCK_APPEND(char, envP, outputP, contents, size);
+
+ XMLRPC_MEMBLOCK_FREE(const char, escapedP);
+ }
}
@@ -271,43 +271,43 @@
-/*=========================================================================
-** xmlrpc_serialize_struct
-**=========================================================================
-** Dump the contents of a struct.
-*/
-
static void
-xmlrpc_serialize_struct(xmlrpc_env *env,
- xmlrpc_mem_block *output,
- xmlrpc_value *strct) {
-
+serializeStruct(xmlrpc_env * const envP,
+ xmlrpc_mem_block * const outputP,
+ xmlrpc_value * const structP,
+ xmlrpc_dialect const dialect) {
+/*----------------------------------------------------------------------------
+ Add to *outputP the content of a <value> element to represent
+ the structure value *valueP. I.e. "<struct> ... </struct>".
+-----------------------------------------------------------------------------*/
size_t size;
size_t i;
- xmlrpc_value *key, *value;
+ xmlrpc_value * memberKeyP;
+ xmlrpc_value * memberValueP;
- format_out(env, output, "<struct>"CRLF);
- XMLRPC_FAIL_IF_FAULT(env);
+ addString(envP, outputP, "<struct>"CRLF);
+ XMLRPC_FAIL_IF_FAULT(envP);
- size = xmlrpc_struct_size(env, strct);
- XMLRPC_FAIL_IF_FAULT(env);
- for (i = 0; i < size; i++) {
- xmlrpc_struct_get_key_and_value(env, strct, i, &key, &value);
- XMLRPC_FAIL_IF_FAULT(env);
- format_out(env, output, "<member><name>");
- XMLRPC_FAIL_IF_FAULT(env);
- xmlrpc_serialize_string_data(env, output, key);
- XMLRPC_FAIL_IF_FAULT(env);
- format_out(env, output, "</name>"CRLF);
- XMLRPC_FAIL_IF_FAULT(env);
- xmlrpc_serialize_value(env, output, value);
- XMLRPC_FAIL_IF_FAULT(env);
- format_out(env, output, "</member>"CRLF);
- XMLRPC_FAIL_IF_FAULT(env);
+ size = xmlrpc_struct_size(envP, structP);
+ XMLRPC_FAIL_IF_FAULT(envP);
+ for (i = 0; i < size; ++i) {
+ xmlrpc_struct_get_key_and_value(envP, structP, i,
+ &memberKeyP, &memberValueP);
+ XMLRPC_FAIL_IF_FAULT(envP);
+ addString(envP, outputP, "<member><name>");
+ XMLRPC_FAIL_IF_FAULT(envP);
+ serializeUtf8MemBlock(envP, outputP, &memberKeyP->_block);
+ XMLRPC_FAIL_IF_FAULT(envP);
+ addString(envP, outputP, "</name>"CRLF);
+ XMLRPC_FAIL_IF_FAULT(envP);
+ xmlrpc_serialize_value2(envP, outputP, memberValueP, dialect);
+ XMLRPC_FAIL_IF_FAULT(envP);
+ addString(envP, outputP, "</member>"CRLF);
+ XMLRPC_FAIL_IF_FAULT(envP);
}
- format_out(env, output, "</struct>");
- XMLRPC_FAIL_IF_FAULT(env);
+ addString(envP, outputP, "</struct>");
+ XMLRPC_FAIL_IF_FAULT(envP);
cleanup:
return;
@@ -315,175 +315,229 @@
-/*=========================================================================
-** xmlrpc_serialize_value
-**=========================================================================
-** Dump a value in the appropriate fashion.
-*/
+static void
+serializeArray(xmlrpc_env * const envP,
+ xmlrpc_mem_block * const outputP,
+ xmlrpc_value * const valueP,
+ xmlrpc_dialect const dialect) {
+/*----------------------------------------------------------------------------
+ Add to *outputP the content of a <value> element to represent
+ the array value *valueP. I.e. "<array> ... </array>".
+-----------------------------------------------------------------------------*/
+ int const size = xmlrpc_array_size(envP, valueP);
-void
-xmlrpc_serialize_value(xmlrpc_env *env,
- xmlrpc_mem_block *output,
- xmlrpc_value *value) {
+ if (!envP->fault_occurred) {
+ addString(envP, outputP, "<array><data>"CRLF);
+ if (!envP->fault_occurred) {
+ int i;
+ /* Serialize each item. */
+ for (i = 0; i < size && !envP->fault_occurred; ++i) {
+ xmlrpc_value * const itemP =
+ xmlrpc_array_get_item(envP, valueP, i);
+ if (!envP->fault_occurred) {
+ xmlrpc_serialize_value2(envP, outputP, itemP, dialect);
+ if (!envP->fault_occurred)
+ addString(envP, outputP, CRLF);
+ }
+ }
+ }
+ }
+ if (!envP->fault_occurred)
+ addString(envP, outputP, "</data></array>");
+}
- xmlrpc_value *item;
- size_t size;
- unsigned char* contents;
- size_t i;
- XMLRPC_ASSERT_ENV_OK(env);
- XMLRPC_ASSERT(output != NULL);
- XMLRPC_ASSERT_VALUE_OK(value);
-
- /* Print our ubiquitous header. */
- format_out(env, output, "<value>");
- XMLRPC_FAIL_IF_FAULT(env);
- switch (value->_type) {
+static void
+formatValueContent(xmlrpc_env * const envP,
+ xmlrpc_mem_block * const outputP,
+ xmlrpc_value * const valueP,
+ xmlrpc_dialect const dialect) {
+/*----------------------------------------------------------------------------
+ Add to *outputP the content of a <value> element to represent
+ value *valueP. E.g. "<int>42</int>"
+-----------------------------------------------------------------------------*/
+ XMLRPC_ASSERT_ENV_OK(envP);
+ switch (valueP->_type) {
case XMLRPC_TYPE_INT:
- /* XXX - We assume that '%i' is the appropriate format specifier
- ** for an xmlrpc_int32 value. We should add some test cases to
- ** make sure this works. */
- format_out(env, output, "<i4>%i</i4>", value->_value.i);
+ formatOut(envP, outputP, "<i4>%d</i4>", valueP->_value.i);
break;
+ case XMLRPC_TYPE_I8: {
+ const char * const elemName =
+ dialect == xmlrpc_dialect_apache ? "ex.i8" : "i8";
+ formatOut(envP, outputP, "<%s>%" PRId64 "</%s>",
+ elemName, valueP->_value.i8, elemName);
+ } break;
+
case XMLRPC_TYPE_BOOL:
- /* XXX - We assume that '%i' is the appropriate format specifier
- ** for an xmlrpc_bool value. */
- format_out(env, output, "<boolean>%i</boolean>",
- (value->_value.b) ? 1 : 0);
+ formatOut(envP, outputP, "<boolean>%s</boolean>",
+ valueP->_value.b ? "1" : "0");
break;
- case XMLRPC_TYPE_DOUBLE:
- /* We must output a number of the form [+-]?\d*.\d*. */
- format_out(env, output, "<double>%.17g</double>", value->_value.d);
+ case XMLRPC_TYPE_DOUBLE: {
+ const char * serializedValue;
+ xmlrpc_formatFloat(envP, valueP->_value.d, &serializedValue);
+ if (!envP->fault_occurred) {
+ addString(envP, outputP, "<double>");
+ if (!envP->fault_occurred) {
+ addString(envP, outputP, serializedValue);
+ if (!envP->fault_occurred)
+ addString(envP, outputP, "</double>");
+ }
+ xmlrpc_strfree(serializedValue);
+ }
+ } break;
+
+ case XMLRPC_TYPE_DATETIME:
+ addString(envP, outputP, "<dateTime.iso8601>");
+ if (!envP->fault_occurred) {
+ serializeUtf8MemBlock(envP, outputP, &valueP->_block);
+ if (!envP->fault_occurred) {
+ addString(envP, outputP, "</dateTime.iso8601>");
+ }
+ }
break;
case XMLRPC_TYPE_STRING:
- format_out(env, output, "<string>");
- XMLRPC_FAIL_IF_FAULT(env);
- xmlrpc_serialize_string_data(env, output, value);
- XMLRPC_FAIL_IF_FAULT(env);
- format_out(env, output, "</string>");
+ addString(envP, outputP, "<string>");
+ if (!envP->fault_occurred) {
+ serializeUtf8MemBlock(envP, outputP, &valueP->_block);
+ if (!envP->fault_occurred)
+ addString(envP, outputP, "</string>");
+ }
break;
- case XMLRPC_TYPE_ARRAY:
- format_out(env, output, "<array><data>"CRLF);
- XMLRPC_FAIL_IF_FAULT(env);
-
- /* Serialize each item. */
- size = xmlrpc_array_size(env, value);
- XMLRPC_FAIL_IF_FAULT(env);
- for (i = 0; i < size; i++) {
- item = xmlrpc_array_get_item(env, value, i);
- XMLRPC_FAIL_IF_FAULT(env);
- xmlrpc_serialize_value(env, output, item);
- XMLRPC_FAIL_IF_FAULT(env);
- format_out(env, output, CRLF);
- XMLRPC_FAIL_IF_FAULT(env);
+ case XMLRPC_TYPE_BASE64: {
+ unsigned char * const contents =
+ XMLRPC_MEMBLOCK_CONTENTS(unsigned char, &valueP->_block);
+ size_t const size =
+ XMLRPC_MEMBLOCK_SIZE(unsigned char, &valueP->_block);
+ addString(envP, outputP, "<base64>"CRLF);
+ if (!envP->fault_occurred) {
+ xmlrpc_serialize_base64_data(envP, outputP, contents, size);
+ if (!envP->fault_occurred)
+ addString(envP, outputP, "</base64>");
}
+ } break;
- format_out(env, output, "</data></array>");
+ case XMLRPC_TYPE_ARRAY:
+ serializeArray(envP, outputP, valueP, dialect);
break;
case XMLRPC_TYPE_STRUCT:
- xmlrpc_serialize_struct(env, output, value);
- break;
-
- case XMLRPC_TYPE_BASE64:
- format_out(env, output, "<base64>"CRLF);
- XMLRPC_FAIL_IF_FAULT(env);
- contents = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(unsigned char,
- &value->_block);
- size = XMLRPC_TYPED_MEM_BLOCK_SIZE(unsigned char, &value->_block);
- xmlrpc_serialize_base64_data(env, output, contents, size);
- XMLRPC_FAIL_IF_FAULT(env);
- format_out(env, output, "</base64>");
- break;
-
- case XMLRPC_TYPE_DATETIME:
- format_out(env, output, "<dateTime.iso8601>");
- XMLRPC_FAIL_IF_FAULT(env);
- xmlrpc_serialize_string_data(env, output, value);
- XMLRPC_FAIL_IF_FAULT(env);
- format_out(env, output, "</dateTime.iso8601>");
+ serializeStruct(envP, outputP, valueP, dialect);
break;
case XMLRPC_TYPE_C_PTR:
- xmlrpc_env_set_fault_formatted(
- env, XMLRPC_INTERNAL_ERROR,
- "Tried to serialize a C pointer value.");
+ xmlrpc_faultf(envP, "Tried to serialize a C pointer value.");
break;
- case XMLRPC_TYPE_NIL:
- format_out(env, output, "<nil/>");
- XMLRPC_FAIL_IF_FAULT(env);
- break;
+ case XMLRPC_TYPE_NIL: {
+ const char * const elemName =
+ dialect == xmlrpc_dialect_apache ? "ex.nil" : "nil";
+ formatOut(envP, outputP, "<%s/>", elemName);
+ } break;
case XMLRPC_TYPE_DEAD:
- xmlrpc_env_set_fault_formatted(
- env, XMLRPC_INTERNAL_ERROR,
- "Tried to serialize a deaad value.");
+ xmlrpc_faultf(envP, "Tried to serialize a dead value.");
break;
default:
- xmlrpc_env_set_fault_formatted(
- env, XMLRPC_INTERNAL_ERROR,
- "Invalid xmlrpc_value type: %d", value->_type);
+ xmlrpc_faultf(envP, "Invalid xmlrpc_value type: %d", valueP->_type);
}
- XMLRPC_FAIL_IF_FAULT(env);
+}
- /* Print our ubiquitous footer. */
- format_out(env, output, "</value>");
- XMLRPC_FAIL_IF_FAULT(env);
- cleanup:
- return;
+
+void
+xmlrpc_serialize_value2(xmlrpc_env * const envP,
+ xmlrpc_mem_block * const outputP,
+ xmlrpc_value * const valueP,
+ xmlrpc_dialect const dialect) {
+/*----------------------------------------------------------------------------
+ Generate the XML to represent XML-RPC value 'valueP' in XML-RPC.
+
+ Add it to *outputP.
+-----------------------------------------------------------------------------*/
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT(outputP != NULL);
+ XMLRPC_ASSERT_VALUE_OK(valueP);
+
+ addString(envP, outputP, "<value>");
+
+ if (!envP->fault_occurred) {
+ formatValueContent(envP, outputP, valueP, dialect);
+
+ if (!envP->fault_occurred)
+ addString(envP, outputP, "</value>");
+ }
}
-/*=========================================================================
-** xmlrpc_serialize_params
-**=========================================================================
-** Serialize a list as a set of parameters.
-*/
+void
+xmlrpc_serialize_value(xmlrpc_env * const envP,
+ xmlrpc_mem_block * const outputP,
+ xmlrpc_value * const valueP) {
+
+ xmlrpc_serialize_value2(envP, outputP, valueP, xmlrpc_dialect_i8);
+}
+
+
void
-xmlrpc_serialize_params(xmlrpc_env *env,
- xmlrpc_mem_block *output,
- xmlrpc_value *param_array) {
-
- size_t size, i;
- xmlrpc_value *item;
-
- XMLRPC_ASSERT_ENV_OK(env);
- XMLRPC_ASSERT(output != NULL);
- XMLRPC_ASSERT_VALUE_OK(param_array);
-
- format_out(env, output, "<params>"CRLF);
- XMLRPC_FAIL_IF_FAULT(env);
-
- /* Dump each parameter. */
- size = xmlrpc_array_size(env, param_array);
- XMLRPC_FAIL_IF_FAULT(env);
- for (i = 0; i < size; i++) {
- format_out(env, output, "<param>");
- XMLRPC_FAIL_IF_FAULT(env);
- item = xmlrpc_array_get_item(env, param_array, i);
- XMLRPC_FAIL_IF_FAULT(env);
- xmlrpc_serialize_value(env, output, item);
- XMLRPC_FAIL_IF_FAULT(env);
- format_out(env, output, "</param>"CRLF);
- XMLRPC_FAIL_IF_FAULT(env);
+xmlrpc_serialize_params2(xmlrpc_env * const envP,
+ xmlrpc_mem_block * const outputP,
+ xmlrpc_value * const paramArrayP,
+ xmlrpc_dialect const dialect) {
+/*----------------------------------------------------------------------------
+ Serialize the parameter list of an XML-RPC call.
+-----------------------------------------------------------------------------*/
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT(outputP != NULL);
+ XMLRPC_ASSERT_VALUE_OK(paramArrayP);
+
+ addString(envP, outputP, "<params>"CRLF);
+ if (!envP->fault_occurred) {
+ /* Serialize each parameter. */
+ size_t const paramCount = xmlrpc_array_size(envP, paramArrayP);
+ if (!envP->fault_occurred) {
+ size_t paramSeq;
+ for (paramSeq = 0;
+ paramSeq < paramCount && !envP->fault_occurred;
+ ++paramSeq) {
+
+ addString(envP, outputP, "<param>");
+ if (!envP->fault_occurred) {
+ xmlrpc_value * const itemP =
+ xmlrpc_array_get_item(envP, paramArrayP, paramSeq);
+ if (!envP->fault_occurred) {
+ xmlrpc_serialize_value2(envP, outputP, itemP, dialect);
+ if (!envP->fault_occurred)
+ addString(envP, outputP, "</param>"CRLF);
+ }
+ }
+ }
+ }
}
- format_out(env, output, "</params>"CRLF);
- XMLRPC_FAIL_IF_FAULT(env);
+ if (!envP->fault_occurred)
+ addString(envP, outputP, "</params>"CRLF);
+}
- cleanup:
- return;
+
+
+void
+xmlrpc_serialize_params(xmlrpc_env * const envP,
+ xmlrpc_mem_block * const outputP,
+ xmlrpc_value * const paramArrayP) {
+/*----------------------------------------------------------------------------
+ Serialize the parameter list of an XML-RPC call in the original
+ "i8" dialect.
+-----------------------------------------------------------------------------*/
+ xmlrpc_serialize_params2(envP, outputP, paramArrayP, xmlrpc_dialect_i8);
}
@@ -495,131 +549,166 @@
*/
void
-xmlrpc_serialize_call(xmlrpc_env * const env,
- xmlrpc_mem_block * const output,
- const char * const method_name,
- xmlrpc_value * const param_array) {
-
- xmlrpc_mem_block *escaped;
- char *contents;
- size_t size;
+xmlrpc_serialize_call2(xmlrpc_env * const envP,
+ xmlrpc_mem_block * const outputP,
+ const char * const methodName,
+ xmlrpc_value * const paramArrayP,
+ xmlrpc_dialect const dialect) {
+/*----------------------------------------------------------------------------
+ Serialize an XML-RPC call of method named 'methodName' with parameter
+ list *paramArrayP. Use XML-RPC dialect 'dialect'.
- XMLRPC_ASSERT_ENV_OK(env);
- XMLRPC_ASSERT(output != NULL);
- XMLRPC_ASSERT(method_name != NULL);
- XMLRPC_ASSERT_VALUE_OK(param_array);
+ Append the call XML ot *outputP.
+-----------------------------------------------------------------------------*/
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT(outputP != NULL);
+ XMLRPC_ASSERT(methodName != NULL);
+ XMLRPC_ASSERT_VALUE_OK(paramArrayP);
- /* Set up our error-handling preconditions. */
- escaped = NULL;
-
- /* Dump our header. */
- format_out(env, output, XML_PROLOGUE);
- XMLRPC_FAIL_IF_FAULT(env);
- format_out(env, output, "<methodCall>"CRLF"<methodName>");
- XMLRPC_FAIL_IF_FAULT(env);
-
- /* Dump the method name. */
- escaped = escape_string(env, method_name, strlen(method_name));
- XMLRPC_FAIL_IF_FAULT(env);
- contents = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, escaped);
- size = XMLRPC_TYPED_MEM_BLOCK_SIZE(char, escaped);
- XMLRPC_TYPED_MEM_BLOCK_APPEND(char, env, output, contents, size);
- XMLRPC_FAIL_IF_FAULT(env);
-
- /* Dump our parameters and footer. */
- format_out(env, output, "</methodName>"CRLF);
- XMLRPC_FAIL_IF_FAULT(env);
- xmlrpc_serialize_params(env, output, param_array);
- XMLRPC_FAIL_IF_FAULT(env);
- format_out(env, output, "</methodCall>"CRLF);
- XMLRPC_FAIL_IF_FAULT(env);
-
- cleanup:
- if (escaped)
- xmlrpc_mem_block_free(escaped);
+ addString(envP, outputP, XML_PROLOGUE);
+ if (!envP->fault_occurred) {
+ addString(envP, outputP, "<methodCall>"CRLF"<methodName>");
+ if (!envP->fault_occurred) {
+ xmlrpc_mem_block * encodedP;
+ escapeForXml(envP, methodName, strlen(methodName), &encodedP);
+ if (!envP->fault_occurred) {
+ const char * const contents =
+ XMLRPC_MEMBLOCK_CONTENTS(char, encodedP);
+ size_t const size = XMLRPC_MEMBLOCK_SIZE(char, encodedP);
+ XMLRPC_MEMBLOCK_APPEND(char, envP, outputP, contents, size);
+ if (!envP->fault_occurred) {
+ addString(envP, outputP, "</methodName>"CRLF);
+ if (!envP->fault_occurred) {
+ xmlrpc_serialize_params2(envP, outputP, paramArrayP,
+ dialect);
+ if (!envP->fault_occurred)
+ addString(envP, outputP, "</methodCall>"CRLF);
+ }
+ }
+ XMLRPC_MEMBLOCK_FREE(char, encodedP);
+ }
+ }
+ }
}
-/*=========================================================================
-** xmlrpc_serialize_response
-**=========================================================================
-** Serialize the (non-fault) response to an XML-RPC call.
-*/
+void
+xmlrpc_serialize_call(xmlrpc_env * const envP,
+ xmlrpc_mem_block * const outputP,
+ const char * const methodName,
+ xmlrpc_value * const paramArrayP) {
+
+ xmlrpc_serialize_call2(envP, outputP, methodName, paramArrayP,
+ xmlrpc_dialect_i8);
+}
+
+
void
-xmlrpc_serialize_response (xmlrpc_env *env,
- xmlrpc_mem_block *output,
- xmlrpc_value *value) {
-
- XMLRPC_ASSERT_ENV_OK(env);
- XMLRPC_ASSERT(output != NULL);
- XMLRPC_ASSERT_VALUE_OK(value);
-
- format_out(env, output, XML_PROLOGUE);
- XMLRPC_FAIL_IF_FAULT(env);
- format_out(env, output, "<methodResponse>"CRLF"<params>"CRLF"<param>");
- XMLRPC_FAIL_IF_FAULT(env);
-
- xmlrpc_serialize_value(env, output, value);
- XMLRPC_FAIL_IF_FAULT(env);
-
- format_out(env, output,
- "</param>"CRLF"</params>"CRLF"</methodResponse>"CRLF);
- XMLRPC_FAIL_IF_FAULT(env);
-
- cleanup:
- return;
+xmlrpc_serialize_response2(xmlrpc_env * const envP,
+ xmlrpc_mem_block * const outputP,
+ xmlrpc_value * const valueP,
+ xmlrpc_dialect const dialect) {
+/*----------------------------------------------------------------------------
+ Serialize a result response to an XML-RPC call.
+
+ The result is 'valueP'.
+
+ Add the response XML to *outputP.
+-----------------------------------------------------------------------------*/
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT(outputP != NULL);
+ XMLRPC_ASSERT_VALUE_OK(valueP);
+
+ addString(envP, outputP, XML_PROLOGUE);
+ if (!envP->fault_occurred) {
+ addString(envP, outputP,
+ "<methodResponse>"CRLF"<params>"CRLF"<param>");
+ if (!envP->fault_occurred) {
+ xmlrpc_serialize_value2(envP, outputP, valueP, dialect);
+ if (!envP->fault_occurred) {
+ addString(envP, outputP,
+ "</param>"CRLF"</params>"CRLF
+ "</methodResponse>"CRLF);
+ }
+ }
+ }
}
-/*=========================================================================
-** xmlrpc_serialize_fault
-**=========================================================================
-** Serialize an XML-RPC fault.
-**
-** If this function fails, it will set up the first env argument. You'll
-** need to take some other drastic action to produce a serialized fault
-** of your own. (This function should only fail in an out-of-memory
-** situation, AFAIK.)
-*/
+void
+xmlrpc_serialize_response(xmlrpc_env * const envP,
+ xmlrpc_mem_block * const outputP,
+ xmlrpc_value * const valueP) {
+
+ xmlrpc_serialize_response2(envP, outputP, valueP, xmlrpc_dialect_i8);
+}
+
+
void
-xmlrpc_serialize_fault(xmlrpc_env *env,
- xmlrpc_mem_block *output,
- xmlrpc_env *fault) {
-
- xmlrpc_value *strct;
-
- XMLRPC_ASSERT_ENV_OK(env);
- XMLRPC_ASSERT(output != NULL);
- XMLRPC_ASSERT(fault != NULL && fault->fault_occurred);
-
- /* Set up our error-handling preconditions. */
- strct = NULL;
-
- /* Build a fault structure. */
- strct = xmlrpc_build_value(env, "{s:i,s:s}",
- "faultCode", (xmlrpc_int32) fault->fault_code,
- "faultString", fault->fault_string);
- XMLRPC_FAIL_IF_FAULT(env);
-
- /* Output our header. */
- format_out(env, output, XML_PROLOGUE);
- XMLRPC_FAIL_IF_FAULT(env);
- format_out(env, output, "<methodResponse>"CRLF"<fault>"CRLF);
- XMLRPC_FAIL_IF_FAULT(env);
-
- /* Serialize our fault structure. */
- xmlrpc_serialize_value(env, output, strct);
- XMLRPC_FAIL_IF_FAULT(env);
-
- /* Output our footer. */
- format_out(env, output, CRLF"</fault>"CRLF"</methodResponse>"CRLF);
- XMLRPC_FAIL_IF_FAULT(env);
-
- cleanup:
- if (strct)
- xmlrpc_DECREF(strct);
+xmlrpc_serialize_fault(xmlrpc_env * const envP,
+ xmlrpc_mem_block * const outputP,
+ const xmlrpc_env * const faultP) {
+/*----------------------------------------------------------------------------
+ Serialize a fault response to an XML-RPC call.
+
+ 'faultP' is the fault.
+
+ Add the response XML to *outputP.
+-----------------------------------------------------------------------------*/
+ xmlrpc_value * faultStructP;
+
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT(outputP != NULL);
+ XMLRPC_ASSERT(faultP != NULL);
+ XMLRPC_ASSERT(faultP->fault_occurred);
+
+ faultStructP = xmlrpc_build_value(envP, "{s:i,s:s}",
+ "faultCode",
+ (xmlrpc_int32) faultP->fault_code,
+ "faultString", faultP->fault_string);
+ if (!envP->fault_occurred) {
+ addString(envP, outputP, XML_PROLOGUE);
+ if (!envP->fault_occurred) {
+ addString(envP, outputP, "<methodResponse>"CRLF"<fault>"CRLF);
+ if (!envP->fault_occurred) {
+ xmlrpc_serialize_value(envP, outputP, faultStructP);
+ if (!envP->fault_occurred) {
+ addString(envP, outputP,
+ CRLF"</fault>"CRLF"</methodResponse>"CRLF);
+ }
+ }
+ }
+ xmlrpc_DECREF(faultStructP);
+ }
}
+
+
+
+/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR 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. */
Modified: freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_server_abyss.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_server_abyss.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_server_abyss.c Fri May 23 16:56:24 2008
@@ -2,19 +2,43 @@
#include "xmlrpc_config.h"
+#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <errno.h>
+#include <time.h>
+#include <fcntl.h>
+#ifdef _WIN32
+# include <io.h>
+#else
+# include <signal.h>
+# include <sys/wait.h>
+# include <grp.h>
+#endif
+#include "bool.h"
+#include "int.h"
#include "mallocvar.h"
#include "xmlrpc-c/abyss.h"
#include "xmlrpc-c/base.h"
#include "xmlrpc-c/server.h"
#include "xmlrpc-c/base_int.h"
+#include "xmlrpc-c/string_int.h"
#include "xmlrpc-c/server_abyss.h"
+
+struct xmlrpc_server_abyss {
+ TServer abyssServer;
+ TChanSwitch * chanSwitchP;
+ bool shutdownEnabled;
+ /* User wants system.shutdown to succeed */
+};
+
+
+
/*=========================================================================
** die_if_fault_occurred
**=========================================================================
@@ -32,18 +56,110 @@
-/*=========================================================================
-** send_xml_data
-**=========================================================================
-** Blast some XML data back to the client.
-*/
+static void
+initAbyss(xmlrpc_env * const envP) {
+
+ const char * error;
+ AbyssInit(&error);
+ if (error) {
+ xmlrpc_faultf(envP, "Failed to initialize the Abyss library. %s",
+ error);
+ xmlrpc_strfree(error);
+ }
+}
+
+
+
+static void
+termAbyss(void) {
+
+ AbyssTerm();
+}
+
+
+
+static unsigned int globallyInitialized = 0;
+ /* Initialization count */
+
+
+void
+xmlrpc_server_abyss_global_init(xmlrpc_env * const envP) {
+
+ /* Note that this is specified as not thread safe; user calls it at
+ the beginning of his program, when it is only one thread.
+ */
+
+ XMLRPC_ASSERT_ENV_OK(envP);
+
+ if (globallyInitialized == 0)
+ initAbyss(envP);
+
+ ++globallyInitialized;
+}
+
+
+
+void
+xmlrpc_server_abyss_global_term(void) {
+
+ /* Note that this is specified as not thread safe; user calls it at
+ the end of his program, when it is only one thread.
+ */
+
+ XMLRPC_ASSERT(globallyInitialized > 0);
+
+ --globallyInitialized;
+
+ if (globallyInitialized == 0)
+ termAbyss();
+}
+
+
+
+static void
+validateGlobalInit(xmlrpc_env * const envP) {
+
+ if (!globallyInitialized)
+ xmlrpc_faultf(envP, "libxmlrpc_server_abyss has not been globally "
+ "initialized. See xmlrpc_server_abyss_init()");
+}
+
+
+
+static void
+addAuthCookie(xmlrpc_env * const envP,
+ TSession * const abyssSessionP,
+ const char * const authCookie) {
+
+ const char * cookieResponse;
+
+ xmlrpc_asprintf(&cookieResponse, "auth=%s", authCookie);
+
+ if (cookieResponse == xmlrpc_strsol)
+ xmlrpc_faultf(envP, "Insufficient memory to generate cookie "
+ "response header.");
+ else {
+ ResponseAddField(abyssSessionP, "Set-Cookie", cookieResponse);
+
+ xmlrpc_strfree(cookieResponse);
+ }
+}
+
+
static void
sendXmlData(xmlrpc_env * const envP,
- TSession * const r,
- char * const buffer,
- size_t const len) {
+ TSession * const abyssSessionP,
+ const char * const body,
+ size_t const len,
+ bool const chunked) {
+/*----------------------------------------------------------------------------
+ Generate an HTTP response containing body 'body' of length 'len'
+ characters.
+ This is meant to run in the context of an Abyss URI handler for
+ Abyss session 'abyssSessionP'.
+-----------------------------------------------------------------------------*/
const char * http_cookie = NULL;
/* This used to set http_cookie to getenv("HTTP_COOKIE"), but
that doesn't make any sense -- environment variables are not
@@ -51,58 +167,50 @@
- Bryan 2004.10.03.
*/
- /* fwrite(buffer, sizeof(char), len, stderr); */
+ /* Various bugs before Xmlrpc-c 1.05 caused the response to be not
+ chunked in the most basic case, but chunked if the client explicitly
+ requested keepalive. I think it's better not to chunk, because
+ it's simpler, so I removed this in 1.05. I don't know what the
+ purpose of chunking would be, and an original comment suggests
+ the author wasn't sure chunking was a good idea.
- /* XXX - Is it safe to chunk our response? */
- ResponseChunked(r);
+ In 1.06 we added the user option to chunk.
+ */
+ if (chunked)
+ ResponseChunked(abyssSessionP);
- ResponseStatus(r, 200);
-
- if (http_cookie) {
- /* There's an auth cookie, so pass it back in the response. */
+ ResponseStatus(abyssSessionP, 200);
- char *cookie_response;
-
- cookie_response = malloc(10+strlen(http_cookie));
- sprintf(cookie_response, "auth=%s", http_cookie);
-
- /* Return abyss response. */
- ResponseAddField(r, "Set-Cookie", cookie_response);
+ if (http_cookie)
+ /* There's an auth cookie, so pass it back in the response. */
+ addAuthCookie(envP, abyssSessionP, http_cookie);
- free(cookie_response);
- }
-
if ((size_t)(uint32_t)len != len)
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR,
- "XML-RPC method generated a response too "
- "large for Abyss to send");
+ xmlrpc_faultf(envP, "XML-RPC method generated a response too "
+ "large for Abyss to send");
else {
uint32_t const abyssLen = (uint32_t)len;
- ResponseContentType(r, "text/xml; charset=\"utf-8\"");
- ResponseContentLength(r, abyssLen);
-
- ResponseWrite(r);
+
+ ResponseContentType(abyssSessionP, "text/xml; charset=\"utf-8\"");
+ ResponseContentLength(abyssSessionP, abyssLen);
- HTTPWrite(r, buffer, abyssLen);
- HTTPWriteEnd(r);
+ ResponseWriteStart(abyssSessionP);
+ ResponseWriteBody(abyssSessionP, body, abyssLen);
+ ResponseWriteEnd(abyssSessionP);
}
}
-/*=========================================================================
-** send_error
-**=========================================================================
-** Send an error back to the client.
-*/
-
static void
-send_error(TSession * const abyssSessionP,
- unsigned int const status) {
-
+sendError(TSession * const abyssSessionP,
+ unsigned int const status,
+ const char * const explanation) {
+/*----------------------------------------------------------------------------
+ Send an error response back to the client.
+-----------------------------------------------------------------------------*/
ResponseStatus(abyssSessionP, (uint16_t) status);
- ResponseError(abyssSessionP);
+ ResponseError2(abyssSessionP, explanation);
}
@@ -111,35 +219,7 @@
traceChunkRead(TSession * const abyssSessionP) {
fprintf(stderr, "XML-RPC handler got a chunk of %u bytes\n",
- abyssSessionP->conn->buffersize -
- abyssSessionP->conn->bufferpos);
-}
-
-
-
-/*=========================================================================
-** get_buffer_data
-**=========================================================================
-** Extract some data from the TConn's underlying input buffer. Do not
-** extract more than 'max'.
-*/
-
-static void
-get_buffer_data(TSession * const r,
- size_t const max,
- char ** const out_start,
- size_t * const out_len) {
-
- /* Point to the start of our data. */
- *out_start = &r->conn->buffer[r->conn->bufferpos];
-
- /* Decide how much data to retrieve. */
- *out_len = r->conn->buffersize - r->conn->bufferpos;
- if (*out_len > max)
- *out_len = max;
-
- /* Update our buffer position. */
- r->conn->bufferpos += *out_len;
+ (unsigned int)SessionReadDataAvail(abyssSessionP));
}
@@ -151,20 +231,10 @@
/*----------------------------------------------------------------------------
Get the next chunk of data from the connection into the buffer.
-----------------------------------------------------------------------------*/
- abyss_bool succeeded;
-
- /* Reset our read buffer & flush data from previous reads. */
- ConnReadInit(abyssSessionP->conn);
-
- /* Read more network data into our buffer. If we encounter a
- timeout, exit immediately. We're very forgiving about the
- timeout here. We allow a full timeout per network read, which
- would allow somebody to keep a connection alive nearly
- indefinitely. But it's hard to do anything intelligent here
- without very complicated code.
- */
- succeeded = ConnRead(abyssSessionP->conn,
- abyssSessionP->server->timeout);
+ bool succeeded;
+
+ succeeded = SessionRefillBuffer(abyssSessionP);
+
if (!succeeded)
xmlrpc_env_set_fault_formatted(
envP, XMLRPC_TIMEOUT_ERROR, "Timed out waiting for "
@@ -194,21 +264,23 @@
if (trace)
fprintf(stderr, "XML-RPC handler processing body. "
- "Content Size = %u bytes\n", contentSize);
+ "Content Size = %u bytes\n", (unsigned)contentSize);
body = xmlrpc_mem_block_new(envP, 0);
if (!envP->fault_occurred) {
size_t bytesRead;
- char * chunkPtr;
+ const char * chunkPtr;
size_t chunkLen;
bytesRead = 0;
while (!envP->fault_occurred && bytesRead < contentSize) {
- get_buffer_data(abyssSessionP, contentSize - bytesRead,
- &chunkPtr, &chunkLen);
+ SessionGetReadData(abyssSessionP, contentSize - bytesRead,
+ &chunkPtr, &chunkLen);
bytesRead += chunkLen;
+ assert(bytesRead <= contentSize);
+
XMLRPC_MEMBLOCK_APPEND(char, envP, body, chunkPtr, chunkLen);
if (bytesRead < contentSize)
refillBufferFromConnection(envP, abyssSessionP, trace);
@@ -224,7 +296,7 @@
static void
storeCookies(TSession * const httpRequestP,
- unsigned int * const httpErrorP) {
+ const char ** const errorP) {
/*----------------------------------------------------------------------------
Get the cookie settings from the HTTP headers and remember them for
use in responses.
@@ -241,7 +313,7 @@
}
/* TODO: parse HTTP_COOKIE to find auth pair, if there is one */
- *httpErrorP = 0;
+ *errorP = NULL;
}
@@ -249,18 +321,19 @@
static void
validateContentType(TSession * const httpRequestP,
- unsigned int * const httpErrorP) {
+ const char ** const errorP) {
/*----------------------------------------------------------------------------
- If the client didn't specify a content-type of "text/xml", return
- "400 Bad Request". We can't allow the client to default this header,
- because some firewall software may rely on all XML-RPC requests
- using the POST method and a content-type of "text/xml".
+ If the client didn't specify a content-type of "text/xml", fail.
+ We can't allow the client to default this header, because some
+ firewall software may rely on all XML-RPC requests using the POST
+ method and a content-type of "text/xml".x
-----------------------------------------------------------------------------*/
const char * const content_type =
RequestHeaderValue(httpRequestP, "content-type");
if (content_type == NULL)
- *httpErrorP = 400;
+ xmlrpc_asprintf(errorP,
+ "You did not supply a content-type HTTP header");
else {
const char * const sempos = strchr(content_type, ';');
unsigned int baselen;
@@ -273,33 +346,39 @@
else
baselen = strlen(content_type);
- if (strncmp(content_type, "text/xml", baselen) != 0)
- *httpErrorP = 400;
+ if (!xmlrpc_strneq(content_type, "text/xml", baselen))
+ xmlrpc_asprintf(errorP, "Your content-type HTTP header value '%s' "
+ "does not have a base type of 'text/xml'",
+ content_type);
else
- *httpErrorP = 0;
+ *errorP = NULL;
}
}
static void
-processContentLength(TSession * const httpRequestP,
- size_t * const inputLenP,
- unsigned int * const httpErrorP) {
+processContentLength(TSession * const httpRequestP,
+ size_t * const inputLenP,
+ bool * const missingP,
+ const char ** const errorP) {
/*----------------------------------------------------------------------------
Make sure the content length is present and non-zero. This is
technically required by XML-RPC, but we only enforce it because we
don't want to figure out how to safely handle HTTP < 1.1 requests
- without it. If the length is missing, return "411 Length Required".
+ without it.
-----------------------------------------------------------------------------*/
const char * const content_length =
RequestHeaderValue(httpRequestP, "content-length");
- if (content_length == NULL)
- *httpErrorP = 411;
- else {
+ if (content_length == NULL) {
+ *missingP = TRUE;
+ *errorP = NULL;
+ } else {
+ *missingP = FALSE;
if (content_length[0] == '\0')
- *httpErrorP = 400;
+ xmlrpc_asprintf(errorP, "The value in your content-length "
+ "HTTP header value is a null string");
else {
unsigned long contentLengthValue;
char * tail;
@@ -307,15 +386,21 @@
contentLengthValue = strtoul(content_length, &tail, 10);
if (*tail != '\0')
- /* There's non-numeric crap in the length */
- *httpErrorP = 400;
+ xmlrpc_asprintf(errorP, "There's non-numeric crap in "
+ "the value of your content-length "
+ "HTTP header: '%s'", tail);
else if (contentLengthValue < 1)
- *httpErrorP = 400;
+ xmlrpc_asprintf(errorP, "According to your content-length "
+ "HTTP header, your request is empty (zero "
+ "length)");
else if ((unsigned long)(size_t)contentLengthValue
!= contentLengthValue)
- *httpErrorP = 400;
+ xmlrpc_asprintf(errorP, "According to your content-length "
+ "HTTP header, your request is too big to "
+ "process; we can't even do arithmetic on its "
+ "size: %s bytes", content_length);
else {
- *httpErrorP = 0;
+ *errorP = NULL;
*inputLenP = (size_t)contentLengthValue;
}
}
@@ -328,12 +413,15 @@
traceHandlerCalled(TSession * const abyssSessionP) {
const char * methodDesc;
+ const TRequestInfo * requestInfoP;
- fprintf(stderr, "xmlrpc_server_abyss RPC2 handler called.\n");
+ fprintf(stderr, "xmlrpc_server_abyss URI path handler called.\n");
- fprintf(stderr, "URI = '%s'\n", abyssSessionP->uri);
+ SessionGetRequestInfo(abyssSessionP, &requestInfoP);
- switch (abyssSessionP->method) {
+ fprintf(stderr, "URI = '%s'\n", requestInfoP->uri);
+
+ switch (requestInfoP->method) {
case m_unknown: methodDesc = "unknown"; break;
case m_get: methodDesc = "get"; break;
case m_put: methodDesc = "put"; break;
@@ -346,9 +434,9 @@
}
fprintf(stderr, "HTTP method = '%s'\n", methodDesc);
- if (abyssSessionP->query)
+ if (requestInfoP->query)
fprintf(stderr, "query (component of URL)='%s'\n",
- abyssSessionP->query);
+ requestInfoP->query);
else
fprintf(stderr, "URL has no query component\n");
}
@@ -359,17 +447,22 @@
processCall(TSession * const abyssSessionP,
size_t const contentSize,
xmlrpc_registry * const registryP,
+ bool const wantChunk,
const char * const trace) {
/*----------------------------------------------------------------------------
Handle an RPC request. This is an HTTP request that has the proper form
- to be one of our RPCs.
+ to be an XML-RPC call.
+
+ The text of the call is available through the Abyss session
+ 'abyssSessionP'.
Its content length is 'contentSize' bytes.
-----------------------------------------------------------------------------*/
xmlrpc_env env;
if (trace)
- fprintf(stderr, "xmlrpc_server_abyss RPC2 handler processing RPC.\n");
+ fprintf(stderr,
+ "xmlrpc_server_abyss URI path handler processing RPC.\n");
xmlrpc_env_init(&env);
@@ -378,21 +471,24 @@
&env, XMLRPC_LIMIT_EXCEEDED_ERROR,
"XML-RPC request too large (%d bytes)", contentSize);
else {
- xmlrpc_mem_block *body;
+ xmlrpc_mem_block * body;
/* Read XML data off the wire. */
getBody(&env, abyssSessionP, contentSize, trace, &body);
if (!env.fault_occurred) {
xmlrpc_mem_block * output;
/* Process the RPC. */
- output = xmlrpc_registry_process_call(
- &env, registryP, NULL,
+ xmlrpc_registry_process_call2(
+ &env, registryP,
XMLRPC_MEMBLOCK_CONTENTS(char, body),
- XMLRPC_MEMBLOCK_SIZE(char, body));
+ XMLRPC_MEMBLOCK_SIZE(char, body),
+ abyssSessionP,
+ &output);
if (!env.fault_occurred) {
/* Send out the result. */
sendXmlData(&env, abyssSessionP,
XMLRPC_MEMBLOCK_CONTENTS(char, output),
- XMLRPC_MEMBLOCK_SIZE(char, output));
+ XMLRPC_MEMBLOCK_SIZE(char, output),
+ wantChunk);
XMLRPC_MEMBLOCK_FREE(char, output);
}
@@ -400,10 +496,13 @@
}
}
if (env.fault_occurred) {
+ uint16_t httpResponseStatus;
if (env.fault_code == XMLRPC_TIMEOUT_ERROR)
- send_error(abyssSessionP, 408); /* 408 Request Timeout */
+ httpResponseStatus = 408; /* Request Timeout */
else
- send_error(abyssSessionP, 500); /* 500 Internal Server Error */
+ httpResponseStatus = 500; /* Internal Server Error */
+
+ sendError(abyssSessionP, httpResponseStatus, env.fault_string);
}
xmlrpc_env_clean(&env);
@@ -425,19 +524,20 @@
that is specific to the Xmlrpc-c handler.
-----------------------------------------------------------------------------*/
xmlrpc_registry * registryP;
- const char * filename; /* malloc'ed */
+ const char * uriPath; /* malloc'ed */
+ bool chunkResponse;
+ /* The handler should chunk its response whenever possible */
};
static void
-termUriHandler(URIHandler2 * const this) {
+termUriHandler(void * const arg) {
- struct uriHandlerXmlrpc * const uriHandlerXmlrpcP = this->userdata;
+ struct uriHandlerXmlrpc * const uriHandlerXmlrpcP = arg;
- free((void*)uriHandlerXmlrpcP->filename);
+ xmlrpc_strfree(uriHandlerXmlrpcP->uriPath);
free(uriHandlerXmlrpcP);
- free(this);
}
@@ -461,52 +561,68 @@
-----------------------------------------------------------------------------*/
struct uriHandlerXmlrpc * const uriHandlerXmlrpcP = this->userdata;
+ const TRequestInfo * requestInfoP;
+
if (trace_abyss)
traceHandlerCalled(abyssSessionP);
- /* Note that abyssSessionP->uri is not the whole URI. It is just
+ SessionGetRequestInfo(abyssSessionP, &requestInfoP);
+
+ /* Note that requestInfoP->uri is not the whole URI. It is just
the "file name" part of it.
*/
- if (strcmp(abyssSessionP->uri, uriHandlerXmlrpcP->filename) != 0)
- /* It's for the filename (e.g. "/RPC2") that we're supposed to
+ if (strcmp(requestInfoP->uri, uriHandlerXmlrpcP->uriPath) != 0)
+ /* It's for the path (e.g. "/RPC2") that we're supposed to
handle.
*/
*handledP = FALSE;
else {
*handledP = TRUE;
- /* We understand only the POST HTTP method. For anything else, return
- "405 Method Not Allowed".
- */
- if (abyssSessionP->method != m_post)
- send_error(abyssSessionP, 405);
+ if (requestInfoP->method != m_post)
+ sendError(abyssSessionP, 405,
+ "POST is the only HTTP method this server understands");
+ /* 405 = Method Not Allowed */
else {
- unsigned int httpError;
- storeCookies(abyssSessionP, &httpError);
- if (httpError)
- send_error(abyssSessionP, httpError);
- else {
- unsigned int httpError;
- validateContentType(abyssSessionP, &httpError);
- if (httpError)
- send_error(abyssSessionP, httpError);
- else {
- unsigned int httpError;
+ const char * error;
+ storeCookies(abyssSessionP, &error);
+ if (error) {
+ sendError(abyssSessionP, 400, error);
+ xmlrpc_strfree(error);
+ } else {
+ const char * error;
+ validateContentType(abyssSessionP, &error);
+ if (error) {
+ sendError(abyssSessionP, 400, error);
+ /* 400 = Bad Request */
+ xmlrpc_strfree(error);
+ } else {
+ const char * error;
+ bool missing;
size_t contentSize;
processContentLength(abyssSessionP,
- &contentSize, &httpError);
- if (httpError)
- send_error(abyssSessionP, httpError);
- else
- processCall(abyssSessionP, contentSize,
- uriHandlerXmlrpcP->registryP, trace_abyss);
+ &contentSize, &missing, &error);
+ if (error) {
+ sendError(abyssSessionP, 400, error);
+ xmlrpc_strfree(error);
+ } else {
+ if (missing)
+ sendError(abyssSessionP, 411, "You must send a "
+ "content-length HTTP header in an "
+ "XML-RPC call.");
+ else
+ processCall(abyssSessionP, contentSize,
+ uriHandlerXmlrpcP->registryP,
+ uriHandlerXmlrpcP->chunkResponse,
+ trace_abyss);
+ }
}
}
}
}
if (trace_abyss)
- fprintf(stderr, "xmlrpc_server_abyss RPC2 handler returning.\n");
+ fprintf(stderr, "xmlrpc_server_abyss URI path handler returning.\n");
}
@@ -519,320 +635,636 @@
*/
static xmlrpc_bool
-xmlrpc_server_abyss_default_handler (TSession * const r) {
+xmlrpc_server_abyss_default_handler(TSession * const sessionP) {
+
+ const TRequestInfo * requestInfoP;
+
+ const char * explanation;
if (trace_abyss)
fprintf(stderr, "xmlrpc_server_abyss default handler called.\n");
- send_error(r, 404);
+ SessionGetRequestInfo(sessionP, &requestInfoP);
+
+ xmlrpc_asprintf(
+ &explanation,
+ "This XML-RPC For C/C++ Abyss XML-RPC server "
+ "responds to only one URI path. "
+ "I don't know what URI path that is, "
+ "but it's not the one you requested: '%s'. (Typically, it's "
+ "'/RPC2')", requestInfoP->uri);
+
+ sendError(sessionP, 404, explanation);
+
+ xmlrpc_strfree(explanation);
return TRUE;
}
-/**************************************************************************
-**
-** The code below was adapted from the main.c file of the Abyss webserver
-** project. In addition to the other copyrights on this file, the following
-** code is also under this copyright:
-**
-** Copyright (C) 2000 by Moez Mahfoudh <mmoez at bigfoot.com>.
-** All rights reserved.
-**
-** Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions
-** are met:
-** 1. Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** 2. Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in the
-** documentation and/or other materials provided with the distribution.
-** 3. The name of the author may not be used to endorse or promote products
-** derived from this software without specific prior written permission.
-**
-** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR 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.
-**
-**************************************************************************/
+static void
+setHandler(xmlrpc_env * const envP,
+ TServer * const srvP,
+ const char * const uriPath,
+ xmlrpc_registry * const registryP,
+ bool const chunkResponse) {
+
+ struct uriHandlerXmlrpc * uriHandlerXmlrpcP;
+ URIHandler2 uriHandler;
+ abyss_bool success;
-#include <time.h>
-#include <fcntl.h>
+ trace_abyss = getenv("XMLRPC_TRACE_ABYSS");
+
+ MALLOCVAR_NOFAIL(uriHandlerXmlrpcP);
-#ifdef _WIN32
-#include <io.h>
-#else
-#include <signal.h>
-#include <sys/wait.h>
-#include <grp.h>
-#endif /* _WIN32 */
+ uriHandlerXmlrpcP->registryP = registryP;
+ uriHandlerXmlrpcP->uriPath = strdup(uriPath);
+ uriHandlerXmlrpcP->chunkResponse = chunkResponse;
+
+ uriHandler.handleReq2 = handleXmlrpcReq;
+ uriHandler.handleReq1 = NULL;
+ uriHandler.userdata = uriHandlerXmlrpcP;
+ uriHandler.init = NULL;
+ uriHandler.term = &termUriHandler;
+ ServerAddHandler2(srvP, &uriHandler, &success);
+ if (!success)
+ xmlrpc_faultf(envP, "Abyss failed to register the Xmlrpc-c request "
+ "handler. ServerAddHandler2() failed.");
-static void
-sigterm(int const sig) {
- TraceExit("Signal %d received. Exiting...\n",sig);
+ if (envP->fault_occurred)
+ free(uriHandlerXmlrpcP);
}
-static void
-sigchld(int const sig ATTR_UNUSED) {
-/*----------------------------------------------------------------------------
- This is a signal handler for a SIGCHLD signal (which informs us that
- one of our child processes has terminated).
- We respond by reaping the zombie process.
+void
+xmlrpc_server_abyss_set_handler(xmlrpc_env * const envP,
+ TServer * const srvP,
+ const char * const uriPath,
+ xmlrpc_registry * const registryP) {
- Implementation note: In some systems, just setting the signal handler
- to SIG_IGN (ignore signal) does this. In others, it doesn't.
------------------------------------------------------------------------------*/
-#ifndef _WIN32
- pid_t pid;
- int status;
-
- /* Reap defunct children until there aren't any more. */
- for (;;) {
- pid = waitpid( (pid_t) -1, &status, WNOHANG );
-
- /* none left */
- if (pid==0)
- break;
-
- if (pid<0) {
- /* because of ptrace */
- if (errno==EINTR)
- continue;
-
- break;
- }
- }
-#endif /* _WIN32 */
+ setHandler(envP, srvP, uriPath, registryP, false);
}
-static TServer globalSrv;
- /* When you use the old interface (xmlrpc_server_abyss_init(), etc.),
- this is the Abyss server to which they refer. Obviously, there can be
- only one Abyss server per program using this interface.
- */
+
+static void
+setHandlers(TServer * const srvP,
+ const char * const uriPath,
+ xmlrpc_registry * const registryP,
+ bool const chunkResponse) {
-void
-xmlrpc_server_abyss_init(int const flags ATTR_UNUSED,
- const char * const config_file) {
+ xmlrpc_env env;
- DateInit();
- MIMETypeInit();
+ xmlrpc_env_init(&env);
- ServerCreate(&globalSrv, "XmlRpcServer", 8080, DEFAULT_DOCS, NULL);
+ trace_abyss = getenv("XMLRPC_TRACE_ABYSS");
+
+ setHandler(&env, srvP, uriPath, registryP, chunkResponse);
- ConfReadServerFile(config_file, &globalSrv);
+ if (env.fault_occurred)
+ abort();
- xmlrpc_server_abyss_init_registry();
- /* Installs /RPC2 handler and default handler that use the
- built-in registry.
- */
+ ServerDefaultHandler(srvP, xmlrpc_server_abyss_default_handler);
- ServerInit(&globalSrv);
+ xmlrpc_env_clean(&env);
}
-static void
-setupSignalHandlers(void) {
-#ifndef _WIN32
- struct sigaction mysigaction;
-
- sigemptyset(&mysigaction.sa_mask);
- mysigaction.sa_flags = 0;
-
- /* These signals abort the program, with tracing */
- mysigaction.sa_handler = sigterm;
- sigaction(SIGTERM, &mysigaction, NULL);
- sigaction(SIGINT, &mysigaction, NULL);
- sigaction(SIGHUP, &mysigaction, NULL);
- sigaction(SIGUSR1, &mysigaction, NULL);
+void
+xmlrpc_server_abyss_set_handlers2(TServer * const srvP,
+ const char * const uriPath,
+ xmlrpc_registry * const registryP) {
- /* This signal indicates connection closed in the middle */
- mysigaction.sa_handler = SIG_IGN;
- sigaction(SIGPIPE, &mysigaction, NULL);
-
- /* This signal indicates a child process (request handler) has died */
- mysigaction.sa_handler = sigchld;
- sigaction(SIGCHLD, &mysigaction, NULL);
-#endif
-}
+ setHandlers(srvP, uriPath, registryP, false);
+}
-static void
-setGroups(void) {
+void
+xmlrpc_server_abyss_set_handlers(TServer * const srvP,
+ xmlrpc_registry * const registryP) {
-#ifdef HAVE_SETGROUPS
- if (setgroups(0, NULL) == (-1))
- TraceExit("Failed to setup the group.");
-#endif
+ setHandlers(srvP, "/RPC2", registryP, false);
}
+/*============================================================================
+ createServer()
+============================================================================*/
+
static void
-daemonize(TServer * const srvP) {
-/*----------------------------------------------------------------------------
- Turn Caller into a daemon (i.e. fork a child, then exit; the child
- returns to Caller).
+setAdditionalServerParms(const xmlrpc_server_abyss_parms * const parmsP,
+ unsigned int const parmSize,
+ TServer * const serverP) {
- NOTE: It's ridiculous, but conventional, for us to do this. It's
- ridiculous because the task of daemonizing is not something
- particular to Xmlrpc-c. It ought to be done by a higher level. In
- fact, it should be done before the Xmlrpc-c server program is even
- execed. The user should run a "daemonize" program that creates a
- daemon which execs the Xmlrpc-c server program.
------------------------------------------------------------------------------*/
-#ifndef _WIN32
- /* Become a daemon */
- switch (fork()) {
- case 0:
- break;
- case -1:
- TraceExit("Unable to become a daemon");
- default:
- /* We are the parent */
- exit(0);
- };
-
- setsid();
-
- /* Change the current user if we are root */
- if (getuid()==0) {
- if (srvP->uid == (uid_t)-1)
- TraceExit("Can't run under root privileges. "
- "Please add a User option in your "
- "Abyss configuration file.");
-
- setGroups();
-
- if (srvP->gid != (gid_t)-1)
- if (setgid(srvP->gid)==(-1))
- TraceExit("Failed to change the group.");
+ /* The following ought to be parameters on ServerCreate(), but it
+ looks like plugging them straight into the TServer structure is
+ the only way to set them.
+ */
-
- if (setuid(srvP->uid) == -1)
- TraceExit("Failed to change the user.");
- };
-
- if (srvP->pidfile!=(-1)) {
- char z[16];
-
- sprintf(z,"%d",getpid());
- FileWrite(&srvP->pidfile,z,strlen(z));
- FileClose(&srvP->pidfile);
- };
-#endif /* _WIN32 */
+ if (parmSize >= XMLRPC_APSIZE(keepalive_timeout) &&
+ parmsP->keepalive_timeout > 0)
+ ServerSetKeepaliveTimeout(serverP, parmsP->keepalive_timeout);
+ if (parmSize >= XMLRPC_APSIZE(keepalive_max_conn) &&
+ parmsP->keepalive_max_conn > 0)
+ ServerSetKeepaliveMaxConn(serverP, parmsP->keepalive_max_conn);
+ if (parmSize >= XMLRPC_APSIZE(timeout) &&
+ parmsP->timeout > 0)
+ ServerSetTimeout(serverP, parmsP->timeout);
+ if (parmSize >= XMLRPC_APSIZE(dont_advertise))
+ ServerSetAdvertise(serverP, !parmsP->dont_advertise);
}
static void
-runServerDaemon(TServer * const srvP,
- runfirstFn const runfirst,
- void * const runfirstArg) {
-
- setupSignalHandlers();
+extractServerCreateParms(
+ xmlrpc_env * const envP,
+ const xmlrpc_server_abyss_parms * const parmsP,
+ unsigned int const parmSize,
+ bool * const socketBoundP,
+ unsigned int * const portNumberP,
+ TOsSocket * const socketFdP,
+ const char ** const logFileNameP) {
+
- daemonize(srvP);
-
- /* We run the user supplied runfirst after forking, but before accepting
- connections (helpful when running with threads)
- */
- if (runfirst)
- runfirst(runfirstArg);
+ if (parmSize >= XMLRPC_APSIZE(socket_bound))
+ *socketBoundP = parmsP->socket_bound;
+ else
+ *socketBoundP = FALSE;
- ServerRun(srvP);
+ if (*socketBoundP) {
+ if (parmSize < XMLRPC_APSIZE(socket_handle))
+ xmlrpc_faultf(envP, "socket_bound is true, but server parameter "
+ "structure does not contain socket_handle (it's too "
+ "short)");
+ else
+ *socketFdP = parmsP->socket_handle;
+ } else {
+ if (parmSize >= XMLRPC_APSIZE(port_number))
+ *portNumberP = parmsP->port_number;
+ else
+ *portNumberP = 8080;
- /* We can't exist here because ServerRun doesn't return */
- XMLRPC_ASSERT(FALSE);
+ if (*portNumberP > 0xffff)
+ xmlrpc_faultf(envP,
+ "TCP port number %u exceeds the maximum possible "
+ "TCP port number (65535)",
+ *portNumberP);
+ }
+ if (!envP->fault_occurred) {
+ if (parmSize >= XMLRPC_APSIZE(log_file_name) &&
+ parmsP->log_file_name)
+ *logFileNameP = strdup(parmsP->log_file_name);
+ else
+ *logFileNameP = NULL;
+ }
}
-void
-xmlrpc_server_abyss_run_first(runfirstFn const runfirst,
- void * const runfirstArg) {
-
- runServerDaemon(&globalSrv, runfirst, runfirstArg);
+static void
+chanSwitchCreateOsSocket(TOsSocket const socketFd,
+ TChanSwitch ** const chanSwitchPP,
+ const char ** const errorP) {
+
+#ifdef WIN32
+ ChanSwitchWinCreateWinsock(socketFd, chanSwitchPP, errorP);
+#else
+ ChanSwitchUnixCreateFd(socketFd, chanSwitchPP, errorP);
+#endif
+
}
-void
-xmlrpc_server_abyss_run(void) {
- runServerDaemon(&globalSrv, NULL, NULL);
+static void
+createServerBoundSocket(xmlrpc_env * const envP,
+ TOsSocket const socketFd,
+ const char * const logFileName,
+ TServer * const serverP,
+ TChanSwitch ** const chanSwitchPP) {
+
+ TChanSwitch * chanSwitchP;
+ const char * error;
+
+ chanSwitchCreateOsSocket(socketFd, &chanSwitchP, &error);
+ if (error) {
+ xmlrpc_faultf(envP, "Unable to create Abyss socket out of "
+ "file descriptor %d. %s", socketFd, error);
+ xmlrpc_strfree(error);
+ } else {
+ ServerCreateSwitch(serverP, chanSwitchP, &error);
+ if (error) {
+ xmlrpc_faultf(envP, "Abyss failed to create server. %s", error);
+ xmlrpc_strfree(error);
+ } else {
+ *chanSwitchPP = chanSwitchP;
+
+ ServerSetName(serverP, "XmlRpcServer");
+
+ if (logFileName)
+ ServerSetLogFileName(serverP, logFileName);
+ }
+ if (envP->fault_occurred)
+ ChanSwitchDestroy(chanSwitchP);
+ }
}
+static void
+createServerBare(xmlrpc_env * const envP,
+ const xmlrpc_server_abyss_parms * const parmsP,
+ unsigned int const parmSize,
+ TServer * const serverP,
+ TChanSwitch ** const chanSwitchPP) {
+/*----------------------------------------------------------------------------
+ Create a bare server. It will need further setup before it is ready
+ to use.
+-----------------------------------------------------------------------------*/
+ bool socketBound;
+ unsigned int portNumber;
+ TOsSocket socketFd;
+ const char * logFileName;
+
+ extractServerCreateParms(envP, parmsP, parmSize,
+ &socketBound, &portNumber, &socketFd,
+ &logFileName);
+
+ if (!envP->fault_occurred) {
+ if (socketBound)
+ createServerBoundSocket(envP, socketFd, logFileName,
+ serverP, chanSwitchPP);
+ else {
+ ServerCreate(serverP, "XmlRpcServer", portNumber, DEFAULT_DOCS,
+ logFileName);
+
+ *chanSwitchPP = NULL;
+ }
+ if (logFileName)
+ xmlrpc_strfree(logFileName);
+ }
+}
+
+
+
+static bool
+chunkResponseParm(const xmlrpc_server_abyss_parms * const parmsP,
+ unsigned int const parmSize) {
+
+ return
+ parmSize >= XMLRPC_APSIZE(chunk_response) &&
+ parmsP->chunk_response;
+}
+
+
+
+static const char *
+uriPathParm(const xmlrpc_server_abyss_parms * const parmsP,
+ unsigned int const parmSize) {
+
+ const char * uriPath;
+
+ if (parmSize >= XMLRPC_APSIZE(uri_path) && parmsP->uri_path)
+ uriPath = parmsP->uri_path;
+ else
+ uriPath = "/RPC2";
+
+ return uriPath;
+}
+
+
+
+static void
+createServer(xmlrpc_env * const envP,
+ const xmlrpc_server_abyss_parms * const parmsP,
+ unsigned int const parmSize,
+ TServer * const abyssServerP,
+ TChanSwitch ** const chanSwitchPP) {
+
+ createServerBare(envP, parmsP, parmSize, abyssServerP, chanSwitchPP);
+
+ if (!envP->fault_occurred) {
+ setAdditionalServerParms(parmsP, parmSize, abyssServerP);
+
+ setHandlers(abyssServerP, uriPathParm(parmsP, parmSize),
+ parmsP->registryP,
+ chunkResponseParm(parmsP, parmSize));
+
+ ServerInit(abyssServerP);
+ }
+}
+
+
+
+static bool
+enableShutdownParm(const xmlrpc_server_abyss_parms * const parmsP,
+ unsigned int const parmSize) {
+
+ return
+ parmSize >= XMLRPC_APSIZE(enable_shutdown) &&
+ parmsP->enable_shutdown;
+}
+
+
+
+static xmlrpc_server_shutdown_fn shutdownAbyss;
+
+static void
+shutdownAbyss(xmlrpc_env * const faultP,
+ void * const context,
+ const char * const comment ATTR_UNUSED,
+ void * const callInfo ATTR_UNUSED) {
+/*----------------------------------------------------------------------------
+ Tell Abyss to wrap up whatever it's doing and shut down.
+
+ This is a server shutdown function to be registered in the method
+ registry, for use by the 'system.shutdown' system method.
+
+ After we return, Abyss will finish up the system.shutdown and any
+ other connections that are in progress, then the call to
+ ServerRun() etc. will return.
+
+ *faultP is the result of the shutdown request, not whether we
+ succeeded or failed. We are not allowed to fail.
+-----------------------------------------------------------------------------*/
+ xmlrpc_server_abyss_t * const serverP = context;
+
+ xmlrpc_env_init(faultP);
+
+ if (!serverP->shutdownEnabled)
+ xmlrpc_env_set_fault_formatted(
+ faultP, XMLRPC_REQUEST_REFUSED_ERROR,
+ "Shutdown by client is disabled on this server.");
+ else
+ ServerTerminate(&serverP->abyssServer);
+}
+
+
+
+/*=============================================================================
+ xmlrpc_server_abyss object methods
+=============================================================================*/
+
void
-xmlrpc_server_abyss_set_handler(xmlrpc_env * const envP,
- TServer * const srvP,
- const char * const filename,
- xmlrpc_registry * const registryP) {
+xmlrpc_server_abyss_create(xmlrpc_env * const envP,
+ const xmlrpc_server_abyss_parms * const parmsP,
+ unsigned int const parmSize,
+ xmlrpc_server_abyss_t ** const serverPP) {
+
+ xmlrpc_server_abyss_t * serverP;
+
+ XMLRPC_ASSERT_ENV_OK(envP);
+
+ validateGlobalInit(envP);
+
+ if (!envP->fault_occurred) {
+ if (parmSize < XMLRPC_APSIZE(registryP))
+ xmlrpc_faultf(envP,
+ "You must specify members at least up through "
+ "'registryP' in the server parameters argument. "
+ "That would mean the parameter size would be >= %lu "
+ "but you specified a size of %u",
+ XMLRPC_APSIZE(registryP), parmSize);
+ else {
+ MALLOCVAR(serverP);
+
+ if (serverP == NULL)
+ xmlrpc_faultf(envP, "Unable to allocate memory for "
+ "server descriptor.");
+ else {
+ createServer(envP, parmsP, parmSize,
+ &serverP->abyssServer, &serverP->chanSwitchP);
+
+ if (!envP->fault_occurred) {
+ serverP->shutdownEnabled =
+ enableShutdownParm(parmsP, parmSize);
+
+ xmlrpc_registry_set_shutdown(
+ parmsP->registryP, &shutdownAbyss, serverP);
+
+ if (envP->fault_occurred)
+ free(serverP);
+ else
+ *serverPP = serverP;
+ }
+ }
+ }
+ }
+}
+
+
+
+void
+xmlrpc_server_abyss_destroy(xmlrpc_server_abyss_t * const serverP) {
+
+ XMLRPC_ASSERT(globallyInitialized);
+
+ ServerFree(&serverP->abyssServer);
+
+ if (serverP->chanSwitchP)
+ ChanSwitchDestroy(serverP->chanSwitchP);
+
+ free(serverP);
+}
+
+
+
+void
+xmlrpc_server_abyss_use_sigchld(xmlrpc_server_abyss_t * const serverP) {
+
+ ServerUseSigchld(&serverP->abyssServer);
+}
+
+
+
+void
+xmlrpc_server_abyss_run_server(xmlrpc_env * const envP ATTR_UNUSED,
+ xmlrpc_server_abyss_t * const serverP) {
+
+ ServerRun(&serverP->abyssServer);
+}
+
+
+
+void
+xmlrpc_server_abyss_terminate(
+ xmlrpc_env * const envP ATTR_UNUSED,
+ xmlrpc_server_abyss_t * const serverP) {
+
+ ServerTerminate(&serverP->abyssServer);
+}
+
+
+
+void
+xmlrpc_server_abyss_reset_terminate(
+ xmlrpc_env * const envP ATTR_UNUSED,
+ xmlrpc_server_abyss_t * const serverP) {
+
+ ServerResetTerminate(&serverP->abyssServer);
+}
+
+
+
+static void
+sigchld(int const signalClass ATTR_UNUSED) {
+/*----------------------------------------------------------------------------
+ This is a signal handler for a SIGCHLD signal (which informs us that
+ one of our child processes has terminated).
+
+ The only child processes we have are those that belong to the Abyss
+ server (and then only if the Abyss server was configured to use
+ forking as a threading mechanism), so we respond by passing the
+ signal on to the Abyss server.
+-----------------------------------------------------------------------------*/
+#ifndef WIN32
+ bool childrenLeft;
+ bool error;
+
+ assert(signalClass == SIGCHLD);
+
+ error = false;
+ childrenLeft = true; /* initial assumption */
- struct uriHandlerXmlrpc * uriHandlerXmlrpcP;
- URIHandler2 * uriHandlerP;
- abyss_bool success;
+ /* Reap defunct children until there aren't any more. */
+ while (childrenLeft && !error) {
+ int status;
+ pid_t pid;
+
+ pid = waitpid((pid_t) -1, &status, WNOHANG);
+
+ if (pid == 0)
+ childrenLeft = false;
+ else if (pid < 0) {
+ /* because of ptrace */
+ if (errno != EINTR)
+ error = true;
+ } else
+ ServerHandleSigchld(pid);
+ }
+#endif /* WIN32 */
+}
- trace_abyss = getenv("XMLRPC_TRACE_ABYSS");
-
- MALLOCVAR_NOFAIL(uriHandlerP);
- uriHandlerP->handleReq2 = handleXmlrpcReq;
- uriHandlerP->handleReq1 = NULL;
- uriHandlerP->init = NULL;
- uriHandlerP->term = &termUriHandler;
+struct xmlrpc_server_abyss_sig {
- MALLOCVAR_NOFAIL(uriHandlerXmlrpcP);
+ /* A description of the state of the process' signal handlers before
+ functions in this library messed with them; useful for restoring
+ them later.
+ */
+#ifndef WIN32
+ struct sigaction pipe;
+ struct sigaction chld;
+#else
+ int dummy;
+#endif
+};
- uriHandlerXmlrpcP->registryP = registryP;
- uriHandlerXmlrpcP->filename = strdup(filename);
- uriHandlerP->userdata = uriHandlerXmlrpcP;
- ServerAddHandler2(srvP, uriHandlerP, &success);
+static void
+setupSignalHandlers(xmlrpc_server_abyss_sig * const oldHandlersP) {
+#ifndef WIN32
+ struct sigaction mysigaction;
+
+ sigemptyset(&mysigaction.sa_mask);
+ mysigaction.sa_flags = 0;
+
+ /* This signal indicates connection closed in the middle */
+ mysigaction.sa_handler = SIG_IGN;
+ sigaction(SIGPIPE, &mysigaction, &oldHandlersP->pipe);
+
+ /* This signal indicates a child process (request handler) has died */
+ mysigaction.sa_handler = sigchld;
+ sigaction(SIGCHLD, &mysigaction, &oldHandlersP->chld);
+#endif
+}
- free(uriHandlerP);
- if (!success)
- xmlrpc_faultf(envP, "Abyss failed to register the Xmlrpc-c request "
- "handler. ServerAddHandler2() failed.");
+
+static void
+restoreSignalHandlers(const xmlrpc_server_abyss_sig * const oldHandlersP) {
+#ifndef WIN32
+
+ sigaction(SIGPIPE, &oldHandlersP->pipe, NULL);
+ sigaction(SIGCHLD, &oldHandlersP->chld, NULL);
+
+#endif
}
void
-xmlrpc_server_abyss_set_handlers(TServer * const srvP,
- xmlrpc_registry * const registryP) {
+xmlrpc_server_abyss_setup_sig(
+ xmlrpc_env * const envP,
+ xmlrpc_server_abyss_t * const serverP,
+ xmlrpc_server_abyss_sig ** const oldHandlersPP) {
- xmlrpc_env env;
+ xmlrpc_server_abyss_sig * oldHandlersP;
- xmlrpc_env_init(&env);
+ XMLRPC_ASSERT_ENV_OK(envP);
- trace_abyss = getenv("XMLRPC_TRACE_ABYSS");
+ validateGlobalInit(envP);
+
+ if (!envP->fault_occurred) {
+ MALLOCVAR(oldHandlersP);
+
+ if (oldHandlersP == NULL)
+ xmlrpc_faultf(envP, "Unable to allocate memory to save signal "
+ "handling state.");
+ else {
+ setupSignalHandlers(oldHandlersP);
+
+ xmlrpc_server_abyss_use_sigchld(serverP);
+ }
+ if (oldHandlersPP)
+ *oldHandlersPP = oldHandlersP;
+ else
+ free(oldHandlersP);
+ }
+}
+
+
+
+void
+xmlrpc_server_abyss_restore_sig(
+ const xmlrpc_server_abyss_sig * const oldHandlersP) {
+
+ restoreSignalHandlers(oldHandlersP);
+}
- xmlrpc_server_abyss_set_handler(&env, srvP, "/RPC2", registryP);
+
+
+static void
+runServerDaemon(TServer * const serverP,
+ runfirstFn const runfirst,
+ void * const runfirstArg) {
+
+ xmlrpc_server_abyss_sig oldHandlers;
+
+ setupSignalHandlers(&oldHandlers);
+
+ ServerUseSigchld(serverP);
+
+ ServerDaemonize(serverP);
- if (env.fault_occurred)
- abort();
+ /* We run the user supplied runfirst after forking, but before accepting
+ connections (helpful when running with threads)
+ */
+ if (runfirst)
+ runfirst(runfirstArg);
- ServerDefaultHandler(srvP, xmlrpc_server_abyss_default_handler);
+ ServerRun(serverP);
+
+ restoreSignalHandlers(&oldHandlers);
}
@@ -840,7 +1272,7 @@
static void
oldHighLevelAbyssRun(xmlrpc_env * const envP ATTR_UNUSED,
const xmlrpc_server_abyss_parms * const parmsP,
- unsigned int const parm_size) {
+ unsigned int const parmSize) {
/*----------------------------------------------------------------------------
This is the old deprecated interface, where the caller of the
xmlrpc_server_abyss API supplies an Abyss configuration file and
@@ -852,103 +1284,58 @@
Abyss parameters in memory. That's a more conventional and
flexible API.
-----------------------------------------------------------------------------*/
- TServer srv;
+ TServer server;
runfirstFn runfirst;
void * runfirstArg;
- DateInit();
- MIMETypeInit();
-
- ServerCreate(&srv, "XmlRpcServer", 8080, DEFAULT_DOCS, NULL);
+ ServerCreate(&server, "XmlRpcServer", 8080, DEFAULT_DOCS, NULL);
+
+ assert(parmSize >= XMLRPC_APSIZE(config_file_name));
- ConfReadServerFile(parmsP->config_file_name, &srv);
+ ConfReadServerFile(parmsP->config_file_name, &server);
- xmlrpc_server_abyss_set_handlers(&srv, parmsP->registryP);
+ assert(parmSize >= XMLRPC_APSIZE(registryP));
+
+ setHandlers(&server, "/RPC2", parmsP->registryP, false);
- ServerInit(&srv);
+ ServerInit(&server);
- if (parm_size >= XMLRPC_APSIZE(runfirst_arg)) {
+ if (parmSize >= XMLRPC_APSIZE(runfirst_arg)) {
runfirst = parmsP->runfirst;
runfirstArg = parmsP->runfirst_arg;
} else {
runfirst = NULL;
runfirstArg = NULL;
}
- runServerDaemon(&srv, runfirst, runfirstArg);
-}
-
-
-
-static void
-setAdditionalServerParms(const xmlrpc_server_abyss_parms * const parmsP,
- unsigned int const parm_size,
- TServer * const srvP) {
-
- /* The following ought to be parameters on ServerCreate(), but it
- looks like plugging them straight into the TServer structure is
- the only way to set them.
- */
+ runServerDaemon(&server, runfirst, runfirstArg);
- if (parm_size >= XMLRPC_APSIZE(keepalive_timeout) &&
- parmsP->keepalive_timeout > 0)
- srvP->keepalivetimeout = parmsP->keepalive_timeout;
- if (parm_size >= XMLRPC_APSIZE(keepalive_max_conn) &&
- parmsP->keepalive_max_conn > 0)
- srvP->keepalivemaxconn = parmsP->keepalive_max_conn;
- if (parm_size >= XMLRPC_APSIZE(timeout) &&
- parmsP->timeout > 0)
- srvP->timeout = parmsP->timeout;
- if (parm_size >= XMLRPC_APSIZE(dont_advertise))
- srvP->advertise = !parmsP->dont_advertise;
+ ServerFree(&server);
}
static void
-normalLevelAbyssRun(xmlrpc_env * const envP ATTR_UNUSED,
+normalLevelAbyssRun(xmlrpc_env * const envP,
const xmlrpc_server_abyss_parms * const parmsP,
- unsigned int const parm_size) {
+ unsigned int const parmSize) {
- unsigned int portNumber;
-
- DateInit();
- MIMETypeInit();
-
- if (parm_size >= XMLRPC_APSIZE(port_number))
- portNumber = parmsP->port_number;
- else
- portNumber = 8080;
+ xmlrpc_server_abyss_t * serverP;
- if (portNumber > 0xffff)
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR,
- "TCP port number %u exceeds the maximum possible "
- "TCP port number (65535)",
- portNumber);
- else {
- TServer srv;
- const char * logFileName;
+ xmlrpc_server_abyss_create(envP, parmsP, parmSize, &serverP);
- if (parm_size >= XMLRPC_APSIZE(log_file_name))
- logFileName = parmsP->log_file_name;
- else
- logFileName = NULL;
+ if (!envP->fault_occurred) {
+ xmlrpc_server_abyss_sig * oldHandlersP;
- ServerCreate(&srv, "XmlRpcServer", portNumber, DEFAULT_DOCS,
- logFileName);
+ xmlrpc_server_abyss_setup_sig(envP, serverP, &oldHandlersP);
- setAdditionalServerParms(parmsP, parm_size, &srv);
+ if (!envP->fault_occurred) {
+ xmlrpc_server_abyss_run_server(envP, serverP);
- xmlrpc_server_abyss_set_handlers(&srv, parmsP->registryP);
-
- ServerInit(&srv);
-
- setupSignalHandlers();
-
- ServerRun(&srv);
+ xmlrpc_server_abyss_restore_sig(oldHandlersP);
- /* We can't exist here because ServerRun doesn't return */
- XMLRPC_ASSERT(FALSE);
+ free(oldHandlersP);
+ }
+ xmlrpc_server_abyss_destroy(serverP);
}
}
@@ -957,37 +1344,61 @@
void
xmlrpc_server_abyss(xmlrpc_env * const envP,
const xmlrpc_server_abyss_parms * const parmsP,
- unsigned int const parm_size) {
-
+ unsigned int const parmSize) {
+/*----------------------------------------------------------------------------
+ Note that this is not re-entrant and not thread-safe, due to the
+ global library initialization. If you want to run a server inside
+ a thread of a multi-threaded program, use
+ xmlrpc_server_abyss_create() instead. As required by that
+ subroutine, your program will contain a call to
+ xmlrpc_server_abyss_init() early in your program, when it is only
+ one thread.
+-----------------------------------------------------------------------------*/
XMLRPC_ASSERT_ENV_OK(envP);
- if (parm_size < XMLRPC_APSIZE(registryP))
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR,
- "You must specify members at least up through "
- "'registryP' in the server parameters argument. "
- "That would mean the parameter size would be >= %u "
- "but you specified a size of %u",
- XMLRPC_APSIZE(registryP), parm_size);
- else {
- if (parmsP->config_file_name)
- oldHighLevelAbyssRun(envP, parmsP, parm_size);
- else
- normalLevelAbyssRun(envP, parmsP, parm_size);
+ xmlrpc_server_abyss_global_init(envP);
+
+ if (!envP->fault_occurred) {
+ if (parmSize < XMLRPC_APSIZE(registryP))
+ xmlrpc_faultf(envP,
+ "You must specify members at least up through "
+ "'registryP' in the server parameters argument. "
+ "That would mean the parameter size would be >= %lu "
+ "but you specified a size of %u",
+ XMLRPC_APSIZE(registryP), parmSize);
+ else {
+ if (parmsP->config_file_name)
+ oldHighLevelAbyssRun(envP, parmsP, parmSize);
+ else
+ normalLevelAbyssRun(envP, parmsP, parmSize);
+
+ }
+ xmlrpc_server_abyss_global_term();
}
}
/*=========================================================================
-** XML-RPC Server Method Registry
-**=========================================================================
-** A simple front-end to our method registry.
+ XML-RPC Server Method Registry
+
+ This is an old deprecated form of the server facilities that uses
+ global variables.
+=========================================================================*/
+
+/* These global variables must be treated as read-only after the
+ server has started.
*/
-/* XXX - This variable is *not* currently threadsafe. Once the server has
-** been started, it must be treated as read-only. */
-static xmlrpc_registry *builtin_registryP;
+static TServer globalSrv;
+ /* When you use the old interface (xmlrpc_server_abyss_init(), etc.),
+ this is the Abyss server to which they refer. Obviously, there can be
+ only one Abyss server per program using this interface.
+ */
+
+static xmlrpc_registry * builtin_registryP;
+
+
void
xmlrpc_server_abyss_init_registry(void) {
@@ -1008,7 +1419,7 @@
die_if_fault_occurred(&env);
xmlrpc_env_clean(&env);
- xmlrpc_server_abyss_set_handlers(&globalSrv, builtin_registryP);
+ setHandlers(&globalSrv, "/RPC2", builtin_registryP, false);
}
@@ -1027,9 +1438,9 @@
/* A quick & easy shorthand for adding a method. */
void
-xmlrpc_server_abyss_add_method (char * const method_name,
- xmlrpc_method const method,
- void * const user_data) {
+xmlrpc_server_abyss_add_method(char * const method_name,
+ xmlrpc_method const method,
+ void * const user_data) {
xmlrpc_env env;
xmlrpc_env_init(&env);
@@ -1042,11 +1453,11 @@
void
-xmlrpc_server_abyss_add_method_w_doc (char * const method_name,
- xmlrpc_method const method,
- void * const user_data,
- char * const signature,
- char * const help) {
+xmlrpc_server_abyss_add_method_w_doc(char * const method_name,
+ xmlrpc_method const method,
+ void * const user_data,
+ char * const signature,
+ char * const help) {
xmlrpc_env env;
xmlrpc_env_init(&env);
@@ -1059,6 +1470,40 @@
+void
+xmlrpc_server_abyss_init(int const flags ATTR_UNUSED,
+ const char * const config_file) {
+
+ ServerCreate(&globalSrv, "XmlRpcServer", 8080, DEFAULT_DOCS, NULL);
+
+ ConfReadServerFile(config_file, &globalSrv);
+
+ xmlrpc_server_abyss_init_registry();
+ /* Installs /RPC2 handler and default handler that use the
+ built-in registry.
+ */
+
+ ServerInit(&globalSrv);
+}
+
+
+
+void
+xmlrpc_server_abyss_run_first(runfirstFn const runfirst,
+ void * const runfirstArg) {
+
+ runServerDaemon(&globalSrv, runfirst, runfirstArg);
+}
+
+
+
+void
+xmlrpc_server_abyss_run(void) {
+ runServerDaemon(&globalSrv, NULL, NULL);
+}
+
+
+
/*
** Copyright (C) 2001 by First Peer, Inc. All rights reserved.
**
Modified: freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_server_cgi.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_server_cgi.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_server_cgi.c Fri May 23 16:56:24 2008
@@ -237,8 +237,8 @@
input_size = XMLRPC_TYPED_MEM_BLOCK_SIZE(char, input);
/* Process our call. */
- output = xmlrpc_registry_process_call(&env, registryP, NULL,
- input_data, input_size);
+ xmlrpc_registry_process_call2(&env, registryP,
+ input_data, input_size, NULL, &output);
XMLRPC_FAIL_IF_FAULT(&env);
output_data = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, output);
output_size = XMLRPC_TYPED_MEM_BLOCK_SIZE(char, output);
Added: freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_server_info.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_server_info.c Fri May 23 16:56:24 2008
@@ -0,0 +1,343 @@
+/*=============================================================================
+ xmlrpc_server_info
+===============================================================================
+ The xmlrpc_server_info class.
+
+ By Bryan Henderson, San Jose CA 2007.10.17.
+
+ Contributed to the public domain by its author
+
+ The xmlrpc_server_info class was originally just supposed to be
+ information about an HTTP server, hence the name. But we think of it
+ now as a generic carriage parameter, as in the C++ library. In
+ the future, it should be a union or maybe contain an opaque pointer
+ to the carriage parameter for a particular kind of transport. That
+ way, the client XML transports can be more than just HTTP XML
+ transports.
+=============================================================================*/
+
+#include "bool.h"
+#include "mallocvar.h"
+
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/base_int.h"
+#include "xmlrpc-c/string_int.h"
+#include "xmlrpc-c/client.h"
+#include "xmlrpc-c/client_int.h"
+
+
+
+xmlrpc_server_info *
+xmlrpc_server_info_new(xmlrpc_env * const envP,
+ const char * const serverUrl) {
+
+ xmlrpc_server_info * serverInfoP;
+
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT_PTR_OK(serverUrl);
+
+ MALLOCVAR(serverInfoP);
+ if (serverInfoP == NULL)
+ xmlrpc_faultf(envP, "Couldn't allocate memory for xmlrpc_server_info");
+ else {
+ serverInfoP->serverUrl = strdup(serverUrl);
+ if (serverInfoP->serverUrl == NULL)
+ xmlrpc_faultf(envP, "Couldn't allocate memory for server URL");
+ else {
+ serverInfoP->allowedAuth.basic = false;
+ serverInfoP->allowedAuth.digest = false;
+ serverInfoP->allowedAuth.gssnegotiate = false;
+ serverInfoP->allowedAuth.ntlm = false;
+ serverInfoP->userNamePw = NULL;
+ serverInfoP->basicAuthHdrValue = NULL;
+ if (envP->fault_occurred)
+ xmlrpc_strfree(serverInfoP->serverUrl);
+ }
+ if (envP->fault_occurred)
+ free(serverInfoP);
+ }
+ return serverInfoP;
+}
+
+
+
+static void
+copyUserNamePw(xmlrpc_env * const envP,
+ const char * const src,
+ const char ** const dstP) {
+
+ if (src == NULL)
+ *dstP = NULL;
+ else {
+ *dstP = strdup(src);
+ if (*dstP == NULL)
+ xmlrpc_faultf(envP, "Couldn't allocate memory for user name/pw");
+ }
+}
+
+
+
+static void
+freeIfNonNull(const char * const arg) {
+
+ if (arg)
+ xmlrpc_strfree(arg);
+}
+
+
+
+static void
+copyBasicAuthHdrValue(xmlrpc_env * const envP,
+ const char * const src,
+ const char ** const dstP) {
+
+ if (src == NULL)
+ *dstP = NULL;
+ else {
+ *dstP = strdup(src);
+ if (*dstP == NULL)
+ xmlrpc_faultf(envP, "Couldn't allocate memory "
+ "for authentication header value");
+ }
+}
+
+
+
+static void
+copyServerInfoContent(xmlrpc_env * const envP,
+ xmlrpc_server_info * const dstP,
+ const xmlrpc_server_info * const srcP) {
+
+ dstP->serverUrl = strdup(srcP->serverUrl);
+ if (dstP->serverUrl == NULL)
+ xmlrpc_faultf(envP, "Couldn't allocate memory for server URL");
+ else {
+ copyUserNamePw(envP, srcP->userNamePw, &dstP->userNamePw);
+
+ if (!envP->fault_occurred) {
+ copyBasicAuthHdrValue(envP, srcP->basicAuthHdrValue,
+ &dstP->basicAuthHdrValue);
+
+ if (!envP->fault_occurred) {
+ dstP->allowedAuth.basic =
+ srcP->allowedAuth.basic;
+ dstP->allowedAuth.digest =
+ srcP->allowedAuth.digest;
+ dstP->allowedAuth.gssnegotiate =
+ srcP->allowedAuth.gssnegotiate;
+ dstP->allowedAuth.ntlm =
+ srcP->allowedAuth.ntlm;
+
+ if (envP->fault_occurred)
+ freeIfNonNull(dstP->basicAuthHdrValue);
+ }
+ if (envP->fault_occurred)
+ freeIfNonNull(dstP->userNamePw);
+ }
+ if (envP->fault_occurred)
+ xmlrpc_strfree(dstP->serverUrl);
+ }
+}
+
+
+
+xmlrpc_server_info *
+xmlrpc_server_info_copy(xmlrpc_env * const envP,
+ xmlrpc_server_info * const srcP) {
+
+ xmlrpc_server_info * serverInfoP;
+
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT_PTR_OK(srcP);
+
+ MALLOCVAR(serverInfoP);
+ if (serverInfoP == NULL)
+ xmlrpc_faultf(envP,
+ "Couldn't allocate memory for xmlrpc_server_info");
+ else {
+ copyServerInfoContent(envP, serverInfoP, srcP);
+
+ if (envP->fault_occurred)
+ free(serverInfoP);
+ }
+ return serverInfoP;
+}
+
+
+
+void
+xmlrpc_server_info_free(xmlrpc_server_info * const serverInfoP) {
+
+ XMLRPC_ASSERT_PTR_OK(serverInfoP);
+ XMLRPC_ASSERT(serverInfoP->serverUrl != XMLRPC_BAD_POINTER);
+
+ if (serverInfoP->userNamePw)
+ xmlrpc_strfree(serverInfoP->userNamePw);
+ serverInfoP->userNamePw = XMLRPC_BAD_POINTER;
+
+ if (serverInfoP->basicAuthHdrValue)
+ xmlrpc_strfree(serverInfoP->basicAuthHdrValue);
+ serverInfoP->basicAuthHdrValue = XMLRPC_BAD_POINTER;
+
+ xmlrpc_strfree(serverInfoP->serverUrl);
+ serverInfoP->serverUrl = XMLRPC_BAD_POINTER;
+
+ free(serverInfoP);
+}
+
+
+
+void
+xmlrpc_server_info_set_user(xmlrpc_env * const envP,
+ xmlrpc_server_info * const serverInfoP,
+ const char * const username,
+ const char * const password) {
+
+ const char * userNamePw;
+ xmlrpc_mem_block * userNamePw64;
+
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT_PTR_OK(serverInfoP);
+ XMLRPC_ASSERT_PTR_OK(username);
+ XMLRPC_ASSERT_PTR_OK(password);
+
+ xmlrpc_asprintf(&userNamePw, "%s:%s", username, password);
+
+ userNamePw64 =
+ xmlrpc_base64_encode_without_newlines(envP,
+ (unsigned char*) userNamePw,
+ strlen(userNamePw));
+ if (!envP->fault_occurred) {
+ const char * const data = XMLRPC_MEMBLOCK_CONTENTS(char, userNamePw64);
+ size_t const len = XMLRPC_MEMBLOCK_SIZE(char, userNamePw64);
+ const char * const authType = "Basic ";
+
+ char * hdrValue;
+
+ hdrValue = malloc(strlen(authType) + len + 1);
+ if (hdrValue == NULL)
+ xmlrpc_faultf(envP, "Could not allocate memory to store "
+ "authorization header value.");
+ else {
+ strcpy(hdrValue, authType);
+ strncat(hdrValue, data, len);
+
+ if (serverInfoP->basicAuthHdrValue)
+ xmlrpc_strfree(serverInfoP->basicAuthHdrValue);
+
+ serverInfoP->basicAuthHdrValue = hdrValue;
+ }
+ XMLRPC_MEMBLOCK_FREE(char, userNamePw64);
+ }
+ serverInfoP->userNamePw = userNamePw;
+}
+
+
+
+void
+xmlrpc_server_info_set_basic_auth(xmlrpc_env * const envP,
+ xmlrpc_server_info * const serverInfoP,
+ const char * const username,
+ const char * const password) {
+
+ xmlrpc_server_info_set_user(envP, serverInfoP, username, password);
+
+ if (!envP->fault_occurred) {
+ serverInfoP->allowedAuth.basic = true;
+ serverInfoP->allowedAuth.digest = false;
+ serverInfoP->allowedAuth.gssnegotiate = false;
+ serverInfoP->allowedAuth.ntlm = false;
+ }
+}
+
+
+
+void
+xmlrpc_server_info_allow_auth_basic(xmlrpc_env * const envP,
+ xmlrpc_server_info * const sP) {
+
+ if (sP->userNamePw == NULL)
+ xmlrpc_faultf(envP, "You must set username/password with "
+ "xmlrpc_server_info_set_user()");
+ else
+ sP->allowedAuth.basic = true;
+}
+
+
+
+void
+xmlrpc_server_info_disallow_auth_basic(
+ xmlrpc_env * const envP ATTR_UNUSED,
+ xmlrpc_server_info * const sP) {
+
+ sP->allowedAuth.basic = false;
+}
+
+
+
+void
+xmlrpc_server_info_allow_auth_digest(xmlrpc_env * const envP,
+ xmlrpc_server_info * const sP) {
+
+ if (sP->userNamePw == NULL)
+ xmlrpc_faultf(envP, "You must set username/password with "
+ "xmlrpc_server_info_set_user()");
+ else
+ sP->allowedAuth.digest = true;
+}
+
+
+
+void
+xmlrpc_server_info_disallow_auth_digest(
+ xmlrpc_env * const envP ATTR_UNUSED,
+ xmlrpc_server_info * const sP) {
+
+ sP->allowedAuth.digest = false;
+}
+
+
+
+void
+xmlrpc_server_info_allow_auth_negotiate(xmlrpc_env * const envP,
+ xmlrpc_server_info * const sP) {
+
+ if (sP->userNamePw == NULL)
+ xmlrpc_faultf(envP, "You must set username/password with "
+ "xmlrpc_server_info_set_user()");
+ else
+ sP->allowedAuth.gssnegotiate = true;
+}
+
+
+
+void
+xmlrpc_server_info_disallow_auth_negotiate(
+ xmlrpc_env * const envP ATTR_UNUSED,
+ xmlrpc_server_info * const sP) {
+
+ sP->allowedAuth.gssnegotiate = false;
+}
+
+
+
+void
+xmlrpc_server_info_allow_auth_ntlm(xmlrpc_env * const envP,
+ xmlrpc_server_info * const sP) {
+
+ if (sP->userNamePw == NULL)
+ xmlrpc_faultf(envP, "You must set username/password with "
+ "xmlrpc_server_info_set_user()");
+ else
+ sP->allowedAuth.ntlm = true;
+}
+
+
+
+void
+xmlrpc_server_info_disallow_auth_ntlm(
+ xmlrpc_env * const envP ATTR_UNUSED,
+ xmlrpc_server_info * const sP) {
+
+ sP->allowedAuth.ntlm = true;
+}
Modified: freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_server_w32httpsys.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_server_w32httpsys.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_server_w32httpsys.c Fri May 23 16:56:24 2008
@@ -1,28 +1,4 @@
-/* Copyright (C) 2005 by Steven A. Bone, sbone at pobox.com. All rights reserved.
-**
-** Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions
-** are met:
-** 1. Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** 2. Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in the
-** documentation and/or other materials provided with the distribution.
-** 3. The name of the author may not be used to endorse or promote products
-** derived from this software without specific prior written permission.
-**
-** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR 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. */
-
+/* Copyright information is at end of file. */
/* COMPILATION NOTE:
Note that the Platform SDK headers and
link libraries for Windows XP SP2 or newer are required to compile
@@ -43,20 +19,18 @@
#define _UNICODE
#endif
+/* See compilation note above if this header is not found! */
+#include <http.h>
+#include <strsafe.h>
+
+#include "xmlrpc_config.h"
#include "xmlrpc-c/base.h"
#include "xmlrpc-c/server.h"
#include "xmlrpc-c/server_w32httpsys.h"
#include "version.h"
-#if MUST_BUILD_HTTP_SYS_SERVER > 0
-
-/* See compilation note above if this header is not found! */
-#include <http.h>
-#include <windows.h>
-#include <strsafe.h>
-
#pragma comment( lib, "httpapi" )
-
+#pragma message( "Compiling HTTPS server ..." )
/* XXX - This variable is *not* currently threadsafe. Once the server has
** been started, it must be treated as read-only. */
@@ -99,7 +73,7 @@
DWORD
DoReceiveRequests(
HANDLE hReqQueue,
- const xmlrpc_server_httpsys_parms * const parmsP
+ const xmlrpc_server_httpsys_parms * const parmsP
);
DWORD
@@ -134,126 +108,115 @@
void
xmlrpc_server_httpsys(
- xmlrpc_env * const envP,
+ xmlrpc_env * const envP,
const xmlrpc_server_httpsys_parms * const parmsP,
unsigned int const parm_size
- )
+ )
{
- ULONG retCode;
+ ULONG retCode;
HANDLE hReqQueue = NULL;
HTTPAPI_VERSION HttpApiVersion = HTTPAPI_VERSION_1;
- WCHAR wszURL[35];
+ WCHAR wszURL[35];
- XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT_ENV_OK(envP);
if (parm_size < XMLRPC_HSSIZE(authfn))
- {
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR,
- "You must specify members at least up through "
- "'authfn' in the server parameters argument. "
- "That would mean the parameter size would be >= %u "
- "but you specified a size of %u",
- XMLRPC_HSSIZE(authfn), parm_size);
- return;
- }
-
- //Set logging options
- if (parmsP->logLevel>0)
- g_bDebug=TRUE;
- else
- g_bDebug=FALSE;
-
- if (parmsP->logLevel>1)
- g_bDebugString=TRUE;
- else
- g_bDebugString=FALSE;
-
- if (!parmsP->logFile)
- g_bDebug=FALSE;
- else
- StringCchPrintfA(g_fLogFile,MAX_PATH,parmsP->logFile);
-
- //construct the URL we are listening on
- if (parmsP->useSSL!=0)
- StringCchPrintf(wszURL,35,L"https://+:%u/RPC2",parmsP->portNum);
- else
- StringCchPrintf(wszURL,35,L"http://+:%u/RPC2",parmsP->portNum);
-
- global_registryP = parmsP->registryP;
-
- // Initialize HTTP APIs.
- retCode = HttpInitialize(
- HttpApiVersion,
- HTTP_INITIALIZE_SERVER, // Flags
- NULL // Reserved
- );
- if (retCode != NO_ERROR)
- {
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR,
- "HttpInitialize failed with %lu \n ",
- retCode);
- return;
- }
-
- // Create a Request Queue Handle
- retCode = HttpCreateHttpHandle(
- &hReqQueue, // Req Queue
- 0 // Reserved
- );
- if (retCode != NO_ERROR)
- {
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR,
- "HttpCreateHttpHandle failed with %lu \n ",
- retCode);
- goto CleanUp;
- }
-
- retCode = HttpAddUrl(
- hReqQueue, // Req Queue
- wszURL, // Fully qualified URL
- NULL // Reserved
- );
-
- if (retCode != NO_ERROR)
- {
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR,
- "HttpAddUrl failed with %lu \n ",
- retCode);
- goto CleanUp;
- }
-
- TraceW( L"we are listening for requests on the following url: %ws\n", wszURL);
-
- // Loop while receiving requests
- for(;;)
- {
- TraceW( L"Calling DoReceiveRequests()\n");
- retCode = DoReceiveRequests(hReqQueue, parmsP);
- if(NO_ERROR == retCode)
- {
- TraceW( L"DoReceiveRequests() returned NO_ERROR, breaking");
- break;
- }
- }
+ {
+ xmlrpc_faultf(envP,
+ "You must specify members at least up through "
+ "'authfn' in the server parameters argument. "
+ "That would mean the parameter size would be >= %u "
+ "but you specified a size of %u",
+ XMLRPC_HSSIZE(authfn), parm_size);
+ return;
+ }
+
+ //Set logging options
+ if (parmsP->logLevel>0)
+ g_bDebug=TRUE;
+ else
+ g_bDebug=FALSE;
+
+ if (parmsP->logLevel>1)
+ g_bDebugString=TRUE;
+ else
+ g_bDebugString=FALSE;
+
+ if (!parmsP->logFile)
+ g_bDebug=FALSE;
+ else
+ StringCchPrintfA(g_fLogFile,MAX_PATH,parmsP->logFile);
+
+ //construct the URL we are listening on
+ if (parmsP->useSSL!=0)
+ StringCchPrintf(wszURL,35,L"https://+:%u/RPC2",parmsP->portNum);
+ else
+ StringCchPrintf(wszURL,35,L"http://+:%u/RPC2",parmsP->portNum);
+
+ global_registryP = parmsP->registryP;
+
+ // Initialize HTTP APIs.
+ retCode = HttpInitialize(HttpApiVersion,
+ HTTP_INITIALIZE_SERVER, // Flags
+ NULL // Reserved
+ );
+ if (retCode != NO_ERROR)
+ {
+ xmlrpc_faultf(envP, "HttpInitialize failed with %lu",
+ retCode);
+ return;
+ }
+
+ // Create a Request Queue Handle
+ retCode = HttpCreateHttpHandle(&hReqQueue, // Req Queue
+ 0 // Reserved
+ );
+ if (retCode != NO_ERROR)
+ {
+ xmlrpc_faultf(envP, "HttpCreateHttpHandle failed with %lu", retCode);
+ goto CleanUp;
+ }
+
+ retCode = HttpAddUrl(hReqQueue, // Req Queue
+ wszURL, // Fully qualified URL
+ NULL // Reserved
+ );
+
+ if (retCode != NO_ERROR)
+ {
+ xmlrpc_faultf(envP, "HttpAddUrl failed with %lu", retCode);
+ goto CleanUp;
+ }
+
+ TraceW(L"we are listening for requests on the following url: %ws",
+ wszURL);
+
+ // Loop while receiving requests
+ for(;;)
+ {
+ TraceW(L"Calling DoReceiveRequests()");
+ retCode = DoReceiveRequests(hReqQueue, parmsP);
+ if(NO_ERROR == retCode)
+ {
+ TraceW(L"DoReceiveRequests() returned NO_ERROR, breaking");
+ break;
+ }
+ }
CleanUp:
- TraceW( L"Tearing down the server.\n", wszURL);
+ TraceW(L"Tearing down the server.", wszURL);
+
+ // Call HttpRemoveUrl for the URL that we added.
+ HttpRemoveUrl( hReqQueue, wszURL );
- // Call HttpRemoveUrl for the URL that we added.
- HttpRemoveUrl( hReqQueue, wszURL );
+ // Close the Request Queue handle.
+ if(hReqQueue)
+ CloseHandle(hReqQueue);
- // Close the Request Queue handle.
- if(hReqQueue)
- CloseHandle(hReqQueue);
-
- // Call HttpTerminate.
- HttpTerminate(HTTP_INITIALIZE_SERVER, NULL);
- return;
+ // Call HttpTerminate.
+ HttpTerminate(HTTP_INITIALIZE_SERVER, NULL);
+ return;
}
//
@@ -262,69 +225,71 @@
__inline void TraceA(const char *format, ...)
{
- if(g_bDebug)
- {
- if (format)
- {
- va_list arglist;
- char str[4096];
-
- va_start(arglist, format);
- if (g_fLogFile)
- {
- FILE *fout = fopen(g_fLogFile, "a+t");
- if (fout)
- {
- vfprintf(fout, format, arglist);
- fclose(fout);
- }
- }
-
- StringCchVPrintfA(str,4096, format, arglist);
- printf(str);
-
- if (g_bDebugString)
- {
-
- OutputDebugStringA(str);
- }
-
- va_end(arglist);
- }
- }
+ if(g_bDebug)
+ {
+ if (format)
+ {
+ va_list arglist;
+ char str[4096];
+
+ va_start(arglist, format);
+ StringCchVPrintfA(str, sizeof(str), format, arglist);
+ StringCbCatA(str, sizeof(str), "\n");
+ if (g_fLogFile)
+ {
+ FILE *fout = fopen(g_fLogFile, "a+t");
+ if (fout)
+ {
+ fprintf(fout, str);
+ fclose(fout);
+ }
+ }
+
+ printf(str);
+
+ if (g_bDebugString)
+ {
+
+ OutputDebugStringA(str);
+ }
+
+ va_end(arglist);
+ }
+ }
}
__inline void TraceW(const wchar_t *format, ...)
{
- if(g_bDebug)
- {
- if (format)
- {
- va_list arglist;
- wchar_t str[4096];
-
- va_start(arglist, format);
- if (g_fLogFile)
- {
- FILE *fout = fopen(g_fLogFile, "a+t");
- if (fout)
- {
- vfwprintf(fout, format, arglist);
- fclose(fout);
- }
- }
-
- StringCchVPrintfW(str, 4096, format, arglist);
- wprintf(str);
-
- if (g_bDebugString)
- {
- OutputDebugStringW(str);
- }
-
- va_end(arglist);
- }
- }
+ if(g_bDebug)
+ {
+ if (format)
+ {
+ va_list arglist;
+ wchar_t str[4096];
+
+ va_start(arglist, format);
+ StringCchVPrintfW(str, 4096, format, arglist);
+ StringCbCatW(str, sizeof(str), L"\n");
+ if (g_fLogFile)
+ {
+ FILE *fout = fopen(g_fLogFile, "a+t");
+ if (fout)
+ {
+ fwprintf(fout, str);
+ fclose(fout);
+ }
+ }
+
+ wprintf(str);
+
+ if (g_bDebugString)
+ {
+ OutputDebugStringW(str);
+ }
+
+ va_end(arglist);
+ }
+ }
}
/*
@@ -339,7 +304,7 @@
DWORD
DoReceiveRequests(
IN HANDLE hReqQueue,
- const xmlrpc_server_httpsys_parms * const parmsP
+ const xmlrpc_server_httpsys_parms * const parmsP
)
{
ULONG result;
@@ -348,9 +313,9 @@
PHTTP_REQUEST pRequest;
PCHAR pRequestBuffer;
ULONG RequestBufferLength;
- xmlrpc_env env;
- char szHeaderBuf[255];
- long lContentLength;
+ xmlrpc_env env;
+ char szHeaderBuf[255];
+ long lContentLength;
// Allocate a 2K buffer. Should be good for most requests, we'll grow
// this if required. We also need space for a HTTP_REQUEST structure.
@@ -370,14 +335,14 @@
RtlZeroMemory(pRequest, RequestBufferLength);
result = HttpReceiveHttpRequest(
- hReqQueue, // Req Queue
- requestId, // Req ID
- 0, // Flags
- pRequest, // HTTP request buffer
- RequestBufferLength,// req buffer length
- &bytesRead, // bytes received
- NULL // LPOVERLAPPED
- );
+ hReqQueue, // Req Queue
+ requestId, // Req ID
+ 0, // Flags
+ pRequest, // HTTP request buffer
+ RequestBufferLength,// req buffer length
+ &bytesRead, // bytes received
+ NULL // LPOVERLAPPED
+ );
if(NO_ERROR == result)
{
@@ -386,164 +351,238 @@
{
case HttpVerbPOST:
- TraceW(L"Got a POST request for %ws \n",pRequest->CookedUrl.pFullUrl);
-
- //Check if we need use authorization.
- if(parmsP->authfn)
- {
- xmlrpc_env_init(&env);
- if(pRequest->Headers.KnownHeaders[HttpHeaderAuthorization].RawValueLength<6)
- {
- xmlrpc_env_set_fault( &env, XMLRPC_REQUEST_REFUSED_ERROR,
- "Authorization header too short.");
- }
- else
- {
- //unencode the headers
- if(_strnicmp("basic ",pRequest->Headers.KnownHeaders[HttpHeaderAuthorization].pRawValue,6)!=0)
- {
- xmlrpc_env_set_fault( &env, XMLRPC_REQUEST_REFUSED_ERROR,
- "Authorization header is not of type basic.");
- }
- else
- {
- xmlrpc_mem_block * decoded;
-
- decoded = xmlrpc_base64_decode(&env,pRequest->Headers.KnownHeaders[HttpHeaderAuthorization].pRawValue+6,pRequest->Headers.KnownHeaders[HttpHeaderAuthorization].RawValueLength-6);
- if(!env.fault_occurred)
- {
- char *pDecodedStr;
- char *pUser;
- char *pPass;
- char *pColon;
-
- pDecodedStr = (char*)malloc(decoded->_size+1);
- memcpy(pDecodedStr,decoded->_block,decoded->_size);
- pDecodedStr[decoded->_size]='\0';
- pUser = pPass = pDecodedStr;
- pColon=strchr(pDecodedStr,':');
- if(pColon)
- {
- *pColon='\0';
- pPass=pColon+1;
- //The authfn should set env to fail if auth is denied.
- parmsP->authfn(&env,pUser,pPass);
- }
- else
- {
- xmlrpc_env_set_fault( &env, XMLRPC_REQUEST_REFUSED_ERROR,
- "Decoded auth not of the correct format.");
- }
- free(pDecodedStr);
- }
- if(decoded)
- XMLRPC_MEMBLOCK_FREE(char, decoded);
- }
- }
- if(env.fault_occurred)
- {
- //request basic authorization, as the user did not provide it.
- xmlrpc_env_clean(&env);
- TraceW(L"POST request did not provide valid authorization header.");
- result = SendHttpResponseAuthRequired( hReqQueue, pRequest);
- break;
- }
- xmlrpc_env_clean(&env);
- }
-
- //Check content type to make sure it is text/xml.
- memcpy(szHeaderBuf,pRequest->Headers.KnownHeaders[HttpHeaderContentType].pRawValue,pRequest->Headers.KnownHeaders[HttpHeaderContentType].RawValueLength);
- szHeaderBuf[pRequest->Headers.KnownHeaders[HttpHeaderContentType].RawValueLength]='\0';
- if (_stricmp(szHeaderBuf,"text/xml")!=0)
- {
- //We only handle text/xml data. Anything else is not valid.
- TraceW(L"POST request had an unsupported content-type: %s \n", szHeaderBuf);
- result = SendHttpResponse(
- hReqQueue,
- pRequest,
- 400,
- "Bad Request",
- NULL
- );
- break;
- }
-
- //Check content length to make sure it exists and is not too big.
- memcpy(szHeaderBuf,pRequest->Headers.KnownHeaders[HttpHeaderContentLength].pRawValue,pRequest->Headers.KnownHeaders[HttpHeaderContentLength].RawValueLength);
- szHeaderBuf[pRequest->Headers.KnownHeaders[HttpHeaderContentLength].RawValueLength]='\0';
- lContentLength = atol(szHeaderBuf);
- if (lContentLength<=0)
- {
- //Make sure a content length was supplied.
- TraceW(L"POST request did not include a content-length \n", szHeaderBuf);
- result = SendHttpResponse(
- hReqQueue,
- pRequest,
- 411,
- "Length Required",
- NULL
- );
- break;
- }
- if((size_t) lContentLength > xmlrpc_limit_get(XMLRPC_XML_SIZE_LIMIT_ID))
- {
- //Content-length is too big for us to handle
- TraceW(L"POST request content-length is too big for us to handle: %d bytes \n", lContentLength);
- result = SendHttpResponse(
- hReqQueue,
- pRequest,
- 500,
- "content-length too large",
- NULL
- );
- break;
- }
-
- //our initial validations of POST, content-type, and content-length
- //all check out. Collect and pass the complete buffer to the
- //XMLRPC-C library
-
- xmlrpc_env_init(&env);
+ TraceW(L"Got a POST request for %ws",
+ pRequest->CookedUrl.pFullUrl);
+
+ //Check if we need use authorization.
+ if(parmsP->authfn)
+ {
+ xmlrpc_env_init(&env);
+ if(pRequest->Headers.KnownHeaders[
+ HttpHeaderAuthorization].RawValueLength
+ < 6)
+ {
+ xmlrpc_env_set_fault(
+ &env, XMLRPC_REQUEST_REFUSED_ERROR,
+ "Authorization header too short.");
+ }
+ else
+ {
+ //unencode the headers
+ if(_strnicmp(
+ "basic",
+ pRequest->Headers.KnownHeaders[
+ HttpHeaderAuthorization].pRawValue,5)
+ !=0)
+ {
+#ifndef NDEBUG
+ PCHAR pTmp = (PCHAR)
+ ALLOC_MEM(pRequest->Headers.KnownHeaders[
+ HttpHeaderAuthorization
+ ].RawValueLength + 1 );
+ if( pTmp ) {
+ strncpy(pTmp,
+ pRequest->Headers.KnownHeaders[
+ HttpHeaderAuthorization
+ ].pRawValue,
+ pRequest->Headers.KnownHeaders[
+ HttpHeaderAuthorization
+ ].RawValueLength );
+ pTmp[pRequest->Headers.KnownHeaders[
+ HttpHeaderAuthorization
+ ].RawValueLength] = 0;
+ TraceA("Got HEADER [%s]",pTmp);
+ FREE_MEM(pTmp);
+ }
+#endif /* #ifndef NDEBUG */
+ xmlrpc_env_set_fault(
+ &env, XMLRPC_REQUEST_REFUSED_ERROR,
+ "Authorization header does not start "
+ "with type 'basic'!");
+ }
+ else
+ {
+ xmlrpc_mem_block * decoded;
+
+ decoded =
+ xmlrpc_base64_decode(
+ &env,
+ pRequest->Headers.KnownHeaders[
+ HttpHeaderAuthorization
+ ].pRawValue+6,
+ pRequest->Headers.KnownHeaders[
+ HttpHeaderAuthorization
+ ].RawValueLength-6);
+ if(!env.fault_occurred)
+ {
+ char *pDecodedStr;
+ char *pUser;
+ char *pPass;
+ char *pColon;
+
+ pDecodedStr = (char*)
+ malloc(decoded->_size+1);
+ memcpy(pDecodedStr,
+ decoded->_block,
+ decoded->_size);
+ pDecodedStr[decoded->_size]='\0';
+ pUser = pPass = pDecodedStr;
+ pColon=strchr(pDecodedStr,':');
+ if(pColon)
+ {
+ *pColon='\0';
+ pPass=pColon+1;
+ //The authfn should set env to
+ //fail if auth is denied.
+ parmsP->authfn(&env,pUser,pPass);
+ }
+ else
+ {
+ xmlrpc_env_set_fault(
+ &env,
+ XMLRPC_REQUEST_REFUSED_ERROR,
+ "Decoded auth not of the correct "
+ "format.");
+ }
+ free(pDecodedStr);
+ }
+ if(decoded)
+ XMLRPC_MEMBLOCK_FREE(char, decoded);
+ }
+ }
+ if(env.fault_occurred)
+ {
+ //request basic authorization, as the user
+ //did not provide it.
+ xmlrpc_env_clean(&env);
+ TraceW(L"POST request did not provide valid "
+ L"authorization header.");
+ result =
+ SendHttpResponseAuthRequired( hReqQueue,
+ pRequest);
+ break;
+ }
+ xmlrpc_env_clean(&env);
+ }
+
+ //Check content type to make sure it is text/xml.
+ memcpy(szHeaderBuf,
+ pRequest->Headers.KnownHeaders[
+ HttpHeaderContentType
+ ].pRawValue,
+ pRequest->Headers.KnownHeaders[
+ HttpHeaderContentType
+ ].RawValueLength);
+ szHeaderBuf[pRequest->Headers.KnownHeaders[
+ HttpHeaderContentType
+ ].RawValueLength] = '\0';
+ if (_stricmp(szHeaderBuf,"text/xml")!=0)
+ {
+ //We handle only text/xml data. Anything else
+ //is not valid.
+ TraceW(L"POST request had an unrecognized "
+ L"content-type: %s", szHeaderBuf);
+ result = SendHttpResponse(
+ hReqQueue,
+ pRequest,
+ 400,
+ "Bad Request",
+ NULL
+ );
+ break;
+ }
+
+ //Check content length to make sure it exists and
+ //is not too big.
+ memcpy(szHeaderBuf,
+ pRequest->Headers.KnownHeaders[
+ HttpHeaderContentLength
+ ].pRawValue,
+ pRequest->Headers.KnownHeaders[
+ HttpHeaderContentLength
+ ].RawValueLength);
+ szHeaderBuf[pRequest->Headers.KnownHeaders[
+ HttpHeaderContentLength
+ ].RawValueLength]='\0';
+ lContentLength = atol(szHeaderBuf);
+ if (lContentLength<=0)
+ {
+ //Make sure a content length was supplied.
+ TraceW(L"POST request did not include a "
+ L"content-length", szHeaderBuf);
+ result = SendHttpResponse(
+ hReqQueue,
+ pRequest,
+ 411,
+ "Length Required",
+ NULL
+ );
+ break;
+ }
+ if((size_t) lContentLength >
+ xmlrpc_limit_get(XMLRPC_XML_SIZE_LIMIT_ID))
+ {
+ //Content-length is too big for us to handle
+ TraceW(L"POST request content-length is too big "
+ L"for us to handle: %d bytes",
+ lContentLength);
+ result = SendHttpResponse(
+ hReqQueue,
+ pRequest,
+ 500,
+ "content-length too large",
+ NULL
+ );
+ break;
+ }
+
+ //our initial validations of POST, content-type,
+ //and content-length all check out. Collect and
+ //pass the complete buffer to the XMLRPC-C library
+
+ xmlrpc_env_init(&env);
processRPCCall(&env,hReqQueue, pRequest);
- if (env.fault_occurred)
- {
- //if we fail and it is anything other than a network error,
- //we should return a failure response to the client.
- if (env.fault_code != XMLRPC_NETWORK_ERROR)
- {
- if (env.fault_string)
- result = SendHttpResponse(
- hReqQueue,
- pRequest,
- 500,
- env.fault_string,
- NULL
- );
- else
- result = SendHttpResponse(
- hReqQueue,
- pRequest,
- 500,
- "Unknown Error",
- NULL
- );
- }
- }
-
- xmlrpc_env_clean(&env);
+ if (env.fault_occurred)
+ {
+ //if we fail and it is anything other than a
+ //network error, we should return a failure
+ //response to the client.
+ if (env.fault_code != XMLRPC_NETWORK_ERROR)
+ {
+ if (env.fault_string)
+ result = SendHttpResponse(
+ hReqQueue,
+ pRequest,
+ 500,
+ env.fault_string,
+ NULL
+ );
+ else
+ result = SendHttpResponse(
+ hReqQueue,
+ pRequest,
+ 500,
+ "Unknown Error",
+ NULL
+ );
+ }
+ }
+
+ xmlrpc_env_clean(&env);
break;
default:
- //We only handle POST data. Anything else is not valid.
- TraceW(L"Got an unsupported Verb request for URI %ws \n", pRequest->CookedUrl.pFullUrl);
-
+ //We handle only POST data. Anything else is not valid.
+ TraceW(L"Got an unrecognized Verb request for URI %ws",
+ pRequest->CookedUrl.pFullUrl);
+
result = SendHttpResponse(
- hReqQueue,
- pRequest,
- 405,
- "Method Not Allowed",
- NULL
- );
+ hReqQueue,
+ pRequest,
+ 405,
+ "Method Not Allowed",
+ NULL
+ );
break;
}
if(result != NO_ERROR)
@@ -592,7 +631,6 @@
}
} // for(;;)
-Cleanup:
if(pRequestBuffer)
{
@@ -620,15 +658,15 @@
HTTP_DATA_CHUNK dataChunk;
DWORD result;
DWORD bytesSent;
- CHAR szServerHeader[20];
+ CHAR szServerHeader[20];
// Initialize the HTTP response structure.
INITIALIZE_HTTP_RESPONSE(&response, StatusCode, pReason);
ADD_KNOWN_HEADER(response, HttpHeaderContentType, "text/html");
-
- StringCchPrintfA(szServerHeader,20, "xmlrpc-c %s",XMLRPC_C_VERSION);
- ADD_KNOWN_HEADER(response, HttpHeaderServer, szServerHeader);
+
+ StringCchPrintfA(szServerHeader,20, "xmlrpc-c %s",XMLRPC_C_VERSION);
+ ADD_KNOWN_HEADER(response, HttpHeaderServer, szServerHeader);
if(pEntityString)
{
@@ -644,29 +682,30 @@
// Since we are sending all the entity body in one call, we don't have
// to specify the Content-Length.
result = HttpSendHttpResponse(
- hReqQueue, // ReqQueueHandle
- pRequest->RequestId, // Request ID
- 0, // Flags
- &response, // HTTP response
- NULL, // pReserved1
- &bytesSent, // bytes sent (OPTIONAL)
- NULL, // pReserved2 (must be NULL)
- 0, // Reserved3 (must be 0)
- NULL, // LPOVERLAPPED (OPTIONAL)
- NULL // pReserved4 (must be NULL)
- );
+ hReqQueue, // ReqQueueHandle
+ pRequest->RequestId, // Request ID
+ 0, // Flags
+ &response, // HTTP response
+ NULL, // pReserved1
+ &bytesSent, // bytes sent (OPTIONAL)
+ NULL, // pReserved2 (must be NULL)
+ 0, // Reserved3 (must be 0)
+ NULL, // LPOVERLAPPED (OPTIONAL)
+ NULL // pReserved4 (must be NULL)
+ );
if(result != NO_ERROR)
{
- TraceW(L"HttpSendHttpResponse failed with %lu \n", result);
+ TraceW(L"HttpSendHttpResponse failed with %lu", result);
}
return result;
}
-/*
- * SendHttpResponseAuthRequired sends a 401 status code requesting authorization
+/* SendHttpResponseAuthRequired sends a 401 status code requesting
+ * authorization
*/
+
DWORD
SendHttpResponseAuthRequired(
IN HANDLE hReqQueue,
@@ -676,35 +715,36 @@
HTTP_RESPONSE response;
DWORD result;
DWORD bytesSent;
- CHAR szServerHeader[20];
+ CHAR szServerHeader[20];
// Initialize the HTTP response structure.
INITIALIZE_HTTP_RESPONSE(&response, 401, "Authentication Required");
// Add the WWW_Authenticate header.
- ADD_KNOWN_HEADER(response, HttpHeaderWwwAuthenticate, "Basic realm=\"xmlrpc\"");
-
- StringCchPrintfA(szServerHeader,20, "xmlrpc-c %s",XMLRPC_C_VERSION);
- ADD_KNOWN_HEADER(response, HttpHeaderServer, szServerHeader);
+ ADD_KNOWN_HEADER(response, HttpHeaderWwwAuthenticate,
+ "Basic realm=\"xmlrpc\"");
+
+ StringCchPrintfA(szServerHeader,20, "xmlrpc-c %s",XMLRPC_C_VERSION);
+ ADD_KNOWN_HEADER(response, HttpHeaderServer, szServerHeader);
// Since we are sending all the entity body in one call, we don't have
// to specify the Content-Length.
result = HttpSendHttpResponse(
- hReqQueue, // ReqQueueHandle
- pRequest->RequestId, // Request ID
- 0, // Flags
- &response, // HTTP response
- NULL, // pReserved1
- &bytesSent, // bytes sent (OPTIONAL)
- NULL, // pReserved2 (must be NULL)
- 0, // Reserved3 (must be 0)
- NULL, // LPOVERLAPPED (OPTIONAL)
- NULL // pReserved4 (must be NULL)
- );
+ hReqQueue, // ReqQueueHandle
+ pRequest->RequestId, // Request ID
+ 0, // Flags
+ &response, // HTTP response
+ NULL, // pReserved1
+ &bytesSent, // bytes sent (OPTIONAL)
+ NULL, // pReserved2 (must be NULL)
+ 0, // Reserved3 (must be 0)
+ NULL, // LPOVERLAPPED (OPTIONAL)
+ NULL // pReserved4 (must be NULL)
+ );
if(result != NO_ERROR)
{
- TraceW(L"SendHttpResponseAuthRequired failed with %lu \n", result);
+ TraceW(L"SendHttpResponseAuthRequired failed with %lu", result);
}
return result;
@@ -733,38 +773,36 @@
ULONG BytesRead;
#define MAX_ULONG_STR ((ULONG) sizeof("4294967295"))
CHAR szContentLength[MAX_ULONG_STR];
- CHAR szServerHeader[20];
+ CHAR szServerHeader[20];
HTTP_DATA_CHUNK dataChunk;
ULONG TotalBytesRead = 0;
- xmlrpc_mem_block * body;
- xmlrpc_mem_block * output;
+ xmlrpc_mem_block * body;
+ xmlrpc_mem_block * output;
BytesRead = 0;
- body = NULL;
- output = NULL;
+ body = NULL;
+ output = NULL;
// Allocate some space for an entity buffer.
- EntityBufferLength = 2048;
+ EntityBufferLength = 2048;
pEntityBuffer = (PUCHAR) ALLOC_MEM( EntityBufferLength );
if (pEntityBuffer == NULL)
{
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR,
- "Out of Memory");
+ xmlrpc_faultf(envP, "Out of Memory");
goto Done;
}
- // NOTE: If we had passed the HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY
+ // NOTE: If we had passed the HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY
// flag with HttpReceiveHttpRequest(), the entity would have
// been a part of HTTP_REQUEST (using the pEntityChunks field).
// Since we have not passed that flag, we can be assured that
// there are no entity bodies in HTTP_REQUEST.
if(pRequest->Flags & HTTP_REQUEST_FLAG_MORE_ENTITY_BODY_EXISTS)
{
- //Allocate some space for an XMLRPC memory block.
- body = xmlrpc_mem_block_new(envP, 0);
- if (envP->fault_occurred)
- goto Done;
+ //Allocate some space for an XMLRPC memory block.
+ body = xmlrpc_mem_block_new(envP, 0);
+ if (envP->fault_occurred)
+ goto Done;
// The entity body can be sent over multiple calls. Let's collect all
// of these in a buffer and send the buffer to the xmlrpc-c library
@@ -773,23 +811,23 @@
// Read the entity chunk from the request.
BytesRead = 0;
result = HttpReceiveRequestEntityBody(
- hReqQueue,
- pRequest->RequestId,
- 0,
- pEntityBuffer,
- EntityBufferLength,
- &BytesRead,
- NULL
- );
+ hReqQueue,
+ pRequest->RequestId,
+ 0,
+ pEntityBuffer,
+ EntityBufferLength,
+ &BytesRead,
+ NULL
+ );
switch(result)
{
case NO_ERROR:
if(BytesRead != 0)
{
- XMLRPC_TYPED_MEM_BLOCK_APPEND(char, envP, body,
- pEntityBuffer, BytesRead);
- if(envP->fault_occurred)
- goto Done;
+ XMLRPC_MEMBLOCK_APPEND(char, envP, body,
+ pEntityBuffer, BytesRead);
+ if(envP->fault_occurred)
+ goto Done;
}
break;
@@ -798,112 +836,125 @@
// process the suppossed XMLRPC data.
if(BytesRead != 0)
{
- XMLRPC_TYPED_MEM_BLOCK_APPEND(char, envP, body,
- pEntityBuffer, BytesRead);
- if(envP->fault_occurred)
- goto Done;
+ XMLRPC_MEMBLOCK_APPEND(char, envP, body,
+ pEntityBuffer, BytesRead);
+ if(envP->fault_occurred)
+ goto Done;
}
// We will send the response over multiple calls.
- // This is achieved by passing the
+ // This is achieved by passing the
// HTTP_SEND_RESPONSE_FLAG_MORE_DATA flag.
// NOTE: Since we are accumulating the TotalBytesRead in
// a ULONG, this will not work for entity bodies that
- // are larger than 4 GB. For supporting large entity
+ // are larger than 4 GB. To work with large entity
// bodies, we would have to use a ULONGLONG.
- TraceA("xmlrpc_server RPC2 handler processing RPC request.\n");
-
- // Process the RPC.
- output = xmlrpc_registry_process_call(
- envP, global_registryP, NULL,
- XMLRPC_MEMBLOCK_CONTENTS(char, body),
- XMLRPC_MEMBLOCK_SIZE(char, body));
- if (envP->fault_occurred)
- goto Done;
-
- // Initialize the HTTP response structure.
- INITIALIZE_HTTP_RESPONSE(&response, 200, "OK");
-
- //Add the content-length
- StringCchPrintfA(szContentLength,MAX_ULONG_STR, "%lu",
- XMLRPC_MEMBLOCK_SIZE(char, output));
- ADD_KNOWN_HEADER(
- response,
- HttpHeaderContentLength,
- szContentLength );
-
- //Add the content-type
- ADD_KNOWN_HEADER(response, HttpHeaderContentType, "text/xml");
-
- StringCchPrintfA(szServerHeader,20, "xmlrpc-c %s",XMLRPC_C_VERSION);
- ADD_KNOWN_HEADER(response, HttpHeaderServer, szServerHeader);
-
- //send the response
- result = HttpSendHttpResponse(
- hReqQueue, // ReqQueueHandle
- pRequest->RequestId, // Request ID
- HTTP_SEND_RESPONSE_FLAG_MORE_DATA,
- &response, // HTTP response
- NULL, // pReserved1
- &bytesSent, // bytes sent (optional)
- NULL, // pReserved2
- 0, // Reserved3
- NULL, // LPOVERLAPPED
- NULL // pReserved4
- );
- if(result != NO_ERROR)
- {
- TraceW(L"HttpSendHttpResponse failed with %lu \n", result);
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_NETWORK_ERROR,
- "HttpSendHttpResponse failed with %lu", result);
- goto Done;
- }
-
- // Send entity body from a memory chunk.
- dataChunk.DataChunkType = HttpDataChunkFromMemory;
- dataChunk.FromMemory.BufferLength = (ULONG)XMLRPC_MEMBLOCK_SIZE(char, output);
- dataChunk.FromMemory.pBuffer = XMLRPC_MEMBLOCK_CONTENTS(char, output);
-
- result = HttpSendResponseEntityBody(
- hReqQueue,
- pRequest->RequestId,
- 0, // This is the last send.
- 1, // Entity Chunk Count.
- &dataChunk,
- NULL,
- NULL,
- 0,
- NULL,
- NULL
- );
- if(result != NO_ERROR)
- {
- TraceW(L"HttpSendResponseEntityBody failed with %lu \n", result);
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_NETWORK_ERROR,
- "HttpSendResponseEntityBody failed with %lu", result);
- goto Done;
- }
- goto Done;
+ TraceA("xmlrpc_server RPC2 handler processing "
+ "RPC request.");
+
+ // Process the RPC.
+ xmlrpc_registry_process_call2(
+ envP, global_registryP,
+ XMLRPC_MEMBLOCK_CONTENTS(char, body),
+ XMLRPC_MEMBLOCK_SIZE(char, body),
+ NULL,
+ &output);
+ if (envP->fault_occurred)
+ goto Done;
+
+ // Initialize the HTTP response structure.
+ INITIALIZE_HTTP_RESPONSE(&response, 200, "OK");
+
+ //Add the content-length
+ StringCchPrintfA(szContentLength,MAX_ULONG_STR, "%lu",
+ XMLRPC_MEMBLOCK_SIZE(char, output));
+ ADD_KNOWN_HEADER(
+ response,
+ HttpHeaderContentLength,
+ szContentLength );
+
+ //Add the content-type
+ ADD_KNOWN_HEADER(response, HttpHeaderContentType,
+ "text/xml");
+
+ StringCchPrintfA(szServerHeader,20,
+ "xmlrpc-c %s",XMLRPC_C_VERSION);
+ ADD_KNOWN_HEADER(response, HttpHeaderServer,
+ szServerHeader);
+
+ //send the response
+ result = HttpSendHttpResponse(
+ hReqQueue, // ReqQueueHandle
+ pRequest->RequestId, // Request ID
+ HTTP_SEND_RESPONSE_FLAG_MORE_DATA,
+ &response, // HTTP response
+ NULL, // pReserved1
+ &bytesSent, // bytes sent (optional)
+ NULL, // pReserved2
+ 0, // Reserved3
+ NULL, // LPOVERLAPPED
+ NULL // pReserved4
+ );
+ if(result != NO_ERROR)
+ {
+ TraceW(L"HttpSendHttpResponse failed with %lu",
+ result);
+ xmlrpc_env_set_fault_formatted(
+ envP, XMLRPC_NETWORK_ERROR,
+ "HttpSendHttpResponse failed with %lu", result);
+ goto Done;
+ }
+
+ // Send entity body from a memory chunk.
+ dataChunk.DataChunkType = HttpDataChunkFromMemory;
+ dataChunk.FromMemory.BufferLength =
+ (ULONG)XMLRPC_MEMBLOCK_SIZE(char, output);
+ dataChunk.FromMemory.pBuffer =
+ XMLRPC_MEMBLOCK_CONTENTS(char, output);
+
+ result = HttpSendResponseEntityBody(
+ hReqQueue,
+ pRequest->RequestId,
+ 0, // This is the last send.
+ 1, // Entity Chunk Count.
+ &dataChunk,
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ NULL
+ );
+ if(result != NO_ERROR)
+ {
+ TraceW(L"HttpSendResponseEntityBody failed "
+ L"with %lu", result);
+ xmlrpc_env_set_fault_formatted(
+ envP, XMLRPC_NETWORK_ERROR,
+ "HttpSendResponseEntityBody failed with %lu",
+ result);
+ goto Done;
+ }
+ goto Done;
break;
default:
- TraceW(L"HttpReceiveRequestEntityBody failed with %lu \n", result);
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_NETWORK_ERROR,
- "HttpReceiveRequestEntityBody failed with %lu", result);
+ TraceW(L"HttpReceiveRequestEntityBody failed with %lu",
+ result);
+ xmlrpc_env_set_fault_formatted(
+ envP, XMLRPC_NETWORK_ERROR,
+ "HttpReceiveRequestEntityBody failed "
+ "with %lu", result);
goto Done;
}
} while(TRUE);
}
else
{
- // This request does not have an entity body.
- TraceA("Received a bad request (no body in HTTP post).\n");
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_PARSE_ERROR,
- "Bad POST request (no body)");
+ // This request does not have an entity body.
+ TraceA("Received a bad request (no body in HTTP post).");
+ xmlrpc_env_set_fault_formatted(
+ envP, XMLRPC_PARSE_ERROR,
+ "Bad POST request (no body)");
goto Done;
}
@@ -912,13 +963,39 @@
if(pEntityBuffer)
FREE_MEM(pEntityBuffer);
- if(output)
- XMLRPC_MEMBLOCK_FREE(char, output);
+ if(output)
+ XMLRPC_MEMBLOCK_FREE(char, output);
- if(body)
- XMLRPC_MEMBLOCK_FREE(char, body);
+ if(body)
+ XMLRPC_MEMBLOCK_FREE(char, body);
return;
}
-#endif /* #if MUST_BUILD_HTTP_SYS_SERVER <> 0 */
\ No newline at end of file
+
+
+/* Copyright (C) 2005 by Steven A. Bone, sbone at pobox.com. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR 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. */
+
Added: freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_string.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_string.c Fri May 23 16:56:24 2008
@@ -0,0 +1,864 @@
+/*=============================================================================
+ xmlrpc_string
+===============================================================================
+ Routines for the "string" type of xmlrpc_value.
+
+ By Bryan Henderson.
+
+ Contributed to the public domain by its author.
+=============================================================================*/
+
+#include "xmlrpc_config.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "bool.h"
+#include "mallocvar.h"
+
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/base_int.h"
+#include "xmlrpc-c/string_int.h"
+
+
+
+void
+xmlrpc_destroyString(xmlrpc_value * const valueP) {
+
+ if (valueP->_wcs_block)
+ xmlrpc_mem_block_free(valueP->_wcs_block);
+
+ xmlrpc_mem_block_clean(&valueP->_block);
+}
+
+
+
+static void
+verifyNoNulls(xmlrpc_env * const envP,
+ const char * const contents,
+ unsigned int const len) {
+/*----------------------------------------------------------------------------
+ Verify that the character array 'contents', which is 'len' bytes long,
+ does not contain any NUL characters, which means it can be made into
+ a passable ASCIIZ string just by adding a terminating NUL.
+
+ Fail if the array contains a NUL.
+-----------------------------------------------------------------------------*/
+ unsigned int i;
+
+ for (i = 0; i < len && !envP->fault_occurred; ++i)
+ if (contents[i] == '\0')
+ xmlrpc_env_set_fault_formatted(
+ envP, XMLRPC_TYPE_ERROR,
+ "String must not contain NUL characters");
+}
+
+
+
+#if HAVE_UNICODE_WCHAR
+
+static void
+verifyNoNullsW(xmlrpc_env * const envP,
+ const wchar_t * const contents,
+ unsigned int const len) {
+/*----------------------------------------------------------------------------
+ Same as verifyNoNulls(), but for wide characters.
+-----------------------------------------------------------------------------*/
+ unsigned int i;
+
+ for (i = 0; i < len && !envP->fault_occurred; i++)
+ if (contents[i] == '\0')
+ xmlrpc_env_set_fault_formatted(
+ envP, XMLRPC_TYPE_ERROR,
+ "String must not contain NUL characters");
+}
+#endif
+
+
+
+static void
+validateStringType(xmlrpc_env * const envP,
+ const xmlrpc_value * const valueP) {
+
+ if (valueP->_type != XMLRPC_TYPE_STRING) {
+ xmlrpc_env_set_fault_formatted(
+ envP, XMLRPC_TYPE_ERROR, "Value of type %s supplied where "
+ "string type was expected.",
+ xmlrpc_type_name(valueP->_type));
+ }
+}
+
+
+
+static void
+accessStringValue(xmlrpc_env * const envP,
+ const xmlrpc_value * const valueP,
+ size_t * const lengthP,
+ const char ** const contentsP) {
+
+ validateStringType(envP, valueP);
+ if (!envP->fault_occurred) {
+ unsigned int const size =
+ XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block);
+ const char * const contents =
+ XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block);
+ unsigned int const len = size - 1;
+ /* The memblock has a null character added to the end */
+
+ verifyNoNulls(envP, contents, len);
+
+ *lengthP = len;
+ *contentsP = contents;
+ }
+}
+
+
+
+void
+xmlrpc_read_string(xmlrpc_env * const envP,
+ const xmlrpc_value * const valueP,
+ const char ** const stringValueP) {
+/*----------------------------------------------------------------------------
+ Read the value of an XML-RPC string as an ASCIIZ string, with
+ LF for line delimiters.
+
+ Return the string in newly malloc'ed storage that Caller must free.
+
+ Fail if the string contains null characters (which means it wasn't
+ really a string, but XML-RPC doesn't seem to understand what a string
+ is, and such values are possible).
+-----------------------------------------------------------------------------*/
+ size_t length;
+ const char * contents;
+
+ accessStringValue(envP, valueP, &length, &contents);
+
+ if (!envP->fault_occurred) {
+ char * stringValue;
+
+ MALLOCARRAY(stringValue, length + 1);
+ if (stringValue == NULL)
+ xmlrpc_faultf(envP, "Unable to allocate space "
+ "for %u-character string", length);
+ else {
+ memcpy(stringValue, contents, length);
+ stringValue[length] = '\0';
+
+ *stringValueP = stringValue;
+ }
+ }
+}
+
+
+
+static unsigned int
+lineDelimCount(const char * const start,
+ const char * const end) {
+
+ unsigned int count;
+ const char * p;
+
+ for (p = start, count = 0; p < end; ) {
+ const char * const nlPos = memchr(p, '\n', end-p);
+ if (nlPos) {
+ ++count;
+ p = nlPos + 1;
+ } else
+ p = end;
+ }
+
+ return count;
+}
+
+
+
+static void
+copyAndConvertLfToCrlf(xmlrpc_env * const envP,
+ size_t const srcLen,
+ const char * const src,
+ size_t * const dstLenP,
+ const char ** const dstP) {
+
+ const char * const srcEnd = src + srcLen;
+ unsigned int const nLineDelim = lineDelimCount(src, srcEnd);
+ size_t const dstLen = srcLen + nLineDelim;
+ char * dst;
+
+ MALLOCARRAY(dst, dstLen + 1);
+ if (dst == NULL)
+ xmlrpc_faultf(envP, "Unable to allocate space "
+ "for %u-character string", dstLen + 1);
+ else {
+ const char * p; /* source pointer */
+ char * q; /* destination pointer */
+
+ for (p = &src[0], q = &dst[0]; p < srcEnd; ++p) {
+ if (*p == '\n')
+ *q++ = '\r';
+
+ *q++ = *p;
+ }
+ XMLRPC_ASSERT(q == dst + dstLen);
+
+ *q = '\0';
+
+ *dstP = dst;
+ *dstLenP = dstLen;
+ }
+}
+
+
+
+void
+xmlrpc_read_string_crlf(xmlrpc_env * const envP,
+ const xmlrpc_value * const valueP,
+ const char ** const stringValueP) {
+/*----------------------------------------------------------------------------
+ Same as xmlrpc_read_string(), but return CRLF instead of LF for
+ line delimiters.
+-----------------------------------------------------------------------------*/
+ size_t length;
+ const char * contents;
+
+ accessStringValue(envP, valueP, &length, &contents);
+
+ if (!envP->fault_occurred) {
+ size_t stringLen;
+
+ copyAndConvertLfToCrlf(envP, length, contents,
+ &stringLen, stringValueP);
+ }
+}
+
+
+
+void
+xmlrpc_read_string_old(xmlrpc_env * const envP,
+ const xmlrpc_value * const valueP,
+ const char ** const stringValueP) {
+
+ size_t length;
+ accessStringValue(envP, valueP, &length, stringValueP);
+}
+
+
+
+void
+xmlrpc_read_string_lp(xmlrpc_env * const envP,
+ const xmlrpc_value * const valueP,
+ size_t * const lengthP,
+ const char ** const stringValueP) {
+
+ validateStringType(envP, valueP);
+ if (!envP->fault_occurred) {
+ unsigned int const size =
+ XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block);
+ const char * const contents =
+ XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block);
+
+ char * stringValue;
+
+ stringValue = malloc(size);
+ if (stringValue == NULL)
+ xmlrpc_faultf(envP, "Unable to allocate %u bytes for string.",
+ size);
+ else {
+ memcpy(stringValue, contents, size);
+ *stringValueP = stringValue;
+ *lengthP = size - 1; /* Size includes terminating NUL */
+ }
+ }
+}
+
+
+
+void
+xmlrpc_read_string_lp_crlf(xmlrpc_env * const envP,
+ const xmlrpc_value * const valueP,
+ size_t * const lengthP,
+ const char ** const stringValueP) {
+
+ validateStringType(envP, valueP);
+ if (!envP->fault_occurred) {
+ unsigned int const size =
+ XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block); /* Includes NUL */
+ const char * const contents =
+ XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block);
+
+ copyAndConvertLfToCrlf(envP, size-1, contents,
+ lengthP, stringValueP);
+ }
+}
+
+
+
+void
+xmlrpc_read_string_lp_old(xmlrpc_env * const envP,
+ const xmlrpc_value * const valueP,
+ size_t * const lengthP,
+ const char ** const stringValueP) {
+
+ validateStringType(envP, valueP);
+ if (!envP->fault_occurred) {
+ *lengthP = XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block) - 1;
+ *stringValueP = XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block);
+ }
+}
+
+
+
+static __inline__ void
+setupWcsBlock(xmlrpc_env * const envP,
+ xmlrpc_value * const valueP) {
+/*----------------------------------------------------------------------------
+ Add a wcs block (wchar_t string) to the indicated xmlrpc_value if it
+ doesn't have one already.
+-----------------------------------------------------------------------------*/
+ if (!valueP->_wcs_block) {
+ char * const contents =
+ XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block);
+ size_t const len =
+ XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block) - 1;
+ valueP->_wcs_block =
+ xmlrpc_utf8_to_wcs(envP, contents, len + 1);
+ }
+}
+
+
+
+#if HAVE_UNICODE_WCHAR
+
+static void
+accessStringValueW(xmlrpc_env * const envP,
+ xmlrpc_value * const valueP,
+ size_t * const lengthP,
+ const wchar_t ** const stringValueP) {
+
+ validateStringType(envP, valueP);
+ if (!envP->fault_occurred) {
+ setupWcsBlock(envP, valueP);
+
+ if (!envP->fault_occurred) {
+ wchar_t * const wcontents =
+ XMLRPC_MEMBLOCK_CONTENTS(wchar_t, valueP->_wcs_block);
+ size_t const len =
+ XMLRPC_MEMBLOCK_SIZE(wchar_t, valueP->_wcs_block) - 1;
+
+ verifyNoNullsW(envP, wcontents, len);
+
+ *lengthP = len;
+ *stringValueP = wcontents;
+ }
+ }
+}
+
+
+
+void
+xmlrpc_read_string_w(xmlrpc_env * const envP,
+ xmlrpc_value * const valueP,
+ const wchar_t ** const stringValueP) {
+
+ size_t length;
+ const wchar_t * wcontents;
+
+ accessStringValueW(envP, valueP, &length, &wcontents);
+
+ if (!envP->fault_occurred) {
+ wchar_t * stringValue;
+ MALLOCARRAY(stringValue, length + 1);
+ if (stringValue == NULL)
+ xmlrpc_faultf(envP, "Unable to allocate space for %u-byte string",
+ length);
+ else {
+ memcpy(stringValue, wcontents, length * sizeof(wchar_t));
+ stringValue[length] = '\0';
+
+ *stringValueP = stringValue;
+ }
+ }
+}
+
+
+
+static unsigned int
+lineDelimCountW(const wchar_t * const start,
+ const wchar_t * const end) {
+
+ unsigned int count;
+ const wchar_t * p;
+
+ count = 0;
+ p = start;
+
+ while (p && p < end) {
+ /* We used to use memchr(), but Windows doesn't have it */
+ p = wcsstr(p, L"\n");
+ if (p && p < end) {
+ ++count; /* count the newline */
+ ++p; /* skip the newline */
+ }
+ }
+
+ return count;
+}
+
+
+
+static void
+wCopyAndConvertLfToCrlf(xmlrpc_env * const envP,
+ size_t const srcLen,
+ const wchar_t * const src,
+ size_t * const dstLenP,
+ const wchar_t ** const dstP) {
+
+ const wchar_t * const srcEnd = src + srcLen;
+ unsigned int const nLineDelim = lineDelimCountW(src, srcEnd);
+ size_t const dstLen = srcLen + nLineDelim;
+ wchar_t * dst;
+
+ MALLOCARRAY(dst, dstLen + 1);
+ if (dst == NULL)
+ xmlrpc_faultf(envP, "Unable to allocate space "
+ "for %u-character string", dstLen + 1);
+ else {
+ const wchar_t * p; /* source pointer */
+ wchar_t * q; /* destination pointer */
+
+ for (p = &src[0], q = &dst[0]; p < srcEnd; ++p) {
+ if (*p == '\n')
+ *q++ = '\r';
+
+ *q++ = *p;
+ }
+ XMLRPC_ASSERT(q == dst + dstLen);
+
+ *q = '\0';
+
+ *dstP = dst;
+ *dstLenP = dstLen;
+ }
+}
+
+
+
+void
+xmlrpc_read_string_w_crlf(xmlrpc_env * const envP,
+ xmlrpc_value * const valueP,
+ const wchar_t ** const stringValueP) {
+
+ size_t size;
+ const wchar_t * contents;
+
+ accessStringValueW(envP, valueP, &size, &contents);
+
+ if (!envP->fault_occurred) {
+ size_t stringLen;
+
+ wCopyAndConvertLfToCrlf(envP, size, contents,
+ &stringLen, stringValueP);
+ }
+}
+
+
+
+void
+xmlrpc_read_string_w_old(xmlrpc_env * const envP,
+ xmlrpc_value * const valueP,
+ const wchar_t ** const stringValueP) {
+
+ size_t length;
+
+ accessStringValueW(envP, valueP, &length, stringValueP);
+}
+
+
+
+void
+xmlrpc_read_string_w_lp(xmlrpc_env * const envP,
+ xmlrpc_value * const valueP,
+ size_t * const lengthP,
+ const wchar_t ** const stringValueP) {
+
+ validateStringType(envP, valueP);
+ if (!envP->fault_occurred) {
+ setupWcsBlock(envP, valueP);
+
+ if (!envP->fault_occurred) {
+ wchar_t * const wcontents =
+ XMLRPC_MEMBLOCK_CONTENTS(wchar_t, valueP->_wcs_block);
+ size_t const size =
+ XMLRPC_MEMBLOCK_SIZE(wchar_t, valueP->_wcs_block);
+
+ wchar_t * stringValue;
+
+ MALLOCARRAY(stringValue, size);
+ if (stringValue == NULL)
+ xmlrpc_faultf(envP,
+ "Unable to allocate space for %u-byte string",
+ (unsigned int)size);
+ else {
+ memcpy(stringValue, wcontents, size * sizeof(wchar_t));
+
+ *lengthP = size - 1; /* size includes terminating NUL */
+ *stringValueP = stringValue;
+ }
+ }
+ }
+}
+
+
+
+void
+xmlrpc_read_string_w_lp_crlf(xmlrpc_env * const envP,
+ xmlrpc_value * const valueP,
+ size_t * const lengthP,
+ const wchar_t ** const stringValueP) {
+
+ validateStringType(envP, valueP);
+ if (!envP->fault_occurred) {
+ setupWcsBlock(envP, valueP);
+
+ if (!envP->fault_occurred) {
+ size_t const size =
+ XMLRPC_MEMBLOCK_SIZE(wchar_t, valueP->_wcs_block);
+ wchar_t * const wcontents =
+ XMLRPC_MEMBLOCK_CONTENTS(wchar_t, valueP->_wcs_block);
+
+ wCopyAndConvertLfToCrlf(envP, size-1, wcontents,
+ lengthP, stringValueP);
+ }
+ }
+}
+
+
+
+void
+xmlrpc_read_string_w_lp_old(xmlrpc_env * const envP,
+ xmlrpc_value * const valueP,
+ size_t * const lengthP,
+ const wchar_t ** const stringValueP) {
+
+ validateStringType(envP, valueP);
+ if (!envP->fault_occurred) {
+ setupWcsBlock(envP, valueP);
+
+ if (!envP->fault_occurred) {
+ wchar_t * const wcontents =
+ XMLRPC_MEMBLOCK_CONTENTS(wchar_t, valueP->_wcs_block);
+ size_t const size =
+ XMLRPC_MEMBLOCK_SIZE(wchar_t, valueP->_wcs_block);
+
+ *lengthP = size - 1; /* size includes terminating NUL */
+ *stringValueP = wcontents;
+ }
+ }
+}
+#endif /* HAVE_UNICODE_WCHAR */
+
+
+
+static void
+validateUtf(xmlrpc_env * const envP,
+ const char * const value,
+ size_t const length) {
+
+#if HAVE_UNICODE_WCHAR
+ xmlrpc_validate_utf8(envP, value, length);
+#endif
+}
+
+
+
+static void
+copyLines(xmlrpc_env * const envP,
+ const char * const src,
+ size_t const srcLen,
+ xmlrpc_mem_block * const dstP) {
+/*----------------------------------------------------------------------------
+ Copy the string 'src', 'srcLen' characters long, into 'dst', where
+ 'dst' is the internal representation of string xmlrpc_value contents,
+ and 'src' has lines separated by LF, CR, and/or CRLF.
+
+ Note that the source format differs from the destination format in
+ that in the destination format, lines are separated only by newline
+ (LF).
+
+ It is tempting to believe that if we just put the user's line
+ delimiters in the xmlrpc_value here (i.e. where user has CRLF, the
+ xmlrpc_value also has CRLF), the user's line delimiters would go
+ all the way across to the XML-RPC partner. But that won't work,
+ because the XML processor on the other side will, following Section
+ 2.11 of the XML spec, normalize all line endings to LF anyhow. So
+ then you might ask, why do we bother to do all the work to convert
+ them here? Because: besides just being logically cleaner, this way
+ xmlrpc_read_string() gets the proper value -- the same one the
+ XML-RPC partner would see.
+-----------------------------------------------------------------------------*/
+ /* Destination format is sometimes smaller than source (because
+ CRLF turns into LF), but never smaller. So we allocate
+ destination space equal to source size (plus one for
+ terminating NUL), but don't necessarily use it all.
+ */
+
+ /* To convert LF, CR, and CRLF to LF, all we have to do is
+ copy everything up to a CR verbatim, then insert an LF and
+ skip the CR and any following LF, and repeat.
+ */
+
+ XMLRPC_MEMBLOCK_INIT(char, envP, dstP, srcLen + 1);
+
+ if (!envP->fault_occurred) {
+ const char * const srcEnd = &src[srcLen];
+ char * const contents = XMLRPC_MEMBLOCK_CONTENTS(char, dstP);
+
+ const char * srcCursor;
+ char * dstCursor;
+
+ for (srcCursor = &src[0], dstCursor = &contents[0];
+ srcCursor < srcEnd;) {
+
+ char * const crPos = memchr(srcCursor, '\r', srcEnd - srcCursor);
+
+ if (crPos) {
+ size_t const copyLen = crPos - srcCursor;
+ memcpy(dstCursor, srcCursor, copyLen);
+ srcCursor += copyLen;
+ dstCursor += copyLen;
+
+ *(dstCursor++) = '\n';
+
+ XMLRPC_ASSERT(*srcCursor == '\r');
+ ++srcCursor; /* Move past CR */
+ if (*srcCursor == '\n')
+ ++srcCursor; /* Move past LF */
+ } else {
+ size_t const remainingLen = srcEnd - srcCursor;
+ memcpy(dstCursor, srcCursor, remainingLen);
+ srcCursor += remainingLen;
+ dstCursor += remainingLen;
+ }
+ }
+
+ *dstCursor++ = '\0';
+
+ XMLRPC_ASSERT((unsigned)(dstCursor - &contents[0]) <= srcLen + 1);
+
+ XMLRPC_MEMBLOCK_RESIZE(char, envP, dstP, dstCursor - &contents[0]);
+ }
+}
+
+
+
+static void
+copySimple(xmlrpc_env * const envP,
+ const char * const src,
+ size_t const srcLen,
+ xmlrpc_mem_block * const dstP) {
+/*----------------------------------------------------------------------------
+ Copy the string 'src', 'srcLen' characters long, into 'dst', where
+ 'dst' is the internal representation of string xmlrpc_value contents,
+ and 'src', conveniently enough, is in the exact same format.
+
+ To wit, 'src' has lines separated by LFs only -- no CR or CRLF.
+-----------------------------------------------------------------------------*/
+ XMLRPC_MEMBLOCK_INIT(char, envP, dstP, srcLen + 1);
+ if (!envP->fault_occurred) {
+ char * const contents = XMLRPC_MEMBLOCK_CONTENTS(char, dstP);
+
+ memcpy(contents, src, srcLen);
+ contents[srcLen] = '\0';
+ }
+}
+
+
+
+enum crTreatment { CR_IS_LINEDELIM, CR_IS_CHAR };
+
+static xmlrpc_value *
+stringNew(xmlrpc_env * const envP,
+ size_t const length,
+ const char * const value,
+ enum crTreatment const crTreatment) {
+
+ xmlrpc_value * valP;
+
+ validateUtf(envP, value, length);
+
+ if (!envP->fault_occurred) {
+ xmlrpc_createXmlrpcValue(envP, &valP);
+
+ if (!envP->fault_occurred) {
+ valP->_type = XMLRPC_TYPE_STRING;
+ valP->_wcs_block = NULL;
+
+ /* Note that copyLines() works for strings with no CRs, but
+ it's slower.
+ */
+ if (memchr(value, '\r', length) && crTreatment == CR_IS_LINEDELIM)
+ copyLines(envP, value, length, &valP->_block);
+ else
+ copySimple(envP, value, length, &valP->_block);
+
+ if (envP->fault_occurred)
+ free(valP);
+ }
+ }
+ return valP;
+}
+
+
+
+xmlrpc_value *
+xmlrpc_string_new_lp(xmlrpc_env * const envP,
+ size_t const length,
+ const char * const value) {
+
+ return stringNew(envP, length, value, CR_IS_LINEDELIM);
+}
+
+
+
+xmlrpc_value *
+xmlrpc_string_new_lp_cr(xmlrpc_env * const envP,
+ size_t const length,
+ const char * const value) {
+
+ return stringNew(envP, length, value, CR_IS_CHAR);
+}
+
+
+
+xmlrpc_value *
+xmlrpc_string_new(xmlrpc_env * const envP,
+ const char * const value) {
+
+ return stringNew(envP, strlen(value), value, CR_IS_LINEDELIM);
+}
+
+
+
+xmlrpc_value *
+xmlrpc_string_new_cr(xmlrpc_env * const envP,
+ const char * const value) {
+
+ return stringNew(envP, strlen(value), value, CR_IS_CHAR);
+}
+
+
+
+xmlrpc_value *
+xmlrpc_string_new_va(xmlrpc_env * const envP,
+ const char * const format,
+ va_list args) {
+
+ const char * formattedString;
+ xmlrpc_value * retvalP;
+
+ XMLRPC_ASSERT_ENV_OK(envP);
+ XMLRPC_ASSERT(format != NULL);
+
+ xmlrpc_vasprintf(&formattedString, format, args);
+
+ if (formattedString == xmlrpc_strsol) {
+ xmlrpc_faultf(envP, "Out of memory building formatted string");
+ retvalP = NULL; /* defeat compiler warning */
+ } else
+ retvalP = xmlrpc_string_new(envP, formattedString);
+
+ xmlrpc_strfree(formattedString);
+
+ return retvalP;
+}
+
+
+
+xmlrpc_value *
+xmlrpc_string_new_f(xmlrpc_env * const envP,
+ const char * const format,
+ ...) {
+
+ va_list args;
+ xmlrpc_value * retval;
+
+ va_start(args, format);
+
+ retval = xmlrpc_string_new_va(envP, format, args);
+
+ va_end(args);
+
+ return retval;
+}
+
+
+
+#if HAVE_UNICODE_WCHAR
+
+static xmlrpc_value *
+stringWNew(xmlrpc_env * const envP,
+ size_t const length,
+ const wchar_t * const value,
+ enum crTreatment const crTreatment) {
+
+ xmlrpc_value * valP;
+ xmlrpc_mem_block * utf8P;
+
+ valP = NULL; /* defeat compiler warning */
+
+ utf8P = xmlrpc_wcs_to_utf8(envP, value, length);
+ if (!envP->fault_occurred) {
+ char * const utf8_value = XMLRPC_MEMBLOCK_CONTENTS(char, utf8P);
+ size_t const utf8_len = XMLRPC_MEMBLOCK_SIZE(char, utf8P);
+
+ if (!envP->fault_occurred) {
+ valP = stringNew(envP, utf8_len, utf8_value, crTreatment);
+
+ XMLRPC_MEMBLOCK_FREE(char, utf8P);
+ }
+ }
+ return valP;
+}
+
+
+
+xmlrpc_value *
+xmlrpc_string_w_new_lp(xmlrpc_env * const envP,
+ size_t const length,
+ const wchar_t * const value) {
+
+ return stringWNew(envP, length, value, CR_IS_LINEDELIM);
+}
+
+
+
+
+xmlrpc_value *
+xmlrpc_string_w_new_lp_cr(xmlrpc_env * const envP,
+ size_t const length,
+ const wchar_t * const value) {
+
+ return stringWNew(envP, length, value, CR_IS_CHAR);
+}
+
+
+
+
+xmlrpc_value *
+xmlrpc_string_w_new(xmlrpc_env * const envP,
+ const wchar_t * const value) {
+
+ return stringWNew(envP, wcslen(value), value, CR_IS_LINEDELIM);
+}
+
+
+
+xmlrpc_value *
+xmlrpc_string_w_new_cr(xmlrpc_env * const envP,
+ const wchar_t * const value) {
+
+ return stringWNew(envP, wcslen(value), value, CR_IS_CHAR);
+}
+
+#endif /* HAVE_UNICODE_WCHAR */
Modified: freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_struct.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_struct.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/src/xmlrpc_struct.c Fri May 23 16:56:24 2008
@@ -31,6 +31,7 @@
#include "xmlrpc-c/base.h"
#include "xmlrpc-c/base_int.h"
+#include "int.h"
#define KEY_ERROR_BUFFER_SZ (32)
@@ -115,26 +116,23 @@
-/*=========================================================================
-** get_hash
-**=========================================================================
-** A mindlessly simple hash function. Please feel free to write something
-** more clever if this produces bad results.
-*/
-
-static unsigned char
-get_hash(const char * const key,
- size_t const key_len) {
+static uint32_t
+hashStructKey(const char * const key,
+ size_t const keyLen) {
- unsigned char retval;
+ uint32_t hash;
size_t i;
XMLRPC_ASSERT(key != NULL);
- retval = 0;
- for (i = 0; i < key_len; i++)
- retval += key[i];
- return retval;
+ /* This is the Bernstein hash, optimized for lower case ASCII
+ keys. Note that the bytes of such a key differ only in their
+ lower 5 bits.
+ */
+ for (hash = 0, i = 0; i < keyLen; ++i)
+ hash = hash + key[i] + (hash << 5);
+
+ return hash;
}
@@ -149,28 +147,28 @@
static int
find_member(xmlrpc_value * const strctP,
const char * const key,
- size_t const key_len) {
+ size_t const keyLen) {
size_t size, i;
- unsigned char hash;
- _struct_member *contents;
- xmlrpc_value *keyval;
- char *keystr;
- size_t keystr_size;
+ uint32_t searchHash;
+ _struct_member * contents; /* array */
+ xmlrpc_value * keyvalP;
+ const char * keystr;
+ size_t keystrSize;
XMLRPC_ASSERT_VALUE_OK(strctP);
XMLRPC_ASSERT(key != NULL);
/* Look for our key. */
- hash = get_hash(key, key_len);
+ searchHash = hashStructKey(key, keyLen);
size = XMLRPC_MEMBLOCK_SIZE(_struct_member, &strctP->_block);
contents = XMLRPC_MEMBLOCK_CONTENTS(_struct_member, &strctP->_block);
- for (i = 0; i < size; i++) {
- if (contents[i].key_hash == hash) {
- keyval = contents[i].key;
- keystr = XMLRPC_MEMBLOCK_CONTENTS(char, &keyval->_block);
- keystr_size = XMLRPC_MEMBLOCK_SIZE(char, &keyval->_block)-1;
- if (key_len == keystr_size && memcmp(key, keystr, key_len) == 0)
+ for (i = 0; i < size; ++i) {
+ if (contents[i].keyHash == searchHash) {
+ keyvalP = contents[i].key;
+ keystr = XMLRPC_MEMBLOCK_CONTENTS(char, &keyvalP->_block);
+ keystrSize = XMLRPC_MEMBLOCK_SIZE(char, &keyvalP->_block)-1;
+ if (keystrSize == keyLen && memcmp(key, keystr, keyLen) == 0)
return i;
}
}
@@ -336,7 +334,7 @@
if (*valuePP == NULL) {
xmlrpc_env_set_fault_formatted(
envP, XMLRPC_INDEX_ERROR, "No member of struct has key '%.*s'",
- XMLRPC_MEMBLOCK_SIZE(char, &keyP->_block),
+ (int)XMLRPC_MEMBLOCK_SIZE(char, &keyP->_block),
XMLRPC_MEMBLOCK_CONTENTS(char, &keyP->_block));
}
}
@@ -390,7 +388,7 @@
xmlrpc_env_set_fault_formatted(
envP, XMLRPC_INDEX_ERROR,
"No member of struct has key '%.*s'",
- keyLen, key);
+ (int)keyLen, key);
/* We should fix the error message to format the key
for display */
} else
@@ -436,29 +434,28 @@
xmlrpc_struct_set_value_n(xmlrpc_env * const envP,
xmlrpc_value * const strctP,
const char * const key,
- size_t const key_len,
+ size_t const keyLen,
xmlrpc_value * const valueP) {
- xmlrpc_value *keyval;
-
XMLRPC_ASSERT_ENV_OK(envP);
XMLRPC_ASSERT(key != NULL);
- /* Set up error handling preconditions. */
- keyval = NULL;
-
- XMLRPC_TYPE_CHECK(envP, strctP, XMLRPC_TYPE_STRUCT);
-
- /* Build an xmlrpc_value from our string. */
- keyval = xmlrpc_build_value(envP, "s#", key, key_len);
- XMLRPC_FAIL_IF_FAULT(envP);
+ if (xmlrpc_value_type(strctP) != XMLRPC_TYPE_STRUCT)
+ xmlrpc_env_set_fault_formatted(
+ envP, XMLRPC_TYPE_ERROR,
+ "Trying to set value in something not a struct. "
+ "Type is %d; struct is %d",
+ xmlrpc_value_type(strctP), XMLRPC_TYPE_STRUCT);
+ else {
+ xmlrpc_value * keyvalP;
- /* Do the actual work. */
- xmlrpc_struct_set_value_v(envP, strctP, keyval, valueP);
+ /* Get the key as an xmlrpc_value */
+ keyvalP = xmlrpc_build_value(envP, "s#", key, keyLen);
+ if (!envP->fault_occurred)
+ xmlrpc_struct_set_value_v(envP, strctP, keyvalP, valueP);
- cleanup:
- if (keyval)
- xmlrpc_DECREF(keyval);
+ xmlrpc_DECREF(keyvalP);
+ }
}
@@ -501,9 +498,9 @@
xmlrpc_DECREF(old_value);
} else {
/* Add a new member. */
- new_member.key_hash = get_hash(key, key_len);
- new_member.key = keyvalP;
- new_member.value = valueP;
+ new_member.keyHash = hashStructKey(key, key_len);
+ new_member.key = keyvalP;
+ new_member.value = valueP;
XMLRPC_MEMBLOCK_APPEND(_struct_member, envP, &strctP->_block,
&new_member, 1);
XMLRPC_FAIL_IF_FAULT(envP);
@@ -578,7 +575,7 @@
if (index < 0)
xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INDEX_ERROR, "Index %d is negative.");
+ envP, XMLRPC_INDEX_ERROR, "Index %d is negative.", index);
else {
xmlrpc_struct_read_member(envP, structP, index, keyvalP, valueP);
if (!envP->fault_occurred) {
Modified: freeswitch/trunk/libs/xmlrpc-c/tools/Makefile
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/tools/Makefile (original)
+++ freeswitch/trunk/libs/xmlrpc-c/tools/Makefile Fri May 23 16:56:24 2008
@@ -1,22 +1,25 @@
-SUBDIR=tools
-ifeq ($(SRCDIR)x,x)
-SRCDIR = $(CURDIR)/..
-BUILDDIR = $(SRCDIR)
+ifeq ($(SRCDIR),)
+ updir = $(shell echo $(dir $(1)) | sed 's/.$$//')
+ SRCDIR := $(call updir,$(CURDIR))
+ BLDDIR := $(SRCDIR)
endif
+SUBDIR := tools
-include $(SRCDIR)/Makefile.config
+include $(BLDDIR)/config.mk
SUBDIRS = binmode-rpc-kit turbocharger
ifeq ($(MUST_BUILD_CLIENT),yes)
SUBDIRS += xmlrpc xmlrpc_transport
-endif
-ifeq ($(ENABLE_CPLUSPLUS),yes)
- SUBDIRS += xml-rpc-api2cpp
+ ifeq ($(ENABLE_CPLUSPLUS),yes)
+ SUBDIRS += xml-rpc-api2cpp xmlrpc_cpp_proxy
+ # We could add 'xmlrpc_pstream' here, but we don't because we don't
+ # want to deal with finding the Readline/Ncurses libraries.
+ endif
endif
-.PHONY: all clean distclean install dep
+.PHONY: all clean distclean install check dep
all: $(SUBDIRS:%=%/all)
@@ -26,6 +29,8 @@
install: $(SUBDIRS:%=%/install)
+check:
+
dep: $(SUBDIRS:%=%/dep)
-include $(SRCDIR)/Makefile.common
+include $(SRCDIR)/common.mk
Added: freeswitch/trunk/libs/xmlrpc-c/tools/common.mk
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/tools/common.mk Fri May 23 16:56:24 2008
@@ -0,0 +1,43 @@
+# We try to get Xmlrpc-c directories early in the link library search
+# path to avert problems with other versions of Xmlrpc-c being in more
+# general directories (such as /usr/local/lib) that are added to the
+# search path by curl-config, etc. That's why we separate the -L from
+# the corresponding -l.
+#
+# Note that in a properly configured system, curl-config, etc. do not
+# generate -L options for general directories.
+
+CLIENT_LDLIBS = -Lblddir/src -Lblddir/lib/libutil
+
+CLIENT_LDLIBS += -lxmlrpc_client -lxmlrpc -lxmlrpc_util
+
+ifeq ($(MUST_BUILD_LIBWWW_CLIENT),yes)
+ CLIENT_LDLIBS += $(shell libwww-config --libs)
+endif
+ifeq ($(MUST_BUILD_CURL_CLIENT),yes)
+ CLIENT_LDLIBS += $(shell curl-config --libs)
+endif
+ifeq ($(MUST_BUILD_WININET_CLIENT),yes)
+ CLIENT_LDLIBS += $(shell wininet-config --libs)
+endif
+
+CLIENT_LDLIBS += $(LDLIBS_XML)
+
+CLIENTPP_LDLIBS = -Lblddir/src/cpp
+CLIENTPP_LDLIBS += -lxmlrpc_client++ -lxmlrpc_packetsocket -lxmlrpc++
+
+include $(SRCDIR)/common.mk
+
+ifneq ($(OMIT_LIB_RULE),Y)
+srcdir/tools/lib/dumpvalue.o: FORCE
+ $(MAKE) -C $(dir $@) -f $(SRCDIR)/tools/lib/Makefile $(notdir $@)
+endif
+
+.PHONY: install
+install: install-common
+
+.PHONY: check
+check:
+
+.PHONY: FORCE
+FORCE:
Added: freeswitch/trunk/libs/xmlrpc-c/tools/lib/Makefile
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/tools/lib/Makefile Fri May 23 16:56:24 2008
@@ -0,0 +1,48 @@
+ifeq ($(SRCDIR),)
+ updir = $(shell echo $(dir $(1)) | sed 's/.$$//')
+ TOOLSDIR := $(call updir,$(CURDIR))
+ SRCDIR := $(call updir,$(TOOLSDIR))
+ BLDDIR := $(SRCDIR)
+endif
+SUBDIR := tools/lib
+
+default: all
+
+include $(BLDDIR)/config.mk
+
+OMIT_LIB_RULE = Y
+
+include $(SRCDIR)/tools/common.mk
+
+INCLUDES = \
+ -Isrcdir/$(SUBDIR)/include \
+ -Iblddir \
+ -Isrcdir/include \
+ -Isrcdir/lib/util/include \
+
+CFLAGS = $(CFLAGS_COMMON) $(INCLUDES) $(CFLAGS_PERSONAL) $(CADD)
+
+LIBOBJS = \
+ dumpvalue.o \
+
+.PHONY: all
+all: $(LIBOBJS)
+
+%.o:%.c
+ $(CC) -c $(CFLAGS) $<
+
+# This common.mk dependency makes sure the symlinks get built before
+# this make file is used for anything.
+
+$(SRCDIR)/tool/common.mk: srcdir blddir
+
+include Makefile.depend
+
+.PHONY: dep
+dep: dep-common
+
+.PHONY: clean
+clean: clean-common
+
+.PHONY: distclean
+distclean: clean distclean-common
Added: freeswitch/trunk/libs/xmlrpc-c/tools/lib/dumpvalue.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/tools/lib/dumpvalue.c Fri May 23 16:56:24 2008
@@ -0,0 +1,475 @@
+/* dumpvalue() service, which prints to Standard Output the value of
+ an xmlrpc_value.
+
+ We've put this in a separate module in hopes that it eventually can be
+ used for debugging purposes in other places.
+*/
+
+#define _GNU_SOURCE
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "xmlrpc_config.h" /* information about this build environment */
+#include "int.h"
+#include "casprintf.h"
+#include "mallocvar.h"
+
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/string_int.h"
+
+#include "dumpvalue.h"
+
+
+
+static void
+dumpInt(const char * const prefix,
+ xmlrpc_value * const valueP) {
+
+ xmlrpc_env env;
+ xmlrpc_int value;
+
+ xmlrpc_env_init(&env);
+
+ xmlrpc_read_int(&env, valueP, &value);
+
+ if (env.fault_occurred)
+ printf("Internal error: unable to extract value of "
+ "integer xmlrpc_value %lx. %s\n",
+ (unsigned long)valueP, env.fault_string);
+ else
+ printf("%sInteger: %d\n", prefix, value);
+
+ xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+dumpBool(const char * const prefix,
+ xmlrpc_value * const valueP) {
+
+ xmlrpc_env env;
+ xmlrpc_bool value;
+
+ xmlrpc_env_init(&env);
+
+ xmlrpc_read_bool(&env, valueP, &value);
+
+ if (env.fault_occurred)
+ printf("Internal error: Unable to extract value of "
+ "boolean xmlrpc_value %lx. %s\n",
+ (unsigned long)valueP, env.fault_string);
+ else
+ printf("%sBoolean: %s\n", prefix, value ? "TRUE" : "FALSE");
+
+ xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+dumpDouble(const char * const prefix,
+ xmlrpc_value * const valueP) {
+
+ xmlrpc_env env;
+ xmlrpc_double value;
+
+ xmlrpc_env_init(&env);
+
+ xmlrpc_read_double(&env, valueP, &value);
+
+ if (env.fault_occurred)
+ printf("Internal error: Unable to extract value from "
+ "floating point number xmlrpc_value %lx. %s\n",
+ (unsigned long)valueP, env.fault_string);
+ else
+ printf("%sFloating Point: %f\n", prefix, value);
+
+ xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+dumpDatetime(const char * const prefix,
+ xmlrpc_value * const valueP) {
+
+ printf("%sDon't know how to print datetime value %lx.\n",
+ prefix, (unsigned long) valueP);
+}
+
+
+
+static size_t
+nextLineSize(const char * const string,
+ size_t const startPos,
+ size_t const stringSize) {
+/*----------------------------------------------------------------------------
+ Return the length of the line that starts at offset 'startPos' in the
+ string 'string', which is 'stringSize' characters long.
+
+ 'string' in not NUL-terminated.
+
+ A line begins at beginning of string or after a newline character and
+ runs through the next newline character or end of string. The line
+ includes the newline character at the end, if any.
+-----------------------------------------------------------------------------*/
+ size_t i;
+
+ for (i = startPos; i < stringSize && string[i] != '\n'; ++i);
+
+ if (i < stringSize)
+ ++i; /* Include the newline */
+
+ return i - startPos;
+}
+
+
+
+static void
+dumpMultilineString(const char * const prefix,
+ const char * const value,
+ size_t const length) {
+
+ size_t cursor; /* Index into value[] */
+
+ for (cursor = 0; cursor < length; ) {
+ /* Print one line of buffer */
+
+ size_t const lineSize = nextLineSize(value, cursor, length);
+ const char * const printableLine =
+ xmlrpc_makePrintable_lp(&value[cursor], lineSize);
+
+ printf("%s%s\n", prefix, printableLine);
+
+ cursor += lineSize;
+
+ strfree(printableLine);
+ }
+}
+
+
+
+static void
+dumpSimpleString(const char * const value,
+ size_t const length) {
+
+ const char * const printable = xmlrpc_makePrintable_lp(value, length);
+
+ printf("'%s'\n", printable);
+
+ strfree(printable);
+}
+
+
+
+static void
+dumpString(const char * const prefix,
+ xmlrpc_value * const valueP) {
+
+ xmlrpc_env env;
+ size_t length;
+ const char * value;
+
+ xmlrpc_env_init(&env);
+
+ xmlrpc_read_string_lp(&env, valueP, &length, &value);
+
+ if (env.fault_occurred)
+ printf("Internal error: Unable to extract value from "
+ "string xmlrpc_value %lx. %s\n",
+ (unsigned long)valueP, env.fault_string);
+ else {
+ printf("%sString: ", prefix);
+ if (strlen(value) == length && strchr(value, '\n')) {
+ const char * prefix2;
+ casprintf(&prefix2, "%s ", prefix);
+ printf("\n");
+ dumpMultilineString(prefix2, value, length);
+ strfree(prefix2);
+ } else
+ dumpSimpleString(value, length);
+
+ strfree(value);
+ }
+ xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+dumpBase64(const char * const prefix,
+ xmlrpc_value * const valueP) {
+
+ xmlrpc_env env;
+ const unsigned char * value;
+ size_t length;
+
+ xmlrpc_env_init(&env);
+
+ xmlrpc_read_base64(&env, valueP, &length, &value);
+
+ if (env.fault_occurred)
+ printf("Unable to parse base64 bit string xmlrpc_value %lx. %s\n",
+ (unsigned long)valueP, env.fault_string);
+ else {
+ unsigned int i;
+
+ printf("%sBit string: ", prefix);
+ for (i = 0; i < length; ++i)
+ printf("%02x", value[i]);
+
+ free((void*)value);
+ }
+ xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+dumpArray(const char * const prefix,
+ xmlrpc_value * const arrayP) {
+
+ xmlrpc_env env;
+ unsigned int arraySize;
+
+ xmlrpc_env_init(&env);
+
+ XMLRPC_ASSERT_ARRAY_OK(arrayP);
+
+ arraySize = xmlrpc_array_size(&env, arrayP);
+ if (env.fault_occurred)
+ printf("Unable to get array size. %s\n", env.fault_string);
+ else {
+ int const spaceCount = strlen(prefix);
+
+ unsigned int i;
+ const char * blankPrefix;
+
+ printf("%sArray of %u items:\n", prefix, arraySize);
+
+ casprintf(&blankPrefix, "%*s", spaceCount, "");
+
+ for (i = 0; i < arraySize; ++i) {
+ xmlrpc_value * valueP;
+
+ xmlrpc_array_read_item(&env, arrayP, i, &valueP);
+
+ if (env.fault_occurred)
+ printf("Unable to get array item %u\n", i);
+ else {
+ const char * prefix2;
+
+ casprintf(&prefix2, "%s Index %2u ", blankPrefix, i);
+ dumpValue(prefix2, valueP);
+ strfree(prefix2);
+
+ xmlrpc_DECREF(valueP);
+ }
+ }
+ strfree(blankPrefix);
+ }
+ xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+dumpStructMember(const char * const prefix,
+ xmlrpc_value * const structP,
+ unsigned int const index) {
+
+ xmlrpc_env env;
+
+ xmlrpc_value * keyP;
+ xmlrpc_value * valueP;
+
+ xmlrpc_env_init(&env);
+
+ xmlrpc_struct_read_member(&env, structP, index, &keyP, &valueP);
+
+ if (env.fault_occurred)
+ printf("Unable to get struct member %u\n", index);
+ else {
+ int const blankCount = strlen(prefix);
+ const char * prefix2;
+ const char * blankPrefix;
+
+ casprintf(&prefix2, "%s Key: ", prefix);
+ dumpValue(prefix2, keyP);
+ strfree(prefix2);
+
+ casprintf(&blankPrefix, "%*s", blankCount, "");
+
+ casprintf(&prefix2, "%s Value: ", blankPrefix);
+ dumpValue(prefix2, valueP);
+ strfree(prefix2);
+
+ strfree(blankPrefix);
+
+ xmlrpc_DECREF(keyP);
+ xmlrpc_DECREF(valueP);
+ }
+ xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+dumpStruct(const char * const prefix,
+ xmlrpc_value * const structP) {
+
+ xmlrpc_env env;
+ unsigned int structSize;
+
+ xmlrpc_env_init(&env);
+
+ structSize = xmlrpc_struct_size(&env, structP);
+ if (env.fault_occurred)
+ printf("Unable to get struct size. %s\n", env.fault_string);
+ else {
+ unsigned int i;
+
+ printf("%sStruct of %u members:\n", prefix, structSize);
+
+ for (i = 0; i < structSize; ++i) {
+ const char * prefix1;
+
+ if (i == 0)
+ prefix1 = strdup(prefix);
+ else {
+ int const blankCount = strlen(prefix);
+ casprintf(&prefix1, "%*s", blankCount, "");
+ }
+ dumpStructMember(prefix1, structP, i);
+
+ strfree(prefix1);
+ }
+ }
+ xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+dumpCPtr(const char * const prefix,
+ xmlrpc_value * const valueP) {
+
+ xmlrpc_env env;
+ void * value;
+
+ xmlrpc_env_init(&env);
+
+ xmlrpc_read_cptr(&env, valueP, &value);
+
+ if (env.fault_occurred)
+ printf("Unable to parse C pointer xmlrpc_value %lx. %s\n",
+ (unsigned long)valueP, env.fault_string);
+ else
+ printf("%sC pointer: '%lux'\n", prefix, (unsigned long)value);
+
+ xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+dumpNil(const char * const prefix,
+ xmlrpc_value * const valueP) {
+
+ xmlrpc_env env;
+
+ xmlrpc_env_init(&env);
+
+ xmlrpc_read_nil(&env, valueP);
+
+ if (env.fault_occurred)
+ printf("Internal error: nil value xmlrpc_value %lx "
+ "is not valid. %s\n",
+ (unsigned long)valueP, env.fault_string);
+ else
+ printf("%sNil\n", prefix);
+
+ xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+dumpI8(const char * const prefix,
+ xmlrpc_value * const valueP) {
+
+ xmlrpc_env env;
+ xmlrpc_int64 value;
+
+ xmlrpc_env_init(&env);
+
+ xmlrpc_read_i8(&env, valueP, &value);
+
+ if (env.fault_occurred)
+ printf("Internal error: unable to extract value of "
+ "64-bit integer xmlrpc_value %lx. %s\n",
+ (unsigned long)valueP, env.fault_string);
+ else
+ printf("%s64-bit integer: %" PRId64 "\n", prefix, value);
+
+ xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+dumpUnknown(const char * const prefix,
+ xmlrpc_value * const valueP) {
+
+ printf("%sDon't recognize value type %u of xmlrpc_value %lx.\n",
+ prefix, xmlrpc_value_type(valueP), (unsigned long)valueP);
+ printf("%sCan't print it.\n", prefix);
+}
+
+
+
+void
+dumpValue(const char * const prefix,
+ xmlrpc_value * const valueP) {
+
+ switch (xmlrpc_value_type(valueP)) {
+ case XMLRPC_TYPE_INT:
+ dumpInt(prefix, valueP);
+ break;
+ case XMLRPC_TYPE_BOOL:
+ dumpBool(prefix, valueP);
+ break;
+ case XMLRPC_TYPE_DOUBLE:
+ dumpDouble(prefix, valueP);
+ break;
+ case XMLRPC_TYPE_DATETIME:
+ dumpDatetime(prefix, valueP);
+ break;
+ case XMLRPC_TYPE_STRING:
+ dumpString(prefix, valueP);
+ break;
+ case XMLRPC_TYPE_BASE64:
+ dumpBase64(prefix, valueP);
+ break;
+ case XMLRPC_TYPE_ARRAY:
+ dumpArray(prefix, valueP);
+ break;
+ case XMLRPC_TYPE_STRUCT:
+ dumpStruct(prefix, valueP);
+ break;
+ case XMLRPC_TYPE_C_PTR:
+ dumpCPtr(prefix, valueP);
+ break;
+ case XMLRPC_TYPE_NIL:
+ dumpNil(prefix, valueP);
+ break;
+ case XMLRPC_TYPE_I8:
+ dumpI8(prefix, valueP);
+ break;
+ default:
+ dumpUnknown(prefix, valueP);
+ }
+}
Added: freeswitch/trunk/libs/xmlrpc-c/tools/lib/include/dumpvalue.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/tools/lib/include/dumpvalue.h Fri May 23 16:56:24 2008
@@ -0,0 +1,10 @@
+#ifndef DUMPVALUE_H_INCLUDED
+#define DUMPVALUE_H_INCLUDED
+
+struct _xmlrpc_value;
+
+void
+dumpValue(const char * const prefix,
+ struct _xmlrpc_value * const valueP);
+
+#endif
Added: freeswitch/trunk/libs/xmlrpc-c/tools/perl_packetsocket/PacketSocket.pm
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/tools/perl_packetsocket/PacketSocket.pm Fri May 23 16:56:24 2008
@@ -0,0 +1,186 @@
+###############################################################################
+#
+# This Perl module provides a "packet socket" of the kind that
+# XML-RPC For C/C++ uses for its "packet stream" variation on XML-RPC.
+#
+# This module does not use the XML-RPC For C/C++ libraries. It is
+# pure Perl and layers on top of IO::Socket.
+#
+# By Bryan Henderson, San Jose CA 08.03.12.
+#
+# Contributed to the public domain by author.
+#
+###############################################################################
+
+package IO::PacketSocket;
+
+use strict;
+use warnings;
+use Exporter;
+use Carp;
+use vars qw(@ISA $VERSION @EXPORT);
+use Errno qw(:POSIX);
+use English;
+use IO::Socket::INET
+
+
+$VERSION = 1.00;
+ at ISA = qw(Exporter IO);
+
+my ($TRUE, $FALSE) = (1,0);
+
+my $ESC = chr(0x1B); # ASCII Escape
+
+my $startDelim = $ESC . 'PKT';
+my $endDelim = $ESC . 'END';
+my $escapedEsc = $ESC . 'ESC';
+
+
+sub createObject {
+ my ($class, %args) = @_;
+
+ my $errorRet;
+ # Description of why we can't create the object. Undefined if
+ # we haven't given up yet.
+
+ my $packetSocket;
+
+ $packetSocket = {};
+
+ bless ($packetSocket, $class);
+
+ if (defined($args{STREAMSOCKET})) {
+ $packetSocket->{STREAMSOCKET} = $args{STREAMSOCKET};
+ } else {
+ $errorRet = "You must specify STREAMSOCKET";
+ }
+
+ $packetSocket->{RECEIVE_BUFFER} = '';
+
+ if ($errorRet && !$args{ERROR}) {
+ carp("Failed to create PacketSocket object. $errorRet");
+ }
+ if ($args{ERROR}) {
+ $ {$args{ERROR}} = $errorRet;
+ }
+ if ($args{HANDLE}) {
+ $ {$args{HANDLE}} = $packetSocket;
+ }
+}
+
+
+
+sub new {
+
+ my ($class, %args) = @_;
+
+ $args{HANDLE} = \my $retval;
+ $args{ERROR} = undef;
+
+ $class->createObject(%args);
+
+ return $retval;
+}
+
+
+
+sub escaped($) {
+ my ($x) = @_;
+#-----------------------------------------------------------------------------
+# Return $x, but properly escaped to be inside a packet socket
+# packet.
+#-----------------------------------------------------------------------------
+
+ $x =~ s{$ESC}{$escapedEsc}g;
+
+ return $x;
+}
+
+
+
+sub unescaped($) {
+ my ($x) = @_;
+#-----------------------------------------------------------------------------
+# Inverse of escaped()
+#-----------------------------------------------------------------------------
+
+ $x =~ s{$escapedEsc}{$ESC}g;
+
+ return $x;
+}
+
+
+
+sub send() {
+ my($this, $payload) = @_;
+
+ my $retval;
+
+ my $packet = $startDelim . escaped($payload) . $endDelim;
+
+ $retval = $this->{STREAMSOCKET}->send($packet);
+
+ return $retval;
+}
+
+
+
+sub havePacket() {
+
+ my ($this) = @_;
+
+ return ($this->{RECEIVE_BUFFER} =~ m{$endDelim});
+}
+
+
+
+sub validatePacketStart($) {
+
+ my ($packetR) = @_;
+
+ my $delim = substr($$packetR, 0, 4);
+
+ if ($startDelim !~ m{^$delim}) {
+ die("Received bytes '$delim' are not in any packet. " .
+ "Sender is probably not using a packet socket");
+ }
+}
+
+
+
+sub recv() {
+ my ($this, $payloadR) = @_;
+
+ my $gotPacket;
+ my $eof;
+ my $escapedPacket;
+
+ $gotPacket = $FALSE;
+ $eof = $FALSE;
+
+ while (!$gotPacket && !$eof) {
+ validatePacketStart(\$this->{RECEIVE_BUFFER});
+
+ $this->{STREAMSOCKET}->recv(my $buffer, 4096, 0);
+
+ if ($buffer eq '') {
+ $eof = $TRUE;
+ } else {
+ $this->{RECEIVE_BUFFER} .= $buffer;
+ }
+
+ validatePacketStart(\$this->{RECEIVE_BUFFER});
+
+ if ($this->{RECEIVE_BUFFER} =~
+ m{^($startDelim)(.*?)($endDelim)(.*)}s) {
+
+ ($escapedPacket, $this->{RECEIVE_BUFFER}) = ($2, $3);
+
+ $gotPacket = $TRUE;
+ }
+ }
+
+ $$payloadR = $eof ? '' : unescaped($escapedPacket);
+}
+
+1;
Modified: freeswitch/trunk/libs/xmlrpc-c/tools/turbocharger/mod_gzip.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/tools/turbocharger/mod_gzip.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/tools/turbocharger/mod_gzip.c Fri May 23 16:56:24 2008
@@ -355,6 +355,7 @@
* End of inline comments
*/
+#include <stdlib.h>
/*
* Apache headers...
*/
@@ -6722,7 +6723,6 @@
# define STDC_HEADERS
# define SET_BINARY_MODE(fd) setmode(fd, O_BINARY)
# include <io.h>
-# include <malloc.h>
# ifdef NTFAT
# define NO_MULTIPLE_DOTS
# define MAX_EXT_CHARS 3
@@ -6742,7 +6742,6 @@
void * fcalloc (unsigned items, unsigned size);
void fcfree (void *ptr);
# else
-# include <malloc.h>
# define fcalloc(nitems,itemsize) halloc((long)(nitems),(itemsize))
# define fcfree(ptr) hfree(ptr)
# endif
Modified: freeswitch/trunk/libs/xmlrpc-c/tools/xml-rpc-api2cpp/DataType.cpp
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/tools/xml-rpc-api2cpp/DataType.cpp (original)
+++ freeswitch/trunk/libs/xmlrpc-c/tools/xml-rpc-api2cpp/DataType.cpp Fri May 23 16:56:24 2008
@@ -1,6 +1,8 @@
#include <iostream>
#include <sstream>
#include <stdexcept>
+#include <map>
+#include <vector>
#include "xmlrpc-c/oldcppwrapper.hpp"
#include "DataType.hpp"
@@ -15,50 +17,66 @@
// Instances of DataType know how generate code fragments for manipulating
// a specific XML-RPC data type.
-string DataType::defaultParameterBaseName (int position) const {
- ostringstream name_stream;
- name_stream << typeName() << position << ends;
- string name(name_stream.str());
- return name;
+string
+DataType::defaultParameterBaseName(unsigned int const position) const {
+
+ ostringstream nameStream;
+
+ nameStream << typeName() << position;
+
+ return nameStream.str();
}
-//=========================================================================
-// class RawDataType
-//=========================================================================
-// We want to manipulate some XML-RPC data types as XmlRpcValue objects.
class RawDataType : public DataType {
public:
- RawDataType (const string& type_name) : DataType(type_name) {}
+ RawDataType(string const& typeName) : DataType(typeName) {}
- virtual string parameterFragment (const string& base_name) const;
- virtual string inputConversionFragment (const string& base_name) const;
- virtual string returnTypeFragment () const;
- virtual string outputConversionFragment (const string& var_name) const;
+ virtual string
+ parameterFragment(string const& baseName) const;
+
+ virtual string
+ inputConversionFragment(string const& baseName) const;
+
+ virtual string
+ returnTypeFragment() const;
+
+ virtual string
+ outputConversionFragment(string const& varName) const;
};
-string RawDataType::parameterFragment (const string& base_name) const {
- return "XmlRpcValue /*" + typeName() + "*/ " + base_name;
+
+
+string
+RawDataType::parameterFragment(string const& baseName) const {
+ return "XmlRpcValue /*" + typeName() + "*/ " + baseName;
}
-string RawDataType::inputConversionFragment (const string& base_name) const {
- return base_name;
+
+
+string
+RawDataType::inputConversionFragment(string const& baseName) const {
+
+ return baseName;
}
-string RawDataType::returnTypeFragment () const {
+
+
+string
+RawDataType::returnTypeFragment() const {
return "XmlRpcValue /*" + typeName() + "*/";
}
-string RawDataType::outputConversionFragment (const string& var_name) const {
- return var_name;
+
+
+string
+RawDataType::outputConversionFragment(string const& varName) const {
+
+ return varName;
}
-//=========================================================================
-// class SimpleDataType
-//=========================================================================
-// Other types can be easily converted to and from a single native type.
class SimpleDataType : public DataType {
string mNativeType;
@@ -66,130 +84,185 @@
string mGetterFunc;
public:
- SimpleDataType (const string& type_name,
- const string& native_type,
- const string& maker_func,
- const string& getter_func);
-
- virtual string parameterFragment (const string& base_name) const;
- virtual string inputConversionFragment (const string& base_name) const;
- virtual string returnTypeFragment () const;
- virtual string outputConversionFragment (const string& var_name) const;
+ SimpleDataType(string const& typeName,
+ string const& nativeType,
+ string const& makerFunc,
+ string const& getterFunc);
+
+ virtual string
+ parameterFragment(string const& baseName) const;
+
+ virtual string
+ inputConversionFragment(string const& baseName) const;
+
+ virtual string
+ returnTypeFragment() const;
+
+ virtual string
+ outputConversionFragment(string const& varName) const;
};
-SimpleDataType::SimpleDataType (const string& type_name,
- const string& native_type,
- const string& maker_func,
- const string& getter_func)
- : DataType(type_name),
- mNativeType(native_type),
- mMakerFunc(maker_func),
- mGetterFunc(getter_func)
-{
+
+
+SimpleDataType::SimpleDataType(string const& typeName,
+ string const& nativeType,
+ string const& makerFunc,
+ string const& getterFunc)
+ : DataType(typeName),
+ mNativeType(nativeType),
+ mMakerFunc(makerFunc),
+ mGetterFunc(getterFunc) {
}
-string SimpleDataType::parameterFragment (const string& base_name) const {
- return mNativeType + " " + base_name;
+
+
+string
+SimpleDataType::parameterFragment(string const& baseName) const {
+
+ return mNativeType + " const " + baseName;
}
-string SimpleDataType::inputConversionFragment (const string& base_name) const
-{
- return mMakerFunc + "(" + base_name + ")";
+
+
+string
+SimpleDataType::inputConversionFragment(string const& baseName) const {
+
+ return mMakerFunc + "(" + baseName + ")";
}
-string SimpleDataType::returnTypeFragment () const {
+
+
+string
+SimpleDataType::returnTypeFragment() const {
+
return mNativeType;
}
-string SimpleDataType::outputConversionFragment (const string& var_name) const
-{
- return var_name + "." + mGetterFunc + "()";
+
+
+string
+SimpleDataType::outputConversionFragment(string const& varName) const {
+ return varName + "." + mGetterFunc + "()";
}
-//=========================================================================
-// class VoidDataType
-//=========================================================================
-// Some XML-RPC servers declare functions as void. Such functions have
-// an arbitrary return value which we should ignore.
class VoidDataType : public DataType {
public:
- VoidDataType () : DataType("void") {}
+ VoidDataType() : DataType("void") {}
- virtual string parameterFragment (const string& base_name) const;
- virtual string inputConversionFragment (const string& base_name) const;
- virtual string returnTypeFragment () const;
- virtual string outputConversionFragment (const string& var_name) const;
+ virtual string
+ parameterFragment(string const& baseName) const;
+
+ virtual string
+ inputConversionFragment(string const& baseName) const;
+
+ virtual string
+ returnTypeFragment() const;
+
+ virtual string
+ outputConversionFragment(string const& varName) const;
};
-string VoidDataType::parameterFragment (const string&) const {
+
+
+string
+VoidDataType::parameterFragment(string const&) const {
+
throw domain_error("Can't handle functions with 'void' arguments'");
-
}
-string VoidDataType::inputConversionFragment (const string&) const {
+
+
+string
+VoidDataType::inputConversionFragment(string const&) const {
+
throw domain_error("Can't handle functions with 'void' arguments'");
}
-string VoidDataType::returnTypeFragment () const {
+
+
+string
+VoidDataType::returnTypeFragment () const {
+
return "void";
}
-string VoidDataType::outputConversionFragment (const string&) const {
+
+
+string
+VoidDataType::outputConversionFragment(string const&) const {
return "/* Return value ignored. */";
}
-//=========================================================================
-// function findDataType
-//=========================================================================
-// Given the name of an XML-RPC data type, try to find a corresponding
-// DataType object.
-SimpleDataType intType ("int", "XmlRpcValue::int32",
- "XmlRpcValue::makeInt",
- "getInt");
-SimpleDataType boolType ("bool", "bool",
- "XmlRpcValue::makeBool",
- "getBool");
-SimpleDataType doubleType ("double", "double",
- "XmlRpcValue::makeDouble",
- "getDouble");
-SimpleDataType stringType ("string", "string",
- "XmlRpcValue::makeString",
- "getString");
-
-RawDataType dateTimeType ("dateTime");
-RawDataType base64Type ("base64");
-RawDataType structType ("struct");
-RawDataType arrayType ("array");
+static SimpleDataType const intType ("int", "XmlRpcValue::int32",
+ "XmlRpcValue::makeInt",
+ "getInt");
+static SimpleDataType const boolType ("bool", "bool",
+ "XmlRpcValue::makeBool",
+ "getBool");
+static SimpleDataType const doubleType ("double", "double",
+ "XmlRpcValue::makeDouble",
+ "getDouble");
+static SimpleDataType const stringType ("string", "std::string",
+ "XmlRpcValue::makeString",
+ "getString");
+
+static RawDataType const dateTimeType ("dateTime");
+static RawDataType const base64Type ("base64");
+static RawDataType const structType ("struct");
+static RawDataType const arrayType ("array");
+
+static VoidDataType const voidType;
+
-VoidDataType voidType;
-const DataType& findDataType (const string& name) {
+const DataType&
+findDataType(string const& name) {
+/*----------------------------------------------------------------------------
+ Given the name of an XML-RPC data type, try to find a corresponding
+ DataType object.
+-----------------------------------------------------------------------------*/
if (name == "int" || name == "i4")
- return intType;
+ return intType;
else if (name == "boolean")
- return boolType;
+ return boolType;
else if (name == "double")
- return doubleType;
+ return doubleType;
else if (name == "string")
- return stringType;
+ return stringType;
else if (name == "dateTime.iso8601")
- return dateTimeType;
+ return dateTimeType;
else if (name == "base64")
- return base64Type;
+ return base64Type;
else if (name == "struct")
- return structType;
+ return structType;
else if (name == "array")
- return arrayType;
+ return arrayType;
else if (name == "void")
- return voidType;
+ return voidType;
+ else if (name == "INT")
+ return intType;
+ else if (name == "BOOLEAN")
+ return boolType;
+ else if (name == "DOUBLE")
+ return doubleType;
+ else if (name == "STRING")
+ return stringType;
+ else if (name == "DATETIME.ISO8601")
+ return dateTimeType;
+ else if (name == "BASE64")
+ return base64Type;
+ else if (name == "STRUCT")
+ return structType;
+ else if (name == "ARRAY")
+ return arrayType;
+ else if (name == "VOID")
+ return voidType;
+ else if (name == "NIL")
+ return voidType;
else
- throw domain_error("Unknown XML-RPC type " + name);
-
- // This code should never be executed.
- XMLRPC_ASSERT(0);
- return intType;
+ throw domain_error("Unknown XML-RPC type name '" + name + "'");
}
Modified: freeswitch/trunk/libs/xmlrpc-c/tools/xml-rpc-api2cpp/DataType.hpp
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/tools/xml-rpc-api2cpp/DataType.hpp (original)
+++ freeswitch/trunk/libs/xmlrpc-c/tools/xml-rpc-api2cpp/DataType.hpp Fri May 23 16:56:24 2008
@@ -23,7 +23,7 @@
// Given a parameter position, calculate a unique base name for all
// parameter-related variables.
virtual std::string
- defaultParameterBaseName(int position) const;
+ defaultParameterBaseName(unsigned int const position) const;
// Virtual functions for processing parameters.
virtual std::string
Modified: freeswitch/trunk/libs/xmlrpc-c/tools/xml-rpc-api2cpp/Makefile
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/tools/xml-rpc-api2cpp/Makefile (original)
+++ freeswitch/trunk/libs/xmlrpc-c/tools/xml-rpc-api2cpp/Makefile Fri May 23 16:56:24 2008
@@ -1,21 +1,32 @@
-ifeq ($(SRCDIR)x,x)
-SRCDIR = $(CURDIR)/../..
-BUILDDIR= $(SRCDIR)
+ifeq ($(SRCDIR),)
+ updir = $(shell echo $(dir $(1)) | sed 's/.$$//')
+ TOOLSDIR := $(call updir,$(CURDIR))
+ SRCDIR := $(call updir,$(TOOLSDIR))
+ BLDDIR := $(SRCDIR)
endif
+SUBDIR := tools/xml-rpc-api2cpp
default: all
-include $(BUILDDIR)/Makefile.config
+include $(BLDDIR)/config.mk
-include ../Makefile.common
+include $(SRCDIR)/tools/common.mk
-INCLUDES = -I$(SRCDIR) -I$(SRCDIR)/include
+INCLUDES = -I$(BLDDIR) -I$(BLDDIR)/include -I$(SRCDIR)/include
CXXFLAGS = $(INCLUDES) $(CXXFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD)
-LDFLAGS = $(CLIENT_LDFLAGS) $(LADD)
+LDFLAGS = $(LADD)
-all: xml-rpc-api2cpp
+LDLIBS = -L$(BLDDIR)/src/cpp -lxmlrpc_cpp -lxmlrpc_server $(CLIENT_LDLIBS)
+
+PROGS :=
+
+ifeq ($(MUST_BUILD_CLIENT),yes)
+ PROGS += xml-rpc-api2cpp
+endif
+
+all: $(PROGS)
OBJECTS = \
xml-rpc-api2cpp.o \
@@ -30,17 +41,23 @@
$(LIBXMLRPC_CLIENT) \
$(LIBXMLRPC_SERVER) \
$(LIBXMLRPC) \
- $(LIBXML)
- $(LIBTOOL) --mode=link $(CXXLD) -o $@ $(LDFLAGS) $^
+ $(LIBXMLRPC_XML) \
+ $(LIBXMLRPC_UTIL)
+ $(CXXLD) -o $@ $(LDFLAGS) $(OBJECTS) $(LDLIBS)
%.o:%.cpp
- $(LIBTOOL) --mode=compile $(CXX) -c $(CXXFLAGS) $<
+ $(CXX) -c $(CXXFLAGS) $<
+
+# This common.mk dependency makes sure the symlinks get built before
+# this make file is used for anything.
+
+$(SRCDIR)/common.mk: srcdir blddir
include Makefile.depend
.PHONY: clean
clean: clean-common
- rm -f xml-rpc-api2cpp
+ rm -f $(PROGS)
.PHONY: distclean
distclean: clean distclean-common
Modified: freeswitch/trunk/libs/xmlrpc-c/tools/xml-rpc-api2cpp/XmlRpcClass.cpp
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/tools/xml-rpc-api2cpp/XmlRpcClass.cpp (original)
+++ freeswitch/trunk/libs/xmlrpc-c/tools/xml-rpc-api2cpp/XmlRpcClass.cpp Fri May 23 16:56:24 2008
@@ -11,68 +11,74 @@
#include "XmlRpcClass.hpp"
-//=========================================================================
-// XmlRpcClass
-//=========================================================================
-// This class stores information about a proxy class, and knows how to
-// generate code.
-
-XmlRpcClass::XmlRpcClass (string class_name)
- : mClassName(class_name)
-{
-}
+XmlRpcClass::XmlRpcClass(string const& className) :
+ mClassName(className) {}
+
+
+
+XmlRpcClass::XmlRpcClass(XmlRpcClass const& c) :
+ mClassName(c.mClassName),
+ mFunctions(c.mFunctions) {}
-XmlRpcClass::XmlRpcClass (const XmlRpcClass& c)
- : mClassName(c.mClassName),
- mFunctions(c.mFunctions)
-{
-}
-XmlRpcClass& XmlRpcClass::operator= (const XmlRpcClass& c)
-{
- if (this == &c)
- return *this;
- mClassName = c.mClassName;
- mFunctions = c.mFunctions;
+
+XmlRpcClass&
+XmlRpcClass::operator= (XmlRpcClass const& c) {
+
+ if (this != &c) {
+ this->mClassName = c.mClassName;
+ this->mFunctions = c.mFunctions;
+ }
return *this;
}
-void XmlRpcClass::addFunction (const XmlRpcFunction& function)
-{
+
+
+void
+XmlRpcClass::addFunction(XmlRpcFunction const& function) {
+
mFunctions.push_back(function);
}
-void XmlRpcClass::printDeclaration (ostream&)
-{
- cout << "class " << mClassName << " {" << endl;
- cout << " XmlRpcClient mClient;" << endl;
- cout << endl;
- cout << "public:" << endl;
- cout << " " << mClassName << " (const XmlRpcClient& client)" << endl;
- cout << " : mClient(client) {}" << endl;
- cout << " " << mClassName << " (const string& server_url)" << endl;
- cout << " : mClient(XmlRpcClient(server_url)) {}" << endl;
- cout << " " << mClassName << " (const " << mClassName << "& o)" << endl;
- cout << " : mClient(o.mClient) {}" << endl;
- cout << endl;
- cout << " " << mClassName << "& operator= (const "
- << mClassName << "& o) {" << endl;
- cout << " if (this != &o) mClient = o.mClient;" << endl;
- cout << " return *this;" << endl;
- cout << " }" << endl;
- vector<XmlRpcFunction>::iterator f;
+
+void
+XmlRpcClass::printDeclaration(ostream & out) const {
+
+ out << "class " << mClassName << " {" << endl;
+ out << " XmlRpcClient mClient;" << endl;
+ out << endl;
+ out << "public:" << endl;
+ out << " " << mClassName << " (const XmlRpcClient& client)" << endl;
+ out << " : mClient(client) {}" << endl;
+ out << " " << mClassName << " (const std::string& server_url)" << endl;
+ out << " : mClient(XmlRpcClient(server_url)) {}" << endl;
+ out << " " << mClassName << " (const " << mClassName << "& o)" << endl;
+ out << " : mClient(o.mClient) {}" << endl;
+ out << endl;
+ out << " " << mClassName << "& operator= (const "
+ << mClassName << "& o) {" << endl;
+ out << " if (this != &o) mClient = o.mClient;" << endl;
+ out << " return *this;" << endl;
+ out << " }" << endl;
+
+ vector<XmlRpcFunction>::const_iterator f;
for (f = mFunctions.begin(); f < mFunctions.end(); ++f) {
- f->printDeclarations(cout);
+ f->printDeclarations(out);
}
- cout << "};" << endl;
+ out << "};" << endl;
}
-void XmlRpcClass::printDefinition (ostream&)
-{
- vector<XmlRpcFunction>::iterator f;
+
+
+void
+XmlRpcClass::printDefinition(ostream & out) const {
+
+ vector<XmlRpcFunction>::const_iterator f;
+
for (f = mFunctions.begin(); f < mFunctions.end(); ++f) {
- f->printDefinitions(cout, mClassName);
+ f->printDefinitions(out, mClassName);
}
}
+
Modified: freeswitch/trunk/libs/xmlrpc-c/tools/xml-rpc-api2cpp/XmlRpcClass.hpp
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/tools/xml-rpc-api2cpp/XmlRpcClass.hpp (original)
+++ freeswitch/trunk/libs/xmlrpc-c/tools/xml-rpc-api2cpp/XmlRpcClass.hpp Fri May 23 16:56:24 2008
@@ -1,19 +1,22 @@
#include <vector>
class XmlRpcClass {
+ // An object of this class contains information about a proxy
+ // class, and knows how to generate code.
+
std::string mClassName;
std::vector<XmlRpcFunction> mFunctions;
public:
- XmlRpcClass (std::string class_name);
- XmlRpcClass (const XmlRpcClass&);
- XmlRpcClass& operator= (const XmlRpcClass&);
+ XmlRpcClass (std::string const& className);
+ XmlRpcClass(XmlRpcClass const&);
+ XmlRpcClass& operator= (XmlRpcClass const&);
std::string className () const { return mClassName; }
void addFunction (const XmlRpcFunction& function);
- void printDeclaration (ostream& out);
- void printDefinition (ostream& out);
+ void printDeclaration (ostream& out) const;
+ void printDefinition (ostream& out) const;
};
Modified: freeswitch/trunk/libs/xmlrpc-c/tools/xml-rpc-api2cpp/XmlRpcFunction.cpp
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/tools/xml-rpc-api2cpp/XmlRpcFunction.cpp (original)
+++ freeswitch/trunk/libs/xmlrpc-c/tools/xml-rpc-api2cpp/XmlRpcFunction.cpp Fri May 23 16:56:24 2008
@@ -1,137 +1,216 @@
#include <iostream>
+#include <sstream>
#include <stdexcept>
#include "xmlrpc-c/oldcppwrapper.hpp"
#include "DataType.hpp"
#include "XmlRpcFunction.hpp"
-using std::domain_error;
-using std::endl;
+using namespace std;
-//=========================================================================
-// class XmlRpcFunction
-//=========================================================================
-// Contains everything we know about a given server function, and knows
-// how to print local bindings.
-
-XmlRpcFunction::XmlRpcFunction(const string& function_name,
- const string& method_name,
- const string& help,
- XmlRpcValue synopsis)
- : mFunctionName(function_name), mMethodName(method_name),
- mHelp(help), mSynopsis(synopsis)
-{
-}
-
-XmlRpcFunction::XmlRpcFunction (const XmlRpcFunction& f)
- : mFunctionName(f.mFunctionName), mMethodName(f.mMethodName),
- mHelp(f.mHelp), mSynopsis(f.mSynopsis)
-{
-}
-
-XmlRpcFunction& XmlRpcFunction::operator= (const XmlRpcFunction& f) {
- if (this == &f)
- return *this;
- mFunctionName = f.mFunctionName;
- mMethodName = f.mMethodName;
- mHelp = f.mHelp;
- mSynopsis = f.mSynopsis;
+XmlRpcFunction::XmlRpcFunction(string const& functionName,
+ string const& methodName,
+ string const& help,
+ XmlRpcValue const signatureList) :
+ mFunctionName(functionName),
+ mMethodName(methodName),
+ mHelp(help),
+ mSynopsis(signatureList) {}
+
+
+
+XmlRpcFunction::XmlRpcFunction(XmlRpcFunction const& f) :
+ mFunctionName(f.mFunctionName),
+ mMethodName(f.mMethodName),
+ mHelp(f.mHelp),
+ mSynopsis(f.mSynopsis) {}
+
+
+
+XmlRpcFunction&
+XmlRpcFunction::operator= (XmlRpcFunction const& f) {
+
+ if (this != &f) {
+ this->mFunctionName = f.mFunctionName;
+ this->mMethodName = f.mMethodName;
+ this->mHelp = f.mHelp;
+ this->mSynopsis = f.mSynopsis;
+ }
return *this;
}
-void XmlRpcFunction::printDeclarations (ostream& out) {
- // XXX - Do a sloppy job of printing documentation.
- out << endl << " /* " << mHelp << " */" << endl;
- // Print each declaration.
- size_t end = mSynopsis.arraySize();
- for (size_t i = 0; i < end; i++)
- printDeclaration(out, i);
+void
+XmlRpcFunction::printDeclarations(ostream & out) const {
+
+ try {
+ // Print the method help as a comment
+
+ out << endl << " /* " << mHelp << " */" << endl;
+
+ size_t end;
+
+ try {
+ end = mSynopsis.arraySize();
+ } catch (XmlRpcFault const& fault) {
+ throw(logic_error("Failed to get size of signature array for "
+ "method " + this->mFunctionName + ". " +
+ fault.getFaultString()));
+ }
+ // Print the declarations for all the signatures of this
+ // XML-RPC method.
+
+ for (size_t i = 0; i < end; ++i)
+ printDeclaration(out, i);
+
+ } catch (exception const& e) {
+ throw(logic_error("Failed to generate declarations for method " +
+ this->mFunctionName + ". " + e.what()));
+ }
}
-void XmlRpcFunction::printDefinitions (ostream& out, const string& className) {
- size_t end = mSynopsis.arraySize();
- for (size_t i = 0; i < end; i++) {
- out << endl;
- printDefinition(out, className, i);
+
+
+void
+XmlRpcFunction::printDefinitions(ostream & out,
+ string const& className) const {
+
+ try {
+ size_t const end(mSynopsis.arraySize());
+
+ for (size_t i = 0; i < end; ++i) {
+ out << endl;
+ printDefinition(out, className, i);
+ }
+ } catch (XmlRpcFault const& fault) {
+ throw(logic_error("Failed to generate definitions for class " +
+ this->mFunctionName + ". " +
+ fault.getFaultString()));
}
}
-// Print the parameter declarations.
-void XmlRpcFunction::printParameters (ostream& out, size_t synopsis_index) {
- size_t end = parameterCount(synopsis_index);
- bool first = true;
- for (size_t i = 0; i < end; i++) {
- if (first)
- first = false;
- else
- out << ", ";
- const DataType& ptype (parameterType(synopsis_index, i));
- string basename = ptype.defaultParameterBaseName(i + 1);
- out << ptype.parameterFragment(basename);
+
+void
+XmlRpcFunction::printParameters(ostream & out,
+ size_t const synopsisIndex) const {
+/*----------------------------------------------------------------------------
+ Print the parameter declarations.
+-----------------------------------------------------------------------------*/
+ size_t const end(parameterCount(synopsisIndex));
+
+ bool first;
+
+ first = true;
+
+ for (size_t i = 0; i < end; ++i) {
+ if (!first)
+ out << ", ";
+
+ DataType const& ptype(parameterType(synopsisIndex, i));
+ string const basename(ptype.defaultParameterBaseName(i + 1));
+ out << ptype.parameterFragment(basename);
+
+ first = false;
}
}
-void XmlRpcFunction::printDeclaration (ostream& out, size_t synopsis_index) {
- const DataType& rtype (returnType(synopsis_index));
- out << " " << rtype.returnTypeFragment() << " "
- << mFunctionName << " (";
- printParameters(out, synopsis_index);
- out << ");" << endl;
+
+
+void
+XmlRpcFunction::printDeclaration(ostream & out,
+ size_t const synopsisIndex) const {
+
+ try {
+ DataType const& rtype(returnType(synopsisIndex));
+
+ out << " " << rtype.returnTypeFragment() << " "
+ << mFunctionName << " (";
+
+ printParameters(out, synopsisIndex);
+
+ out << ");" << endl;
+ } catch (XmlRpcFault const& fault) {
+ ostringstream msg;
+
+ msg << "Failed to generate header for signature "
+ << synopsisIndex
+ << " . "
+ << fault.getFaultString();
+
+ throw(logic_error(msg.str()));
+ }
}
-void XmlRpcFunction::printDefinition (ostream& out,
- const string& className,
- size_t synopsis_index)
-{
- const DataType& rtype (returnType(synopsis_index));
+
+
+void
+XmlRpcFunction::printDefinition(ostream & out,
+ string const& className,
+ size_t const synopsisIndex) const {
+
+ DataType const& rtype(returnType(synopsisIndex));
+
out << rtype.returnTypeFragment() << " "
- << className << "::" << mFunctionName << " (";
- printParameters(out, synopsis_index);
+ << className << "::" << mFunctionName << " (";
+
+ printParameters(out, synopsisIndex);
+
out << ") {" << endl;
- out << " XmlRpcValue params = XmlRpcValue::makeArray();" << endl;
+ out << " XmlRpcValue params(XmlRpcValue::makeArray());" << endl;
/* Emit code to convert the parameters into an array of XML-RPC objects. */
- size_t end = parameterCount(synopsis_index);
- for (size_t i = 0; i < end; i++) {
- const DataType& ptype (parameterType(synopsis_index, i));
- string basename = ptype.defaultParameterBaseName(i + 1);
- out << " params.arrayAppendItem("
- << ptype.inputConversionFragment(basename) << ");" << endl;
+ size_t const end(parameterCount(synopsisIndex));
+ for (size_t i = 0; i < end; ++i) {
+ DataType const& ptype(parameterType(synopsisIndex, i));
+ string const basename(ptype.defaultParameterBaseName(i + 1));
+ out << " params.arrayAppendItem("
+ << ptype.inputConversionFragment(basename) << ");" << endl;
}
/* Emit the function call.*/
- out << " XmlRpcValue result = this->mClient.call(\""
- << mMethodName << "\", params);" << endl;
+ out << " XmlRpcValue result(this->mClient.call(\""
+ << mMethodName << "\", params));" << endl;
/* Emit the return statement. */
out << " return " << rtype.outputConversionFragment("result")
- << ";" << endl;
+ << ";" << endl;
out << "}" << endl;
}
-const DataType& XmlRpcFunction::returnType (size_t synopsis_index) {
- XmlRpcValue func_synop = mSynopsis.arrayGetItem(synopsis_index);
- return findDataType(func_synop.arrayGetItem(0).getString());
+
+
+const DataType&
+XmlRpcFunction::returnType(size_t const synopsisIndex) const {
+
+ XmlRpcValue const funcSynop(mSynopsis.arrayGetItem(synopsisIndex));
+
+ return findDataType(funcSynop.arrayGetItem(0).getString());
}
-size_t XmlRpcFunction::parameterCount (size_t synopsis_index) {
- XmlRpcValue func_synop = mSynopsis.arrayGetItem(synopsis_index);
- size_t size = func_synop.arraySize();
+
+
+size_t
+XmlRpcFunction::parameterCount(size_t const synopsisIndex) const {
+
+ XmlRpcValue const funcSynop(mSynopsis.arrayGetItem(synopsisIndex));
+ size_t const size(funcSynop.arraySize());
+
if (size < 1)
- throw domain_error("Synopsis contained no items");
+ throw domain_error("Synopsis contained no items");
return size - 1;
}
-const DataType& XmlRpcFunction::parameterType (size_t synopsis_index,
- size_t parameter_index)
-{
- XmlRpcValue func_synop = mSynopsis.arrayGetItem(synopsis_index);
- XmlRpcValue param = func_synop.arrayGetItem(parameter_index + 1);
- return findDataType(param.getString());
-}
+DataType const&
+XmlRpcFunction::parameterType(size_t const synopsisIndex,
+ size_t const parameterIndex) const {
+
+ XmlRpcValue const funcSynop(mSynopsis.arrayGetItem(synopsisIndex));
+ XmlRpcValue const param(funcSynop.arrayGetItem(parameterIndex + 1));
+
+ return findDataType(param.getString());
+}
Modified: freeswitch/trunk/libs/xmlrpc-c/tools/xml-rpc-api2cpp/XmlRpcFunction.hpp
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/tools/xml-rpc-api2cpp/XmlRpcFunction.hpp (original)
+++ freeswitch/trunk/libs/xmlrpc-c/tools/xml-rpc-api2cpp/XmlRpcFunction.hpp Fri May 23 16:56:24 2008
@@ -1,4 +1,3 @@
-
#include <string>
#include <iostream>
@@ -6,6 +5,9 @@
using std::ostream;
class XmlRpcFunction {
+ // An object of this class contains everything we know about a
+ // given XML-RPC method, and knows how to print local bindings.
+
string mFunctionName;
string mMethodName;
string mHelp;
@@ -13,25 +15,25 @@
public:
XmlRpcFunction(const string& function_name,
- const string& method_name,
- const string& help,
- XmlRpcValue synopsis);
+ const string& method_name,
+ const string& help,
+ XmlRpcValue synopsis);
XmlRpcFunction (const XmlRpcFunction&);
XmlRpcFunction& operator= (const XmlRpcFunction&);
- void printDeclarations (ostream& out);
- void printDefinitions (ostream& out, const string& className);
+ void printDeclarations (ostream& out) const;
+ void printDefinitions (ostream& out, const string& className) const;
private:
- void printParameters (ostream& out, size_t synopsis_index);
- void printDeclaration (ostream& out, size_t synopsis_index);
+ void printParameters (ostream& out, size_t synopsis_index) const;
+ void printDeclaration (ostream& out, size_t synopsis_index) const;
void printDefinition (ostream& out,
- const string& className,
- size_t synopsis_index);
+ const string& className,
+ size_t synopsis_index) const;
- const DataType& returnType (size_t synopsis_index);
- size_t parameterCount (size_t synopsis_index);
+ const DataType& returnType (size_t synopsis_index) const;
+ size_t parameterCount (size_t synopsis_index) const;
const DataType& parameterType (size_t synopsis_index,
- size_t parameter_index);
+ size_t parameter_index) const;
};
Modified: freeswitch/trunk/libs/xmlrpc-c/tools/xml-rpc-api2cpp/xml-rpc-api2cpp.cpp
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/tools/xml-rpc-api2cpp/xml-rpc-api2cpp.cpp (original)
+++ freeswitch/trunk/libs/xmlrpc-c/tools/xml-rpc-api2cpp/xml-rpc-api2cpp.cpp Fri May 23 16:56:24 2008
@@ -14,144 +14,199 @@
#define VERSION "0.1"
-//=========================================================================
-// function get_class_info
-//=========================================================================
-// Connect to a remote server and extract the information we'll need to
-// build a proxy class.
-
-XmlRpcClass get_class_info (string server_url,
- string class_prefix,
- string class_name)
-{
- // Create a place to store our data.
- XmlRpcClass info(class_name);
-
- // Create a proxy class.
- SystemProxy system(server_url);
-
- // Fetch the full list of methods, and process the ones we want.
- XmlRpcValue methods = system.listMethods();
- size_t end = methods.arraySize();
- for (size_t i = 0; i < end; i++) {
-
- // Break the method name into two pieces.
- string method_prefix;
- string function_name;
- string method_name = methods.arrayGetItem(i).getString();
- size_t last_dot = method_name.rfind('.');
- if (last_dot == string::npos) {
- function_name = method_name;
- } else {
- method_prefix = string(method_name, 0, last_dot);
- function_name = string(method_name, last_dot + 1);
- }
-
- // Decide whether we care about this function.
- if (method_prefix == class_prefix) {
-
- // Fetch some information about the function.
- string help = system.methodHelp(method_name);
- XmlRpcValue signature = system.methodSignature(method_name);
-
- // Add this function to our class information.
- XmlRpcFunction func(function_name, method_name, help, signature);
- info.addFunction(func);
- }
+/*----------------------------------------------------------------------------
+ Command line
+-----------------------------------------------------------------------------*/
+
+class cmdlineInfo {
+public:
+ string serverUrl;
+ string methodPrefix;
+ string localClass;
+
+ cmdlineInfo(int const argc,
+ const char ** const argv);
+
+private:
+ cmdlineInfo();
+};
+
+
+
+cmdlineInfo::cmdlineInfo(int const argc,
+ const char ** const argv) {
+
+ if (argc-1 != 3) {
+ cerr << argv[0] << ": Usage:" << endl
+ << " xml-rpc-api2cpp <server_url> <method_prefix> <local_class>"
+ << endl << endl
+ << "Sample arguments:" << endl
+ << " server_url = http://localhost/RPC2" << endl
+ << " method_prefix = system" << endl
+ << " local_class = SystemProxy" << endl;
+ exit(1);
}
+ this->serverUrl = string(argv[1]);
+ this->methodPrefix = string(argv[2]);
+ this->localClass = string(argv[3]);
+}
+
+
+static XmlRpcClass
+getClassInfo(string const& serverUrl,
+ string const& classPrefix,
+ string const& className) {
+/*----------------------------------------------------------------------------
+ Connect to a remote server and extract the information we'll need to
+ build a proxy class.
+-----------------------------------------------------------------------------*/
+ XmlRpcClass info(className);
+
+ SystemProxy system(serverUrl);
+
+ XmlRpcValue const methods(system.listMethods());
+
+ size_t const end = methods.arraySize();
+
+ for (size_t i = 0; i < end; ++i) {
+
+ // Break the method name into two pieces.
+ string const methodName(methods.arrayGetItem(i).getString());
+ size_t const lastDot(methodName.rfind('.'));
+
+ string methodPrefix;
+ string functionName;
+
+ if (lastDot == string::npos) {
+ methodPrefix = "";
+ functionName = methodName;
+ } else {
+ methodPrefix = string(methodName, 0, lastDot);
+ functionName = string(methodName, lastDot + 1);
+ }
+
+ if (methodPrefix == classPrefix) {
+ // It's a method User cares about
+
+ string const help(system.methodHelp(methodName));
+ XmlRpcValue const signatureList(
+ system.methodSignature(methodName));
+
+ if (signatureList.getType() != XMLRPC_TYPE_ARRAY) {
+ // It must be the string "undef", meaning the server
+ // won't tell us any signatures.
+ cerr << "Skipping method " << methodName << " "
+ << "because server does not report any signatures "
+ << "for it (via system.methodSignature method)"
+ << endl;
+ } else {
+ // Add this function to our class information.
+ XmlRpcFunction const method(functionName,
+ methodName,
+ help,
+ signatureList);
+ info.addFunction(method);
+ }
+ }
+ }
return info;
}
-//=========================================================================
-// function print_header
-//=========================================================================
-// Print a complete header for the specified class.
-
-void print_header (ostream& out, XmlRpcClass& class_info) {
- string class_name = class_info.className();
- out << "// " << class_name << ".h - xmlrpc-c C++ proxy class" << endl;
- out << "// Auto-generated by xml-rpc-api2cpp." << endl;
- out << endl;
-
- string header_symbol = "_" + class_name + "_H_";
- out << "#ifndef " << header_symbol << endl;
- out << "#define " << header_symbol << " 1" << endl;
- out << endl;
- out << "#include <XmlRpcCpp.h>" << endl;
- out << endl;
- class_info.printDeclaration(cout);
+static void
+printHeader(ostream & out,
+ XmlRpcClass const& classInfo) {
+/*----------------------------------------------------------------------------
+ Print a complete header for the specified class.
+-----------------------------------------------------------------------------*/
+ string const className(classInfo.className());
- out << endl;
- out << "#endif /* " << header_symbol << " */" << endl;
+ try {
+ out << "// " << className << ".h - xmlrpc-c C++ proxy class" << endl;
+ out << "// Auto-generated by xml-rpc-api2cpp." << endl;
+ out << endl;
+
+ string const headerSymbol("_" + className + "_H_");
+
+ out << "#ifndef " << headerSymbol << endl;
+ out << "#define " << headerSymbol << " 1" << endl;
+ out << endl;
+ out << "#include <xmlrpc-c/oldcppwrapper.hpp>" << endl;
+ out << endl;
+
+ classInfo.printDeclaration(cout);
+
+ out << endl;
+ out << "#endif /* " << headerSymbol << " */" << endl;
+ } catch (exception const& e) {
+ throw(logic_error("Failed to generate header for class " +
+ className + ". " + e.what()));
+ }
}
-//=========================================================================
-// function print_cc_file
-//=========================================================================
-// Print a complete header for the specified class.
-
-void print_cc_file (ostream& out, XmlRpcClass& class_info) {
- string class_name = class_info.className();
- out << "// " << class_name << ".cc - xmlrpc-c C++ proxy class" << endl;
- out << "// Auto-generated by xml-rpc-api2cpp." << endl;
- out << endl;
- out << "#include <XmlRpcCpp.h>" << endl;
- out << "#include \"" << class_name << ".h\"" << endl;
+static void
+printCppFile(ostream & out,
+ XmlRpcClass const& classInfo) {
+/*----------------------------------------------------------------------------
+ Print a complete definition for the specified class.
+-----------------------------------------------------------------------------*/
+ string const className(classInfo.className());
- class_info.printDefinition(cout);
+ try {
+ out << "// " << className << ".cc - xmlrpc-c C++ proxy class" << endl;
+ out << "// Auto-generated by xml-rpc-api2cpp." << endl;
+ out << endl;
+
+ out << "#include <xmlrpc-c/oldcppwrapper.hpp>" << endl;
+ out << "#include \"" << className << ".h\"" << endl;
+
+ classInfo.printDefinition(cout);
+ } catch (XmlRpcFault const& fault) {
+ throw(logic_error("Failed to generate definition for class " +
+ className + ". " + fault.getFaultString()));
+ }
}
-//=========================================================================
-// function main
-//=========================================================================
-// For now, just a test harness.
-
-int main (int argc, char **argv) {
-
- /* Parse our command-line arguments. */
- if (argc != 4) {
- cerr << argv[0] << ": Usage:" << endl
- << " xml-rpc-api2cpp <server_url> <method_prefix> <local_class>"
- << endl << endl
- << "Sample arguments:" << endl
- << " server_url = http://localhost/RPC2" << endl
- << " method_prefix = system" << endl
- << " local_class = SystemProxy" << endl;
- exit(1);
- }
- string server_url = argv[1];
- string method_prefix = argv[2];
- string local_class = argv[3];
- int status = 0;
+int
+main(int const argc,
+ const char ** const argv) {
+
+ string const progName(argv[0]);
+
+ cmdlineInfo const cmdline(argc, argv);
+
+ int retval;
+
XmlRpcClient::Initialize(NAME, VERSION);
try {
- XmlRpcClass system = get_class_info(server_url,
- method_prefix,
- local_class);
- print_header(cout, system);
- cout << endl;
- print_cc_file(cout, system);
+ XmlRpcClass system = getClassInfo(cmdline.serverUrl,
+ cmdline.methodPrefix,
+ cmdline.localClass);
+ printHeader(cout, system);
+ cout << endl;
+ printCppFile(cout, system);
+ retval = 0;
} catch (XmlRpcFault& fault) {
- cerr << argv[0] << ": XML-RPC fault #" << fault.getFaultCode()
- << ": " << fault.getFaultString() << endl;
- status = 1;
+ cerr << progName << ": XML-RPC fault #" << fault.getFaultCode()
+ << ": " << fault.getFaultString() << endl;
+ retval = 1;
} catch (logic_error& err) {
- cerr << argv[0] << ": " << err.what() << endl;
- status = 1;
+ cerr << progName << ": " << err.what() << endl;
+ retval = 1;
} catch (...) {
- cerr << argv[0] << ": Unknown exception" << endl;
- status = 1;
+ cerr << progName << ": Unknown exception" << endl;
+ retval = 1;
}
XmlRpcClient::Terminate();
- return status;
+ return retval;
}
+
Modified: freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc/Makefile
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc/Makefile (original)
+++ freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc/Makefile Fri May 23 16:56:24 2008
@@ -1,35 +1,59 @@
-ifeq ($(SRCDIR)x,x)
-SRCDIR = $(CURDIR)/../..
-BUILDDIR = $(SRCDIR)
+ifeq ($(SRCDIR),)
+ updir = $(shell echo $(dir $(1)) | sed 's/.$$//')
+ TOOLSDIR := $(call updir,$(CURDIR))
+ SRCDIR := $(call updir,$(TOOLSDIR))
+ BLDDIR := $(SRCDIR)
endif
+SUBDIR := tools/xmlrpc
-all: xmlrpc
+default: all
-include $(BUILDDIR)/Makefile.config
+include $(BLDDIR)/config.mk
PROGRAMS_TO_INSTALL = xmlrpc
-include ../Makefile.common
+include $(SRCDIR)/tools/common.mk
-INCLUDES = -I$(SRCDIR) -I$(SRCDIR)/include -I$(SRCDIR)/lib/util/include
+INCLUDES = \
+ -I../lib/include \
+ -Iblddir \
+ -Iblddir/include \
+ -Isrcdir/include \
+ -Isrcdir/lib/util/include
CFLAGS = $(CFLAGS_COMMON) $(INCLUDES) $(CFLAGS_PERSONAL) $(CADD)
-LDFLAGS = $(CLIENT_LDFLAGS) $(LADD)
+LDFLAGS = $(LADD)
+
+all: xmlrpc
+
+UTIL_OBJS = \
+ casprintf.o \
+ cmdline_parser.o \
+ getoptx.o \
+ stripcaseeq.o \
+ string_parser.o \
-UTIL_OBJS = cmdline_parser.o getoptx.o
UTILS = $(UTIL_OBJS:%=$(UTIL_DIR)/%)
-xmlrpc:%:%.o $(LIBXMLRPC_CLIENT) $(LIBXMLRPC) $(LIBXML) $(UTILS)
- $(LIBTOOL) --mode=link $(CCLD) -o $@ $(LDFLAGS) $^
+DUMPVALUE = srcdir/tools/lib/dumpvalue.o
+
+# Can we just use $(LIBS) in the link?
+
+LIBS = $(LIBXMLRPC_CLIENT) $(LIBXMLRPC) $(LIBXMLRPC_XML) $(LIBXMLRPC_UTIL)
+
+XMLRPC_OBJS = xmlrpc.o $(DUMPVALUE)
+
+xmlrpc: $(XMLRPC_OBJS) $(LIBS) $(UTILS)
+ $(CCLD) -o $@ $(LDFLAGS) $(XMLRPC_OBJS) $(UTILS) $(CLIENT_LDLIBS)
-%.o:%.c
- $(LIBTOOL) --mode=compile $(CC) -c $(CFLAGS) $<
+%.o:%.c $(BLDDIR)/include/xmlrpc-c/config.h
+ $(CC) -c $(CFLAGS) $<
-*.c: config.h
+# This common.mk dependency makes sure the symlinks get built before
+# this make file is used for anything.
-config.h:
- $(LN_S) $(BUILDDIR)/xmlrpc_config.h $@
+$(SRCDIR)/tools/common.mk: srcdir blddir
include Makefile.depend
@@ -38,7 +62,7 @@
.PHONY: clean
clean: clean-common
- rm -f xmlrpc config.h
+ rm -f xmlrpc
.PHONY: distclean
distclean: clean distclean-common
Modified: freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc/xmlrpc.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc/xmlrpc.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc/xmlrpc.c Fri May 23 16:56:24 2008
@@ -40,11 +40,18 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <errno.h>
+#include <assert.h>
-#include "config.h" /* information about this build environment */
-#include "casprintf.h"
+#include "xmlrpc_config.h" /* information about this build environment */
+#include "bool.h"
+#include "int.h"
#include "mallocvar.h"
+#include "girstring.h"
+#include "casprintf.h"
+#include "string_parser.h"
#include "cmdline_parser.h"
+#include "dumpvalue.h"
#include "xmlrpc-c/base.h"
#include "xmlrpc-c/client.h"
@@ -78,8 +85,7 @@
static void
die_if_fault_occurred (xmlrpc_env * const envP) {
if (envP->fault_occurred) {
- fprintf(stderr, "Error: %s (%d)\n",
- envP->fault_string, envP->fault_code);
+ fprintf(stderr, "Failed. %s\n", envP->fault_string);
exit(1);
}
}
@@ -191,7 +197,7 @@
cmd_getOptionValueString(cp, "curluseragent");
if ((!cmdlineP->transport ||
- strcmp(cmdlineP->transport, "curl") != 0)
+ !streq(cmdlineP->transport, "curl"))
&&
(cmdlineP->curlinterface ||
cmdlineP->curlnoverifypeer ||
@@ -235,11 +241,10 @@
computeUrl(const char * const urlArg,
const char ** const urlP) {
- if (strstr(urlArg, "://") != 0) {
- *urlP = strdup(urlArg);
- } else {
+ if (strstr(urlArg, "://") != 0)
+ casprintf(urlP, "%s", urlArg);
+ else
casprintf(urlP, "http://%s/RPC2", urlArg);
- }
}
@@ -249,7 +254,49 @@
const char * const valueString,
xmlrpc_value ** const paramPP) {
- *paramPP = xmlrpc_build_value(envP, "s", valueString);
+ *paramPP = xmlrpc_string_new(envP, valueString);
+}
+
+
+
+static void
+buildBytestring(xmlrpc_env * const envP,
+ const char * const valueString,
+ xmlrpc_value ** const paramPP) {
+
+ size_t const valueStringSize = strlen(valueString);
+
+ if (valueStringSize / 2 * 2 != valueStringSize)
+ xmlrpc_faultf(envP, "Hexadecimal text is not an even "
+ "number of characters (it is %u characters)",
+ strlen(valueString));
+ else {
+ size_t const byteStringSize = strlen(valueString)/2;
+
+ unsigned char byteString[byteStringSize];
+ size_t bsCursor;
+ size_t strCursor;
+
+ strCursor = 0;
+ bsCursor = 0;
+
+ while (strCursor < valueStringSize && !envP->fault_occurred) {
+ int rc;
+
+ assert(bsCursor < byteStringSize);
+
+ rc = sscanf(&valueString[strCursor], "%2hhx",
+ &byteString[bsCursor++]);
+
+ if (rc != 1)
+ xmlrpc_faultf(envP, "Invalid hex data '%s'",
+ &valueString[strCursor]);
+ else
+ strCursor += 2;
+ }
+ if (!envP->fault_occurred)
+ *paramPP = xmlrpc_base64_new(envP, byteStringSize, byteString);
+ }
}
@@ -262,19 +309,19 @@
if (strlen(valueString) < 1)
setError(envP, "Integer argument has nothing after the 'i/'");
else {
- long value;
- char * tailptr;
-
- value = strtol(valueString, &tailptr, 10);
+ int value;
+ const char * error;
- if (*tailptr != '\0')
- setError(envP,
- "Integer argument has non-digit crap in it: '%s'",
- tailptr);
- else
- *paramPP = xmlrpc_build_value(envP, "i", value);
+ interpretInt(valueString, &value, &error);
+
+ if (error) {
+ setError(envP, "'%s' is not a valid 32-bit integer. %s",
+ valueString, error);
+ strfree(error);
+ } else
+ *paramPP = xmlrpc_int_new(envP, value);
}
-}
+}
@@ -283,12 +330,10 @@
const char * const valueString,
xmlrpc_value ** const paramPP) {
- if (strcmp(valueString, "t") == 0 ||
- strcmp(valueString, "true") == 0)
- *paramPP = xmlrpc_build_value(envP, "b", 1);
- else if (strcmp(valueString, "f") == 0 ||
- strcmp(valueString, "false") == 0)
- *paramPP = xmlrpc_build_value(envP, "b", 0);
+ if (streq(valueString, "t") || streq(valueString, "true"))
+ *paramPP = xmlrpc_bool_new(envP, true);
+ else if (streq(valueString, "f") == 0 || streq(valueString, "false"))
+ *paramPP = xmlrpc_bool_new(envP, false);
else
setError(envP, "Boolean argument has unrecognized value '%s'. "
"recognized values are 't', 'f', 'true', and 'false'.",
@@ -298,6 +343,30 @@
static void
+buildDouble(xmlrpc_env * const envP,
+ const char * const valueString,
+ xmlrpc_value ** const paramPP) {
+
+ if (strlen(valueString) < 1)
+ setError(envP, "\"Double\" argument has nothing after the 'd/'");
+ else {
+ double value;
+ char * tailptr;
+
+ value = strtod(valueString, &tailptr);
+
+ if (*tailptr != '\0')
+ setError(envP,
+ "\"Double\" argument has non-decimal crap in it: '%s'",
+ tailptr);
+ else
+ *paramPP = xmlrpc_double_new(envP, value);
+ }
+}
+
+
+
+static void
buildNil(xmlrpc_env * const envP,
const char * const valueString,
xmlrpc_value ** const paramPP) {
@@ -305,7 +374,31 @@
if (strlen(valueString) > 0)
setError(envP, "Nil argument has something after the 'n/'");
else {
- *paramPP = xmlrpc_build_value(envP, "n");
+ *paramPP = xmlrpc_nil_new(envP);
+ }
+}
+
+
+
+static void
+buildI8(xmlrpc_env * const envP,
+ const char * const valueString,
+ xmlrpc_value ** const paramPP) {
+
+ if (strlen(valueString) < 1)
+ setError(envP, "Integer argument has nothing after the 'I/'");
+ else {
+ int64_t value;
+ const char * error;
+
+ interpretLl(valueString, &value, &error);
+
+ if (error) {
+ setError(envP, "'%s' is not a valid 64-bit integer. %s",
+ valueString, error);
+ strfree(error);
+ } else
+ *paramPP = xmlrpc_i8_new(envP, value);
}
}
@@ -318,8 +411,14 @@
if (strncmp(paramArg, "s/", 2) == 0)
buildString(envP, ¶mArg[2], paramPP);
+ else if (strncmp(paramArg, "h/", 2) == 0)
+ buildBytestring(envP, ¶mArg[2], paramPP);
else if (strncmp(paramArg, "i/", 2) == 0)
buildInt(envP, ¶mArg[2], paramPP);
+ else if (strncmp(paramArg, "I/", 2) == 0)
+ buildI8(envP, ¶mArg[2], paramPP);
+ else if (strncmp(paramArg, "d/", 2) == 0)
+ buildDouble(envP, ¶mArg[2], paramPP);
else if (strncmp(paramArg, "b/", 2) == 0)
buildBool(envP, ¶mArg[2], paramPP);
else if (strncmp(paramArg, "n/", 2) == 0)
@@ -344,7 +443,7 @@
xmlrpc_value * paramArrayP;
- paramArrayP = xmlrpc_build_value(envP, "()");
+ paramArrayP = xmlrpc_array_new(envP);
for (i = 0; i < paramCount && !envP->fault_occurred; ++i) {
xmlrpc_value * paramP;
@@ -362,371 +461,37 @@
-/* Forward declaration for recursion */
-static void
-dumpValue(const char * const prefix,
- xmlrpc_value * const valueP);
-
-
-
-static void
-dumpInt(const char * const prefix,
- xmlrpc_value * const valueP) {
-
- xmlrpc_env env;
- xmlrpc_int value;
-
- xmlrpc_env_init(&env);
-
- xmlrpc_parse_value(&env, valueP, "i", &value);
-
- if (env.fault_occurred)
- printf("Unable to parse integer in result. %s\n",
- env.fault_string);
- else
- printf("%sInteger: %d\n", prefix, value);
-
- xmlrpc_env_clean(&env);
-}
-
-
-
-static void
-dumpBool(const char * const prefix,
- xmlrpc_value * const valueP) {
-
- xmlrpc_env env;
- xmlrpc_bool value;
-
- xmlrpc_env_init(&env);
-
- xmlrpc_parse_value(&env, valueP, "b", &value);
-
- if (env.fault_occurred)
- printf("Unable to parse boolean in result. %s\n",
- env.fault_string);
- else
- printf("%sBoolean: %s\n", prefix, value ? "TRUE" : "FALSE");
-
- xmlrpc_env_clean(&env);
-}
-
-
-
-
-static void
-dumpDouble(const char * const prefix,
- xmlrpc_value * const valueP) {
-
- xmlrpc_env env;
- xmlrpc_double value;
-
- xmlrpc_env_init(&env);
-
- xmlrpc_parse_value(&env, valueP, "d", &value);
-
- if (env.fault_occurred)
- printf("Unable to parse floating point number in result. %s\n",
- env.fault_string);
- else
- printf("%sFloating Point: %f\n", prefix, value);
-
- xmlrpc_env_clean(&env);
-}
-
-
-
-static void
-dumpDatetime(const char * const prefix,
- xmlrpc_value * const valueP) {
-
- printf("%sDon't know how to print datetime value result %p.\n",
- prefix, valueP);
-}
-
-
-
-static void
-dumpString(const char * const prefix,
- xmlrpc_value * const valueP) {
-
- xmlrpc_env env;
- const char * value;
-
- xmlrpc_env_init(&env);
-
- xmlrpc_parse_value(&env, valueP, "s", &value);
-
- if (env.fault_occurred)
- printf("Unable to parse string in result. %s\n",
- env.fault_string);
- else
- printf("%sString: '%s'\n", prefix, value);
-
- xmlrpc_env_clean(&env);
-}
-
-
-
static void
-dumpBase64(const char * const prefix,
- xmlrpc_value * const valueP) {
-
- xmlrpc_env env;
- const unsigned char * value;
- size_t length;
-
- xmlrpc_env_init(&env);
+dumpResult(xmlrpc_value * const resultP) {
- xmlrpc_parse_value(&env, valueP, "6", &value, &length);
-
- if (env.fault_occurred)
- printf("Unable to parse base64 bit strnig in result. %s\n",
- env.fault_string);
- else {
- unsigned int i;
+ printf("Result:\n\n");
- printf("%sBit string: ", prefix);
- for (i = 0; i < length; ++i)
- printf("%02x", value[i]);
- }
- xmlrpc_env_clean(&env);
+ dumpValue("", resultP);
}
static void
-dumpArray(const char * const prefix,
- xmlrpc_value * const arrayP) {
-
+callWithClient(xmlrpc_env * const envP,
+ const xmlrpc_server_info * const serverInfoP,
+ const char * const methodName,
+ xmlrpc_value * const paramArrayP,
+ xmlrpc_value ** const resultPP) {
+
xmlrpc_env env;
- unsigned int arraySize;
-
xmlrpc_env_init(&env);
-
- XMLRPC_ASSERT_ARRAY_OK(arrayP);
-
- arraySize = xmlrpc_array_size(&env, arrayP);
- if (env.fault_occurred)
- printf("Unable to get array size. %s\n", env.fault_string);
- else {
- int const spaceCount = strlen(prefix);
-
- unsigned int i;
- const char * blankPrefix;
-
- printf("%sArray of %u items:\n", prefix, arraySize);
-
- casprintf(&blankPrefix, "%*s", spaceCount, "");
-
- for (i = 0; i < arraySize; ++i) {
- xmlrpc_value * valueP;
-
- xmlrpc_array_read_item(&env, arrayP, i, &valueP);
-
- if (env.fault_occurred)
- printf("Unable to get array item %u\n", i);
- else {
- const char * prefix2;
-
- casprintf(&prefix2, "%s Index %2u ", blankPrefix, i);
- dumpValue(prefix2, valueP);
- strfree(prefix2);
-
- xmlrpc_DECREF(valueP);
- }
- }
- strfree(blankPrefix);
- }
- xmlrpc_env_clean(&env);
-}
-
-
-
-static void
-dumpStructMember(const char * const prefix,
- xmlrpc_value * const structP,
- unsigned int const index) {
-
- xmlrpc_env env;
-
- xmlrpc_value * keyP;
- xmlrpc_value * valueP;
+ *resultPP = xmlrpc_client_call_server_params(
+ &env, serverInfoP, methodName, paramArrayP);
- xmlrpc_env_init(&env);
-
- xmlrpc_struct_read_member(&env, structP, index, &keyP, &valueP);
-
if (env.fault_occurred)
- printf("Unable to get struct member %u\n", index);
- else {
- int const blankCount = strlen(prefix);
- const char * prefix2;
- const char * blankPrefix;
-
- casprintf(&prefix2, "%s Key: ", prefix);
- dumpValue(prefix2, keyP);
- strfree(prefix2);
-
- casprintf(&blankPrefix, "%*s", blankCount, "");
-
- casprintf(&prefix2, "%s Value: ", blankPrefix);
- dumpValue(prefix2, valueP);
- strfree(prefix2);
-
- strfree(blankPrefix);
-
- xmlrpc_DECREF(keyP);
- xmlrpc_DECREF(valueP);
- }
+ xmlrpc_faultf(envP, "Call failed. %s. (XML-RPC fault code %d)",
+ env.fault_string, env.fault_code);
xmlrpc_env_clean(&env);
}
static void
-dumpStruct(const char * const prefix,
- xmlrpc_value * const structP) {
-
- xmlrpc_env env;
- unsigned int structSize;
-
- xmlrpc_env_init(&env);
-
- structSize = xmlrpc_struct_size(&env, structP);
- if (env.fault_occurred)
- printf("Unable to get struct size. %s\n", env.fault_string);
- else {
- unsigned int i;
-
- printf("%sStruct of %u members:\n", prefix, structSize);
-
- for (i = 0; i < structSize; ++i) {
- const char * prefix1;
-
- if (i == 0)
- prefix1 = strdup(prefix);
- else {
- int const blankCount = strlen(prefix);
- casprintf(&prefix1, "%*s", blankCount, "");
- }
- dumpStructMember(prefix1, structP, i);
-
- strfree(prefix1);
- }
- }
- xmlrpc_env_clean(&env);
-}
-
-
-
-static void
-dumpCPtr(const char * const prefix,
- xmlrpc_value * const valueP) {
-
- xmlrpc_env env;
- const char * value;
-
- xmlrpc_env_init(&env);
-
- xmlrpc_parse_value(&env, valueP, "p", &value);
-
- if (env.fault_occurred)
- printf("Unable to parse C pointer in result. %s\n",
- env.fault_string);
- else
- printf("%sC pointer: '%p'\n", prefix, value);
-
- xmlrpc_env_clean(&env);
-}
-
-
-
-static void
-dumpNil(const char * const prefix,
- xmlrpc_value * const valueP) {
-
- xmlrpc_env env;
-
- xmlrpc_env_init(&env);
-
- xmlrpc_parse_value(&env, valueP, "n");
-
- if (env.fault_occurred)
- printf("Unable to parse nil value in result. %s\n",
- env.fault_string);
- else
- printf("%sNil\n", prefix);
-
- xmlrpc_env_clean(&env);
-}
-
-
-
-static void
-dumpUnknown(const char * const prefix,
- xmlrpc_value * const valueP) {
-
- printf("%sDon't recognize the type of the result: %u.\n",
- prefix, xmlrpc_value_type(valueP));
- printf("%sCan't print it.\n", prefix);
-}
-
-
-
-static void
-dumpValue(const char * const prefix,
- xmlrpc_value * const valueP) {
-
- switch (xmlrpc_value_type(valueP)) {
- case XMLRPC_TYPE_INT:
- dumpInt(prefix, valueP);
- break;
- case XMLRPC_TYPE_BOOL:
- dumpBool(prefix, valueP);
- break;
- case XMLRPC_TYPE_DOUBLE:
- dumpDouble(prefix, valueP);
- break;
- case XMLRPC_TYPE_DATETIME:
- dumpDatetime(prefix, valueP);
- break;
- case XMLRPC_TYPE_STRING:
- dumpString(prefix, valueP);
- break;
- case XMLRPC_TYPE_BASE64:
- dumpBase64(prefix, valueP);
- break;
- case XMLRPC_TYPE_ARRAY:
- dumpArray(prefix, valueP);
- break;
- case XMLRPC_TYPE_STRUCT:
- dumpStruct(prefix, valueP);
- break;
- case XMLRPC_TYPE_C_PTR:
- dumpCPtr(prefix, valueP);
- break;
- case XMLRPC_TYPE_NIL:
- dumpNil(prefix, valueP);
- break;
- default:
- dumpUnknown(prefix, valueP);
- }
-}
-
-
-
-static void
-dumpResult(xmlrpc_value * const resultP) {
-
- printf("Result:\n\n");
-
- dumpValue("", resultP);
-}
-
-
-
-static void
doCall(xmlrpc_env * const envP,
const char * const transport,
const char * const curlinterface,
@@ -744,7 +509,7 @@
clientparms.transport = transport;
- if (transport && strcmp(transport, "curl") == 0) {
+ if (transport && streq(transport, "curl")) {
struct xmlrpc_curl_xportparms * curlXportParmsP;
MALLOCVAR(curlXportParmsP);
@@ -753,8 +518,7 @@
curlXportParmsP->no_ssl_verifyhost = curlnoverifyhost;
curlXportParmsP->user_agent = curluseragent;
- clientparms.transportparmsP = (struct xmlrpc_xportparms *)
- curlXportParmsP;
+ clientparms.transportparmsP = curlXportParmsP;
clientparms.transportparm_size = XMLRPC_CXPSIZE(user_agent);
} else {
clientparms.transportparmsP = NULL;
@@ -763,13 +527,12 @@
xmlrpc_client_init2(envP, XMLRPC_CLIENT_NO_FLAGS, NAME, VERSION,
&clientparms, XMLRPC_CPSIZE(transportparm_size));
if (!envP->fault_occurred) {
- *resultPP = xmlrpc_client_call_server_params(
- envP, serverInfoP, methodName, paramArrayP);
-
+ callWithClient(envP, serverInfoP, methodName, paramArrayP, resultPP);
+
xmlrpc_client_cleanup();
}
if (clientparms.transportparmsP)
- free(clientparms.transportparmsP);
+ free((void*)clientparms.transportparmsP);
}
Modified: freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc/xmlrpc.html
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc/xmlrpc.html (original)
+++ freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc/xmlrpc.html Fri May 23 16:56:24 2008
@@ -9,6 +9,9 @@
XML-RPC servers. XML-RPC is such that the RPCs normally need to be made
by a program rather than a person to be of use.
+<p>A similar tool done as a web form is at <a
+href="http://gggeek.damacom.it/debugger/">
+http://gggeek.damacom.it/debugger/</a>
<h2>Examples</h2>
@@ -75,7 +78,9 @@
<p>
<b>i/</b><i>integer</i> |
<b>s/</b><i>string</i> |
+<b>h/</b><i>hexstring</i> |
<b>b/</b>{<b>true</b>|<b>false</b>|<b>t</b>|<b>f</b>} |
+<b>d/</b><i>realnum</i> |
<b>n/</b> |
<b><i>string</i></b>
@@ -115,17 +120,27 @@
<dl>
<dt>i/
-<dd>integer (<int4>)
+<dd>integer (<i4>) (32 bit)
<dt>s/
<dd>string (<string>)
+<dt>h/
+<dd>byte string (<base64>). Specify the value in hexadecimal.
+
<dt>b/
-<dd>boolean (<boolean>)
+<dd>boolean (<boolean>). Specify the value as "true" or
+"t" for true; "false" or "f" for false.
+
+<dt>d/
+<dd>double (<double>) (i.e. real number)
<dt>n/
<dd>nil (<nil>)
+<dt>I/
+<dd>64 bit integer (<i8>)
+
</dl>
<p>As a shortcut, if you don't specify a prefix (i.e. your argument does
@@ -239,4 +254,13 @@
</dl>
+<h2>Limitations</h2>
+
+<p>If you run <b>xmlrpc</b> in an environment in which programs get
+their arguments encoded some way other than UTF-8, <b>xmlrpc</b>
+will generate garbage for the XML-RPC call and display garbage for
+the XML-RPC response. Typically, you control this aspect of the
+environment with a <b>LANG</b> environment variable. One safe value
+for <b>LANG</b> is "C".
+
</body>
Added: freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_cpp_proxy/Makefile
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_cpp_proxy/Makefile Fri May 23 16:56:24 2008
@@ -0,0 +1,63 @@
+ifeq ($(SRCDIR),)
+ updir = $(shell echo $(dir $(1)) | sed 's/.$$//')
+ TOOLSDIR := $(call updir,$(CURDIR))
+ SRCDIR := $(call updir,$(TOOLSDIR))
+ BLDDIR := $(SRCDIR)
+endif
+SUBDIR := tools/xmlrpc_cpp_proxy
+
+default: all
+
+include $(BLDDIR)/config.mk
+
+PROGRAMS_TO_INSTALL = xmlrpc_cpp_proxy
+
+include $(SRCDIR)/tools/common.mk
+
+INCLUDES = -I$(BLDDIR) -I$(BLDDIR)/include -I$(SRCDIR)/include
+
+CXXFLAGS = $(INCLUDES) $(CXXFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD)
+
+LDFLAGS = $(LADD)
+
+all: xmlrpc_cpp_proxy
+
+OBJECTS = \
+ xmlrpc_cpp_proxy.o \
+ xmlrpcMethod.o \
+ xmlrpcType.o \
+ proxyClass.o \
+ systemProxy.o \
+
+LIBS = \
+ $(LIBXMLRPC_CLIENTPP) \
+ $(LIBXMLRPCPP) \
+ $(LIBXMLRPC_CLIENT) \
+ $(LIBXMLRPC) \
+ $(LIBXMLRPC_XML) \
+ $(LIBXMLRPC_UTIL) \
+
+LDLIBS = $(CLIENTPP_LDLIBS) $(CLIENT_LDLIBS)
+
+xmlrpc_cpp_proxy: $(OBJECTS) $(LIBS)
+ $(CXXLD) -o $@ $(LDFLAGS) $(OBJECTS) $(LDLIBS) $(LADD)
+
+%.o:%.cpp $(BLDDIR)/include/xmlrpc-c/config.h
+ $(CXX) -c $(CXXFLAGS) $<
+
+# This common.mk dependency makes sure the symlinks get built before
+# this make file is used for anything.
+
+$(SRCDIR)/tools/common.mk: srcdir blddir
+
+include Makefile.depend
+
+.PHONY: clean
+clean: clean-common
+ rm -f xmlrpc_cpp_proxy
+
+.PHONY: distclean
+distclean: clean distclean-common
+
+.PHONY: dep
+dep: dep-common
Added: freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_cpp_proxy/proxyClass.cpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_cpp_proxy/proxyClass.cpp Fri May 23 16:56:24 2008
@@ -0,0 +1,85 @@
+#include <iostream>
+#include <stdexcept>
+#include <vector>
+
+using namespace std;
+
+#include "xmlrpc-c/client_simple.hpp"
+
+#include "xmlrpcType.hpp"
+#include "xmlrpcMethod.hpp"
+
+#include "proxyClass.hpp"
+
+
+proxyClass::proxyClass(string const& className) :
+ _className(className) {}
+
+
+
+proxyClass::proxyClass(proxyClass const& c) :
+ _className(c._className),
+ functions(c.functions) {}
+
+
+
+string
+proxyClass::className() const {
+
+ return this->_className;
+}
+
+
+
+void
+proxyClass::addFunction(xmlrpcMethod const& function) {
+
+ functions.push_back(function);
+}
+
+
+
+void
+proxyClass::printDeclaration(ostream & out) const {
+
+ out << "class " << this->_className << " {" << endl;
+ out << endl;
+ out << "public:" << endl;
+
+ // emit the constructor prototype:
+ out << " " << this->_className << "(std::string const& serverUrl) "
+ << endl
+ << " : serverUrl(serverUrl) {}"
+ << endl;
+
+ // emit the XML-RPC method method prototypes:
+ vector<xmlrpcMethod>::const_iterator f;
+ for (f = this->functions.begin(); f < this->functions.end(); ++f) {
+ f->printDeclarations(out);
+ }
+
+ // emit the private data:
+
+ out << "private:" << endl;
+
+ out << " xmlrpc_c::clientSimple client;" << endl;
+
+ out << " std::string const serverUrl;" << endl;
+ out << " // The URL for the server for which we are proxy" << endl;
+
+ // emit the class closing:
+ out << "};" << endl;
+}
+
+
+
+void
+proxyClass::printDefinition(ostream & out) const {
+
+ vector<xmlrpcMethod>::const_iterator f;
+
+ for (f = this->functions.begin(); f < this->functions.end(); ++f) {
+ f->printDefinitions(out, this->_className);
+ }
+}
+
Added: freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_cpp_proxy/proxyClass.hpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_cpp_proxy/proxyClass.hpp Fri May 23 16:56:24 2008
@@ -0,0 +1,32 @@
+#include <vector>
+#include <string>
+
+#include "xmlrpcMethod.hpp"
+
+class proxyClass {
+ // An object of this class contains information about a proxy
+ // class, and knows how to generate code.
+
+public:
+ proxyClass(std::string const& className);
+
+ proxyClass(proxyClass const&);
+
+ std::string
+ className() const;
+
+ void
+ addFunction(xmlrpcMethod const& function);
+
+ void
+ printDeclaration(std::ostream& out) const;
+
+ void
+ printDefinition(std::ostream& out) const;
+
+private:
+
+ std::string const _className;
+
+ std::vector<xmlrpcMethod> functions;
+};
Added: freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_cpp_proxy/systemProxy.cpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_cpp_proxy/systemProxy.cpp Fri May 23 16:56:24 2008
@@ -0,0 +1,57 @@
+/*=============================================================================
+ systemProxy
+===============================================================================
+
+ This is a proxy class for the introspection system methods of the server.
+
+ Note that you can use 'xmlrpc_cpp_proxy' itself to generate this
+ file, but we hand-edit it to make it easier to read.
+
+=============================================================================*/
+
+#include "systemProxy.hpp"
+
+using namespace std;
+
+xmlrpc_c::value // array
+systemProxy::listMethods(string const& serverUrl) {
+
+ xmlrpc_c::paramList params;
+ xmlrpc_c::value result;
+
+ this->call(serverUrl, "system.listMethods", &result);
+
+ return result;
+}
+
+
+
+xmlrpc_c::value // array
+systemProxy::methodSignature(string const& serverUrl,
+ string const& methodName) {
+
+ xmlrpc_c::paramList params;
+ params.add(xmlrpc_c::value_string(methodName));
+
+ xmlrpc_c::value result;
+
+ this->call(serverUrl, "system.methodSignature", params, &result);
+
+ return result;
+}
+
+
+
+string
+systemProxy::methodHelp(string const& serverUrl,
+ string const& methodName) {
+
+ xmlrpc_c::paramList params;
+ params.add(xmlrpc_c::value_string(methodName));
+
+ xmlrpc_c::value result;
+
+ this->call(serverUrl, "system.methodHelp", params, &result);
+
+ return xmlrpc_c::value_string(result);
+}
Added: freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_cpp_proxy/systemProxy.hpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_cpp_proxy/systemProxy.hpp Fri May 23 16:56:24 2008
@@ -0,0 +1,25 @@
+#ifndef SYSTEMPROXY_HPP_INCLUDED
+#define SYSTEMPROXY_HPP_INCLUDED
+
+#include <xmlrpc-c/base.hpp>
+#include <xmlrpc-c/client_simple.hpp>
+
+class systemProxy : public xmlrpc_c::clientSimple {
+
+public:
+ systemProxy() {}
+
+ xmlrpc_c::value /*array*/
+ listMethods(std::string const& serverUrl);
+
+ xmlrpc_c::value /*array*/
+ methodSignature(std::string const& serverUrl,
+ std::string const& methodName);
+
+ std::string
+ methodHelp(std::string const& serverUrl,
+ std::string const& methodName);
+};
+
+#endif
+
Added: freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_cpp_proxy/xmlrpcMethod.cpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_cpp_proxy/xmlrpcMethod.cpp Fri May 23 16:56:24 2008
@@ -0,0 +1,240 @@
+#include <iostream>
+#include <sstream>
+#include <stdexcept>
+
+#include "xmlrpcType.hpp"
+
+#include "xmlrpcMethod.hpp"
+
+using namespace std;
+
+
+xmlrpcMethod::xmlrpcMethod(string const& functionName,
+ string const& methodName,
+ string const& help,
+ xmlrpc_c::value_array const& signatureList) :
+ mFunctionName(functionName),
+ mMethodName(methodName),
+ mHelp(help),
+ mSynopsis(signatureList) {}
+
+
+
+xmlrpcMethod::xmlrpcMethod(xmlrpcMethod const& f) :
+ mFunctionName(f.mFunctionName),
+ mMethodName(f.mMethodName),
+ mHelp(f.mHelp),
+ mSynopsis(f.mSynopsis) {}
+
+
+
+xmlrpcMethod&
+xmlrpcMethod::operator= (xmlrpcMethod const& f) {
+
+ if (this != &f) {
+ this->mFunctionName = f.mFunctionName;
+ this->mMethodName = f.mMethodName;
+ this->mHelp = f.mHelp;
+ this->mSynopsis = f.mSynopsis;
+ }
+ return *this;
+}
+
+
+
+
+
+
+size_t
+xmlrpcMethod::parameterCount(size_t const synopsisIndex) const {
+
+ xmlrpc_c::value_array const funcSynop(
+ mSynopsis.vectorValueValue()[synopsisIndex]);
+ size_t const size(funcSynop.size());
+
+ if (size < 1)
+ throw domain_error("Synopsis contains no items");
+
+ return size - 1;
+}
+
+
+
+xmlrpcType const&
+xmlrpcMethod::parameterType(size_t const synopsisIndex,
+ size_t const parameterIndex) const {
+
+ xmlrpc_c::value_array const funcSynop(
+ mSynopsis.vectorValueValue()[synopsisIndex]);
+ xmlrpc_c::value_string const param(
+ funcSynop.vectorValueValue()[parameterIndex + 1]);
+
+ return findXmlrpcType(static_cast<string>(param));
+}
+
+
+
+const xmlrpcType&
+xmlrpcMethod::returnType(size_t const synopsisIndex) const {
+
+ xmlrpc_c::value_array const funcSynop(
+ mSynopsis.vectorValueValue()[synopsisIndex]);
+
+ xmlrpc_c::value_string datatype(funcSynop.vectorValueValue()[0]);
+ return findXmlrpcType(static_cast<string>(datatype));
+}
+
+
+
+void
+xmlrpcMethod::printParameters(ostream & out,
+ size_t const synopsisIndex) const {
+/*----------------------------------------------------------------------------
+ Print the parameter declarations.
+-----------------------------------------------------------------------------*/
+ size_t const end(parameterCount(synopsisIndex));
+
+ bool first;
+
+ first = true;
+
+ for (size_t i = 0; i < end; ++i) {
+ if (!first)
+ out << ", ";
+
+ xmlrpcType const& ptype(parameterType(synopsisIndex, i));
+
+ string const localName(ptype.defaultParameterBaseName(i + 1));
+ out << ptype.parameterFragment(localName);
+
+ first = false;
+ }
+}
+
+
+
+void
+xmlrpcMethod::printDeclaration(ostream & out,
+ size_t const synopsisIndex) const {
+
+ try {
+ xmlrpcType const& rtype(returnType(synopsisIndex));
+
+ out << " " << rtype.returnTypeFragment() << " "
+ << mFunctionName << " (";
+
+ printParameters(out, synopsisIndex);
+
+ out << ");" << endl;
+ } catch (xmlrpc_c::fault const& f) {
+ ostringstream msg;
+
+ msg << "Failed to generate header for signature "
+ << synopsisIndex
+ << " . "
+ << f.getDescription();
+
+ throw(logic_error(msg.str()));
+ }
+}
+
+
+
+void
+xmlrpcMethod::printDeclarations(ostream & out) const {
+
+ try {
+ // Print the method help as a comment
+
+ out << endl << " /* " << mHelp << " */" << endl;
+
+ size_t end;
+
+ try {
+ end = mSynopsis.size();
+ } catch (xmlrpc_c::fault const& f) {
+ throw(logic_error("Failed to get size of signature array for "
+ "method " + this->mFunctionName + ". " +
+ f.getDescription()));
+ }
+ // Print the declarations for all the signatures of this
+ // XML-RPC method.
+
+ for (size_t i = 0; i < end; ++i)
+ printDeclaration(out, i);
+
+ } catch (exception const& e) {
+ throw(logic_error("Failed to generate declarations for method " +
+ this->mFunctionName + ". " + e.what()));
+ }
+}
+
+
+
+void
+xmlrpcMethod::printDefinition(ostream & out,
+ string const& className,
+ size_t const synopsisIndex) const {
+
+ xmlrpcType const& rtype(returnType(synopsisIndex));
+
+ out << rtype.returnTypeFragment() << " "
+ << className << "::" << mFunctionName << " (";
+
+ printParameters(out, synopsisIndex);
+
+ out << ") {" << endl;
+
+ size_t const end(parameterCount(synopsisIndex));
+ if (end > 0){
+ // Emit code to generate the parameter list object
+ out << " xmlrpc_c::paramList params;" << endl;
+ for (size_t i = 0; i < end; ++i) {
+ xmlrpcType const& ptype(parameterType(synopsisIndex, i));
+ string const basename(ptype.defaultParameterBaseName(i + 1));
+ out << " params.add("
+ << ptype.inputConversionFragment(basename) << ");" << endl;
+ }
+ }
+
+ // Emit result holder declaration.
+ out << " xmlrpc_c::value result;" << endl;
+
+ // Emit the call to the XML-RPC call method
+ out << " this->client.call("
+ << "this->serverUrl, "
+ << "\"" << mMethodName << "\", ";
+
+ if (end > 0)
+ out << "params, ";
+
+ out << "&result);" << endl;
+
+ // Emit the return statement.
+ out << " return " << rtype.outputConversionFragment("result")
+ << ";" << endl;
+ out << "}" << endl;
+}
+
+
+
+void
+xmlrpcMethod::printDefinitions(ostream & out,
+ string const& className) const {
+
+ try {
+ size_t const end(mSynopsis.size());
+
+ for (size_t i = 0; i < end; ++i) {
+ out << endl;
+ printDefinition(out, className, i);
+ }
+ } catch (xmlrpc_c::fault const& f) {
+ throw(logic_error("Failed to generate definitions for class " +
+ this->mFunctionName + ". " +
+ f.getDescription()));
+ }
+}
+
+
+
Added: freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_cpp_proxy/xmlrpcMethod.hpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_cpp_proxy/xmlrpcMethod.hpp Fri May 23 16:56:24 2008
@@ -0,0 +1,59 @@
+#ifndef XMLRPCMETHOD_HPP
+#define XMLRPCMETHOD_HPP
+
+#include <string>
+#include <iostream>
+#include <xmlrpc-c/base.hpp>
+
+class xmlrpcMethod {
+ // An object of this class contains everything we know about a
+ // given XML-RPC method, and knows how to print local bindings.
+
+ std::string mFunctionName;
+ std::string mMethodName;
+ std::string mHelp;
+ xmlrpc_c::value_array mSynopsis;
+
+public:
+ xmlrpcMethod(std::string const& function_name,
+ std::string const& method_name,
+ std::string const& help,
+ xmlrpc_c::value_array const& signatureList);
+
+ xmlrpcMethod(xmlrpcMethod const& f);
+
+ xmlrpcMethod& operator= (xmlrpcMethod const& f);
+
+ void
+ printDeclarations(std::ostream& out) const;
+
+ void
+ printDefinitions(std::ostream & out,
+ std::string const& className) const;
+
+private:
+ void
+ printParameters(std::ostream & out,
+ size_t const synopsis_index) const;
+
+ void
+ printDeclaration(std::ostream & out,
+ size_t const synopsis_index) const;
+
+ void
+ printDefinition(std::ostream & out,
+ std::string const& className,
+ size_t const synopsis_index) const;
+
+ const xmlrpcType&
+ returnType(size_t const synopsis_index) const;
+
+ size_t
+ parameterCount(size_t const synopsis_index) const;
+
+ const xmlrpcType&
+ parameterType(size_t const synopsis_index,
+ size_t const parameter_index) const;
+};
+
+#endif
Added: freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_cpp_proxy/xmlrpcType.cpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_cpp_proxy/xmlrpcType.cpp Fri May 23 16:56:24 2008
@@ -0,0 +1,270 @@
+#include <iostream>
+#include <sstream>
+#include <stdexcept>
+#include <map>
+#include <vector>
+
+#include <xmlrpc-c/base.hpp>
+
+#include "xmlrpcType.hpp"
+
+using namespace std;
+
+
+
+//=========================================================================
+// abstract class xmlrpcType
+//=========================================================================
+// Instances of xmlrpcType know how generate code fragments for manipulating
+// a specific XML-RPC data type.
+
+string
+xmlrpcType::defaultParameterBaseName(unsigned int const position) const {
+
+ ostringstream nameStream;
+
+ nameStream << typeName() << position;
+
+ return nameStream.str();
+}
+
+
+
+class rawXmlrpcType : public xmlrpcType {
+public:
+ rawXmlrpcType(string const& typeName) : xmlrpcType(typeName) {}
+
+ virtual string
+ parameterFragment(string const& baseName) const;
+
+ virtual string
+ inputConversionFragment(string const& baseName) const;
+
+ virtual string
+ returnTypeFragment() const;
+
+ virtual string
+ outputConversionFragment(string const& varName) const;
+};
+
+
+
+string
+rawXmlrpcType::parameterFragment(string const& baseName) const {
+ return "xmlrpc_c::value /*" + typeName() + "*/ " + baseName;
+}
+
+
+
+string
+rawXmlrpcType::inputConversionFragment(string const& baseName) const {
+
+ return baseName;
+}
+
+
+
+string
+rawXmlrpcType::returnTypeFragment() const {
+ return "xmlrpc_c::value /*" + typeName() + "*/";
+}
+
+
+
+string
+rawXmlrpcType::outputConversionFragment(string const& varName) const {
+
+ return varName;
+}
+
+
+
+class simpleXmlrpcType : public xmlrpcType {
+
+ string mNativeType;
+ string mMakerFunc;
+ string mGetterFunc;
+
+public:
+ simpleXmlrpcType(string const& typeName,
+ string const& nativeType,
+ string const& makerFunc,
+ string const& getterFunc);
+
+ virtual string
+ parameterFragment(string const& baseName) const;
+
+ virtual string
+ inputConversionFragment(string const& baseName) const;
+
+ virtual string
+ returnTypeFragment() const;
+
+ virtual string
+ outputConversionFragment(string const& varName) const;
+};
+
+
+
+simpleXmlrpcType::simpleXmlrpcType(string const& typeName,
+ string const& nativeType,
+ string const& makerFunc,
+ string const& getterFunc)
+ : xmlrpcType(typeName),
+ mNativeType(nativeType),
+ mMakerFunc(makerFunc),
+ mGetterFunc(getterFunc) {
+}
+
+
+
+string
+simpleXmlrpcType::parameterFragment(string const& baseName) const {
+
+ return mNativeType + " const " + baseName;
+}
+
+
+
+string
+simpleXmlrpcType::inputConversionFragment(string const& baseName) const {
+
+ return mMakerFunc + "(" + baseName + ")";
+}
+
+
+
+string
+simpleXmlrpcType::returnTypeFragment() const {
+
+ return mNativeType;
+}
+
+
+
+string
+simpleXmlrpcType::outputConversionFragment(string const& varName) const {
+ return mMakerFunc + "(" + varName + ")";
+}
+
+
+
+class voidXmlrpcType : public xmlrpcType {
+public:
+ voidXmlrpcType() : xmlrpcType("void") {}
+
+ virtual string
+ parameterFragment(string const& baseName) const;
+
+ virtual string
+ inputConversionFragment(string const& baseName) const;
+
+ virtual string
+ returnTypeFragment() const;
+
+ virtual string
+ outputConversionFragment(string const& varName) const;
+};
+
+
+
+string
+voidXmlrpcType::parameterFragment(string const&) const {
+
+ throw domain_error("Can't handle functions with 'void' arguments'");
+}
+
+
+
+string
+voidXmlrpcType::inputConversionFragment(string const&) const {
+
+ throw domain_error("Can't handle functions with 'void' arguments'");
+}
+
+
+
+string
+voidXmlrpcType::returnTypeFragment () const {
+
+ return "void";
+}
+
+
+
+string
+voidXmlrpcType::outputConversionFragment(string const&) const {
+ return "/* Return value ignored. */";
+}
+
+
+
+static simpleXmlrpcType const intType ("int", "int",
+ "xmlrpc_c::value_int",
+ "getInt");
+static simpleXmlrpcType const boolType ("bool", "bool",
+ "xmlrpc_c::value_boolean",
+ "getBool");
+static simpleXmlrpcType const doubleType ("double", "double",
+ "xmlrpc_c::value_double",
+ "getDouble");
+static simpleXmlrpcType const stringType ("string", "std::string",
+ "xmlrpc_c::value_string",
+ "getString");
+
+static rawXmlrpcType const dateTimeType ("dateTime");
+static rawXmlrpcType const base64Type ("base64");
+static rawXmlrpcType const structType ("struct");
+static rawXmlrpcType const arrayType ("array");
+
+static voidXmlrpcType const voidType;
+
+
+
+const xmlrpcType&
+findXmlrpcType(string const& name) {
+/*----------------------------------------------------------------------------
+ Given the name of an XML-RPC data type, try to find a corresponding
+ xmlrpcType object.
+-----------------------------------------------------------------------------*/
+ if (name == "int" || name == "i4")
+ return intType;
+ else if (name == "boolean")
+ return boolType;
+ else if (name == "double")
+ return doubleType;
+ else if (name == "string")
+ return stringType;
+ else if (name == "dateTime.iso8601")
+ return dateTimeType;
+ else if (name == "base64")
+ return base64Type;
+ else if (name == "struct")
+ return structType;
+ else if (name == "array")
+ return arrayType;
+ else if (name == "void")
+ return voidType;
+ else if (name == "INT")
+ return intType;
+ else if (name == "BOOLEAN")
+ return boolType;
+ else if (name == "DOUBLE")
+ return doubleType;
+ else if (name == "STRING")
+ return stringType;
+ else if (name == "DATETIME.ISO8601")
+ return dateTimeType;
+ else if (name == "BASE64")
+ return base64Type;
+ else if (name == "STRUCT")
+ return structType;
+ else if (name == "ARRAY")
+ return arrayType;
+ else if (name == "VOID")
+ return voidType;
+ else if (name == "NIL")
+ return voidType;
+ else
+ throw domain_error("Unknown XML-RPC type name '" + name + "'");
+}
Added: freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_cpp_proxy/xmlrpcType.hpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_cpp_proxy/xmlrpcType.hpp Fri May 23 16:56:24 2008
@@ -0,0 +1,43 @@
+#include <string>
+#include <cassert>
+
+class xmlrpcType {
+ std::string mTypeName;
+
+ xmlrpcType(xmlrpcType const&) { assert(false); }
+
+ xmlrpcType& operator= (xmlrpcType const&) {
+ assert(false);
+ return *this;
+ }
+
+public:
+ xmlrpcType(const std::string& type_name) : mTypeName(type_name) {}
+
+ virtual ~xmlrpcType () {}
+
+ // Return the name for this XML-RPC type.
+ virtual std::string
+ typeName() const { return mTypeName; }
+
+ // Given a parameter position, calculate a unique base name for all
+ // parameter-related variables.
+ virtual std::string
+ defaultParameterBaseName(unsigned int const position) const;
+
+ // Virtual functions for processing parameters.
+ virtual std::string
+ parameterFragment(std::string const& base_name) const = 0;
+
+ virtual std::string
+ inputConversionFragment(std::string const& base_name) const = 0;
+
+ // Virtual functions for processing return values.
+ virtual std::string
+ returnTypeFragment () const = 0;
+
+ virtual std::string
+ outputConversionFragment(std::string const& var_name) const = 0;
+};
+
+const xmlrpcType& findXmlrpcType(const std::string& name);
Added: freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_cpp_proxy/xmlrpc_cpp_proxy.cpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_cpp_proxy/xmlrpc_cpp_proxy.cpp Fri May 23 16:56:24 2008
@@ -0,0 +1,208 @@
+#include <iostream>
+#include <stdexcept>
+#include <cstdlib>
+
+#include "xmlrpcType.hpp"
+#include "xmlrpcMethod.hpp"
+#include "proxyClass.hpp"
+#include "systemProxy.hpp"
+
+using namespace std;
+
+
+/*----------------------------------------------------------------------------
+ Command line
+-----------------------------------------------------------------------------*/
+
+class cmdlineInfo {
+public:
+ string serverUrl;
+ string methodPrefix;
+ string localClass;
+
+ cmdlineInfo(int const argc,
+ const char ** const argv);
+
+private:
+ cmdlineInfo();
+};
+
+
+
+cmdlineInfo::cmdlineInfo(int const argc,
+ const char ** const argv) {
+
+ if (argc-1 != 3) {
+ cerr << "There are 3 arguments: server URL, "
+ << "prefix for the methods to include (null to include all), "
+ << "and name to give the generated proxy class. "
+ << "You specified " << argc-1 << " arguments."
+ << endl
+ << "Example: "
+ << "xmlrpc_cpp_proxy http://localhost/RPC2 system systemProxy"
+ << endl;
+ exit(1);
+ }
+ this->serverUrl = string(argv[1]);
+ this->methodPrefix = string(argv[2]);
+ this->localClass = string(argv[3]);
+}
+
+
+
+static proxyClass
+getClassInfo(string const& serverUrl,
+ string const& classPrefix,
+ string const& className) {
+/*----------------------------------------------------------------------------
+ Connect to a remote server and extract the information we'll need to
+ build a proxy class.
+-----------------------------------------------------------------------------*/
+ proxyClass theClass(className);
+
+ systemProxy system;
+
+ xmlrpc_c::value_array methods(system.listMethods(serverUrl));
+
+ unsigned int arraySize = methods.size();
+
+ for (size_t i = 0; i < arraySize; ++i) {
+
+ // Break the method name into two pieces.
+ xmlrpc_c::value_string val = (methods.vectorValueValue())[i];
+ string const methodName(static_cast<string>(val));
+ size_t const lastDot(methodName.rfind('.'));
+
+ string methodPrefix;
+ string functionName;
+
+ if (lastDot == string::npos) {
+ methodPrefix = "";
+ functionName = methodName;
+ } else {
+ methodPrefix = string(methodName, 0, lastDot);
+ functionName = string(methodName, lastDot + 1);
+ }
+
+ if (methodPrefix == classPrefix) {
+ // It's a method User cares about
+
+ string const help(system.methodHelp(serverUrl, methodName));
+ xmlrpc_c::value const signatureList(
+ system.methodSignature(serverUrl, methodName));
+
+ if (signatureList.type() != xmlrpc_c::value::TYPE_ARRAY) {
+ // It must be the string "undef", meaning the server
+ // won't tell us any signatures.
+ cerr << "Skipping method " << methodName << " "
+ << "because server does not report any signatures "
+ << "for it (via system.methodSignature method)"
+ << endl;
+ } else {
+ // Add this function to our class information.
+ xmlrpcMethod const method(
+ functionName,
+ methodName,
+ help,
+ xmlrpc_c::value_array(signatureList));
+ theClass.addFunction(method);
+ }
+ }
+ }
+ return theClass;
+}
+
+
+
+static void
+printHeader(ostream & out,
+ proxyClass const& classInfo) {
+/*----------------------------------------------------------------------------
+ Print a complete header for the specified class.
+-----------------------------------------------------------------------------*/
+ string const className(classInfo.className());
+
+ try {
+ out << "// Interface definition for " << className << " class, "
+ << "an XML-RPC FOR C/C++ proxy class" << endl;
+ out << "// Generated by 'xmlrpc_cpp_proxy'" << endl;
+ out << endl;
+
+ string const headerSymbol("_" + className + "_H_");
+
+ out << "#ifndef " << headerSymbol << endl;
+ out << "#define " << headerSymbol << " 1" << endl;
+ out << endl;
+ out << "#include <string>" << endl;
+ out << "#include <xmlrpc-c/client_simple.hpp>" << endl;
+ out << endl;
+
+ classInfo.printDeclaration(cout);
+
+ out << endl;
+ out << "#endif /* " << headerSymbol << " */" << endl;
+ } catch (exception const& e) {
+ throw(logic_error("Failed to generate header for class " +
+ className + ". " + e.what()));
+ }
+}
+
+
+
+static void
+printCppFile(ostream & out,
+ proxyClass const& classInfo) {
+/*----------------------------------------------------------------------------
+ Print a complete definition for the specified class.
+-----------------------------------------------------------------------------*/
+ string const className(classInfo.className());
+
+ try {
+ out << "// " << className << " - "
+ << "an XML-RPC FOR C/C++ proxy class" << endl;
+ out << "// Generated by 'xmlrpc_cpp_proxy'" << endl;
+ out << endl;
+
+ out << "#include \"" << className << ".h\"" << endl;
+
+ classInfo.printDefinition(cout);
+ } catch (xmlrpc_c::fault const& f) {
+ throw(logic_error("Failed to generate definition for class " +
+ className + ". " + f.getDescription()));
+ }
+}
+
+
+
+int
+main(int const argc,
+ const char ** const argv) {
+
+ string const myName(argv[0]);
+
+ cmdlineInfo const cmdline(argc, argv);
+
+ int retval;
+
+ try {
+ proxyClass system(getClassInfo(cmdline.serverUrl,
+ cmdline.methodPrefix,
+ cmdline.localClass));
+ printHeader(cout, system);
+ cout << endl;
+ printCppFile(cout, system);
+ retval = 0;
+ } catch (xmlrpc_c::fault& f) {
+ cerr << myName << ": XML-RPC fault #" << f.getCode()
+ << ": " << f.getDescription() << endl;
+ retval = 1;
+ } catch (exception const& e) {
+ cerr << myName << ": " << e.what() << endl;
+ retval = 1;
+ } catch (...) {
+ cerr << myName << ": Unknown exception" << endl;
+ retval = 1;
+ }
+
+ return retval;
+}
Added: freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_pstream/Makefile
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_pstream/Makefile Fri May 23 16:56:24 2008
@@ -0,0 +1,77 @@
+ifeq ($(SRCDIR),)
+ updir = $(shell echo $(dir $(1)) | sed 's/.$$//')
+ TOOLSDIR := $(call updir,$(CURDIR))
+ SRCDIR := $(call updir,$(TOOLSDIR))
+ BLDDIR := $(SRCDIR)
+endif
+SUBDIR := tools/xmlrpc_pstream
+
+READLINE_LDLIBS = -lreadline -lncurses
+
+default: all
+
+include $(BLDDIR)/config.mk
+
+PROGRAMS_TO_INSTALL = xmlrpc_pstream
+
+include $(SRCDIR)/tools/common.mk
+
+INCLUDES = \
+ -I../lib/include \
+ -Isrcdir/lib/util/include \
+ -Iblddir \
+ -Iblddir/include \
+ -Isrcdir/include \
+
+CXXFLAGS = $(INCLUDES) $(CXXFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD)
+
+LDFLAGS = $(LADD)
+
+all: xmlrpc_pstream
+
+OBJECTS = \
+ xmlrpc_pstream.o \
+ $(TOOLSDIR)/lib/dumpvalue.o \
+
+LIBS = \
+ $(LIBXMLRPC_CLIENTPP) \
+ $(LIBXMLRPCPP) \
+ $(LIBXMLRPC_CLIENT) \
+ $(LIBXMLRPC) \
+ $(LIBXMLRPC_XML) \
+ $(LIBXMLRPC_UTIL) \
+
+LDLIBS = $(CLIENTPP_LDLIBS) $(CLIENT_LDLIBS) $(READLINE_LDLIBS)
+
+UTIL_OBJS = \
+ casprintf.o \
+ cmdline_parser_cpp.o \
+ cmdline_parser.o \
+ getoptx.o \
+ string_parser.o \
+ stripcaseeq.o \
+
+UTILS = $(UTIL_OBJS:%=$(UTIL_DIR)/%)
+
+xmlrpc_pstream: $(OBJECTS) $(LIBS) $(UTILS)
+ $(CXXLD) -o $@ $(LDFLAGS) $(OBJECTS) $(UTILS) $(LDLIBS) $(LADD)
+
+%.o:%.cpp blddir/include/xmlrpc-c/config.h
+ $(CXX) -c $(CXXFLAGS) $<
+
+# This common.mk dependency makes sure the symlinks get built before
+# this make file is used for anything.
+
+$(SRCDIR)/common.mk: srcdir blddir
+
+include Makefile.depend
+
+.PHONY: clean
+clean: clean-common
+ rm -f xmlrpc_pstream
+
+.PHONY: distclean
+distclean: clean distclean-common
+
+.PHONY: dep
+dep: dep-common
Added: freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_pstream/test
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_pstream/test Fri May 23 16:56:24 2008
@@ -0,0 +1,28 @@
+#! /bin/sh
+
+# This is for testing and playing with Xmlrpc_pstream.
+
+# To use, first start a packet stream XML-RPC server. The
+# 'pstream_inetd_server' program from examples/cpp is good:
+#
+# $ socketexec -accept -local_port=8080 -- pstream_inetd_server
+#
+# Then (in another shell), run this program:
+#
+# $ ./test
+# > sample.add i/3 i/5
+#
+# Result:
+# Integer: 8
+#
+# > [ctl-D]
+# $
+#
+# OR:
+#
+# $ ./test sample.add i/3 i/5
+# $
+
+socketexec -connect -remote_host=localhost -remote_port=8080 --filedes=3 -- \
+ ./xmlrpc_pstream $*
+
Added: freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_pstream/xmlrpc_pstream.cpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_pstream/xmlrpc_pstream.cpp Fri May 23 16:56:24 2008
@@ -0,0 +1,503 @@
+#include <cassert>
+#include <cerrno>
+#include <string>
+#include <vector>
+#include <list>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <readline/readline.h>
+
+#include "cmdline_parser.hpp"
+#include "xmlrpc-c/girerr.hpp"
+using girerr::throwf;
+
+#include <features.h> // for __BEGIN_DECLS
+
+__BEGIN_DECLS
+#include "dumpvalue.h" /* An internal Xmlrpc-c header file ! */
+__END_DECLS
+
+
+#include <xmlrpc-c/base.hpp>
+#include <xmlrpc-c/client.hpp>
+#include <xmlrpc-c/client_transport.hpp>
+
+using namespace std;
+using namespace xmlrpc_c;
+
+/*----------------------------------------------------------------------------
+ Command line
+-----------------------------------------------------------------------------*/
+
+class cmdlineInfo {
+public:
+ int serverfd;
+ bool interactive;
+
+ // Valid only if !interactive:
+ string methodName;
+ vector<string> params;
+
+ cmdlineInfo(int const argc,
+ const char ** const argv);
+
+private:
+ cmdlineInfo();
+};
+
+
+
+static void
+parseCommandLine(cmdlineInfo * const cmdlineP,
+ int const argc,
+ const char ** const argv) {
+
+ CmdlineParser cp;
+
+ cp.defineOption("serverfd", CmdlineParser::UINT);
+
+ try {
+ cp.processOptions(argc, argv);
+ } catch (exception const& e) {
+ throwf("Command syntax error. %s", e.what());
+ }
+
+ if (cp.optionIsPresent("serverfd")) {
+ cmdlineP->serverfd = cp.getOptionValueUint("serverfd");
+ } else
+ cmdlineP->serverfd = 3;
+
+ if (cp.argumentCount() < 1)
+ cmdlineP->interactive = true;
+ else {
+ cmdlineP->interactive = false;
+ cmdlineP->methodName = cp.getArgument(0);
+ for (uint argI = 1; argI < cp.argumentCount(); ++argI)
+ cmdlineP->params.push_back(cp.getArgument(argI));
+ }
+}
+
+
+
+cmdlineInfo::
+cmdlineInfo(int const argc,
+ const char ** const argv) {
+
+ try {
+ parseCommandLine(this, argc, argv);
+ } catch (exception const& e) {
+ throwf("Command syntax error. %s", e.what());
+ }
+}
+
+
+
+static value
+bytestringValFromParm(string const& valueString) {
+
+ value retval;
+
+ if (valueString.length() / 2 * 2 != valueString.length())
+ throwf("Hexadecimal text is not an even "
+ "number of characters (it is %u characters)",
+ valueString.length());
+ else {
+ vector<unsigned char> byteString(valueString.length() / 2);
+ size_t strCursor;
+
+ strCursor = 0;
+
+ while (strCursor < valueString.length()) {
+ string const hexByte(valueString.substr(strCursor, 2));
+
+ unsigned char byte;
+ int rc;
+
+ rc = sscanf(hexByte.c_str(), "%2hhx", &byte);
+
+ byteString.push_back(byte);
+
+ if (rc != 1)
+ throwf("Invalid hex data '%s'", hexByte.c_str());
+ else
+ strCursor += 2;
+ }
+ retval = value_bytestring(byteString);
+ }
+ return retval;
+}
+
+
+
+static value
+intValFromParm(string const& valueString) {
+
+ value retval;
+
+ if (valueString.length() < 1)
+ throwf("Integer argument has nothing after the 'i/'");
+ else {
+ long longValue;
+ char * tailptr;
+
+ errno = 0;
+
+ longValue = strtol(valueString.c_str(), &tailptr, 10);
+
+ if (errno == ERANGE)
+ throwf("'%s' is out of range for a 32 bit integer",
+ valueString.c_str());
+ else if (errno != 0)
+ throwf("Mysterious failure of strtol(), errno=%d (%s)",
+ errno, strerror(errno));
+ else {
+ if (*tailptr != '\0')
+ throwf("Integer argument has non-digit crap in it: '%s'",
+ tailptr);
+ else
+ retval = value_int(longValue);
+ }
+ }
+ return retval;
+}
+
+
+
+static value
+boolValFromParm(string const& valueString) {
+
+ value retval;
+
+ if (valueString == "t" || valueString == "true")
+ retval = value_boolean(true);
+ else if (valueString == "f" || valueString == "false")
+ retval = value_boolean(false);
+ else
+ throwf("Boolean argument has unrecognized value '%s'. "
+ "recognized values are 't', 'f', 'true', and 'false'.",
+ valueString.c_str());
+
+ return retval;
+}
+
+
+
+static value
+doubleValFromParm(string const& valueString) {
+
+ value retval;
+
+ if (valueString.length() < 1)
+ throwf("\"Double\" argument has nothing after the 'd/'");
+ else {
+ double value;
+ char * tailptr;
+
+ value = strtod(valueString.c_str(), &tailptr);
+
+ if (*tailptr != '\0')
+ throwf("\"Double\" argument has non-decimal crap in it: '%s'",
+ tailptr);
+ else
+ retval = value_double(value);
+ }
+ return retval;
+}
+
+
+
+static value
+nilValFromParm(string const& valueString) {
+
+ value retval;
+
+ if (valueString.length() > 0)
+ throwf("Nil argument has something after the 'n/'");
+ else
+ retval = value_nil();
+
+ return retval;
+}
+
+
+
+static value
+i8ValFromParm(string const& valueString) {
+
+ value retval;
+
+ if (valueString.length() < 1)
+ throwf("Integer argument has nothing after the 'I/'");
+ else {
+ long long value;
+ char * tailptr;
+
+ errno = 0;
+
+ value = strtoll(valueString.c_str(), &tailptr, 10);
+
+ if (errno == ERANGE)
+ throwf("'%s' is out of range for a 64 bit integer",
+ valueString.c_str());
+ else if (errno != 0)
+ throwf("Mysterious failure of strtoll(), errno=%d (%s)",
+ errno, strerror(errno));
+ else {
+ if (*tailptr != '\0')
+ throwf("64 bit integer argument has non-digit crap "
+ "in it: '%s'",
+ tailptr);
+ else
+ retval = value_i8(value);
+ }
+ }
+ return retval;
+}
+
+
+
+static value
+parameterFromArg(string const& paramArg) {
+
+ value param;
+
+ try {
+ if (paramArg.substr(0, 2) == "s/")
+ param = value_string(paramArg.substr(2));
+ else if (paramArg.substr(0, 2) == "h/")
+ param = bytestringValFromParm(paramArg.substr(2));
+ else if (paramArg.substr(0, 2) == "i/")
+ param = intValFromParm(paramArg.substr(2));
+ else if (paramArg.substr(0, 2) == "I/")
+ param = i8ValFromParm(paramArg.substr(2));
+ else if (paramArg.substr(0, 2) == "d/")
+ param = doubleValFromParm(paramArg.substr(2));
+ else if (paramArg.substr(0, 2) == "b/")
+ param = boolValFromParm(paramArg.substr(2));
+ else if (paramArg.substr(0, 2) == "n/")
+ param = nilValFromParm(paramArg.substr(2));
+ else {
+ /* It's not in normal type/value format, so we take it to be
+ the shortcut string notation
+ */
+ param = value_string(paramArg);
+ }
+ } catch (exception const& e) {
+ throwf("Failed to interpret parameter argument '%s'. %s",
+ paramArg.c_str(), e.what());
+ }
+ return param;
+}
+
+
+
+static paramList
+paramListFromParamArgs(vector<string> const& params) {
+
+ paramList paramList;
+
+ for (vector<string>::const_iterator p = params.begin();
+ p != params.end(); ++p)
+ paramList.add(parameterFromArg(*p));
+
+ return paramList;
+}
+
+
+
+static void
+callWithClient(client * const clientP,
+ string const& methodName,
+ paramList const& paramList,
+ value * const resultP) {
+
+ rpcPtr myRpcP(methodName, paramList);
+
+ carriageParm_pstream myCarriageParm; // Empty - no parm needed
+
+ try {
+ myRpcP->call(clientP, &myCarriageParm);
+ } catch (exception const& e) {
+ throwf("RPC failed. %s", e.what());
+ }
+ *resultP = myRpcP->getResult();
+}
+
+
+
+static void
+dumpResult(value const& result) {
+
+ cout << "Result:" << endl << endl;
+
+ /* Here we borrow code from inside Xmlrpc-c, and also use an
+ internal interface of xmlrpc_c::value. This sliminess is one
+ reason that this is Bryan's private code instead of part of the
+ Xmlrpc-c package.
+
+ Note that you must link with the dumpvalue.o object module from
+ inside an Xmlrpc-c build tree.
+ */
+
+ dumpValue("", result.cValueP);
+}
+
+
+
+static list<string>
+parseWordList(string const& wordString) {
+
+ list<string> retval;
+
+ unsigned int pos;
+
+ pos = 0;
+
+ while (pos < wordString.length()) {
+ pos = wordString.find_first_not_of(' ', pos);
+
+ if (pos < wordString.length()) {
+ unsigned int const end = wordString.find_first_of(' ', pos);
+
+ retval.push_back(wordString.substr(pos, end - pos));
+
+ pos = end;
+ }
+ }
+ return retval;
+}
+
+
+
+static void
+parseCommand(string const& cmd,
+ string * const methodNameP,
+ vector<string> * const paramListP) {
+
+ list<string> const wordList(parseWordList(cmd));
+
+ list<string>::const_iterator cmdWordP;
+
+ cmdWordP = wordList.begin();
+
+ if (cmdWordP == wordList.end())
+ throwf("Command '%s' does not have a method name", cmd.c_str());
+ else {
+ *methodNameP = *cmdWordP++;
+
+ *paramListP = vector<string>(); // Start empty
+
+ while (cmdWordP != wordList.end())
+ paramListP->push_back(*cmdWordP++);
+ }
+}
+
+
+
+static void
+doCommand(client_xml * const clientP,
+ string const& methodName,
+ vector<string> const& paramArgs) {
+
+ value result;
+
+ callWithClient(clientP, methodName, paramListFromParamArgs(paramArgs),
+ &result);
+
+ try {
+ dumpResult(result);
+ } catch(exception const& e) {
+ throwf("Error showing result after RPC completed normally. %s",
+ e.what());
+ }
+}
+
+
+
+static void
+getCommand(string * const cmdP,
+ bool* const eofP) {
+
+ const char * cmd;
+
+ cmd = readline(">");
+
+ *eofP = (cmd == NULL);
+
+ if (cmd != NULL) {
+ *cmdP = string(cmd);
+
+ free(const_cast<char *>(cmd));
+ }
+}
+
+
+
+static void
+doInteractive(client_xml * const clientP) {
+
+ bool quitRequested;
+
+ quitRequested = false;
+
+ while (!quitRequested) {
+ string cmd;
+ bool eof;
+
+ getCommand(&cmd, &eof);
+
+ if (eof) {
+ quitRequested = true;
+ cout << endl;
+ } else {
+ try {
+ string methodName;
+ vector<string> paramArgs;
+
+ parseCommand(cmd, &methodName, ¶mArgs);
+
+ doCommand(clientP, methodName, paramArgs);
+ } catch (exception const& e) {
+ cout << "Command failed. " << e.what() << endl;
+ }
+ }
+ }
+}
+
+
+
+int
+main(int const argc,
+ const char ** const argv) {
+
+ try {
+ cmdlineInfo cmdline(argc, argv);
+
+ signal(SIGPIPE, SIG_IGN);
+
+ clientXmlTransport_pstream myTransport(
+ clientXmlTransport_pstream::constrOpt()
+ .fd(cmdline.serverfd));
+
+ client_xml myClient(&myTransport);
+
+ if (cmdline.interactive) {
+ if (cmdline.serverfd == STDIN_FILENO ||
+ cmdline.serverfd == STDOUT_FILENO)
+ throwf("Can't use Stdin or Stdout for the server fd when "
+ "running interactively.");
+ doInteractive(&myClient);
+ } else
+ doCommand(&myClient, cmdline.methodName, cmdline.params);
+
+ } catch (exception const& e) {
+ cerr << "Failed. " << e.what() << endl;
+ } catch (...) {
+ cerr << "Code threw unrecognized exception" << endl;
+ abort();
+ }
+ return 0;
+}
Added: freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_pstream/xmlrpc_pstream.html
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_pstream/xmlrpc_pstream.html Fri May 23 16:56:24 2008
@@ -0,0 +1,200 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
+<title>Xmlrpc_pstream User Manual</title>
+<body>
+
+<p><b>xmlrpc_pstream</b> makes a pseudo-XML-RPC remote procedure call
+(RPC) and displays the response. <b>xmlrpc_pstream</b> runs a
+pseudo-XML-RPC client.
+
+<p>The difference from true XML-RPC is that <b>xmlrpc_pstream</b>
+uses XML-RPC For C/C++'s "pstream" transport mechanism instead
+of HTTP. The pstream transport uses a simple TCP connection.
+
+<h2>Examples</h2>
+
+<pre>
+<tt>
+
+ $ socketexec -connect \
+ -remote_host=localhost -remote_port=8080 --filedes=3 -- \
+ xmlrpc_pstream --serverfd=3
+
+ >sample.add i/3 i/5
+
+ Result:
+ Integer: 8
+</tt>
+</pre>
+<pre>
+<tt>
+
+ $ socketexec -connect \
+ -remote_host=localhost -remote_port=8080 --filedes=3 -- \
+ xmlrpc_pstream sample.add i/3 i/5
+
+ Result:
+ Integer: 8
+</tt>
+</pre>
+
+<p>See the manual for the program <b>xmlrpc</b> for more examples;
+you specify the RPC arguments the same way.
+
+<h2>Overview</h2>
+<p>
+<b>xmlrpc_pstream</b>
+
+[<b>-serverfd=</b><i>integer</i>]
+[<i>methodName</i> [<i>parameter</i> ...]]
+
+<p><i>parameter</i>:
+
+<p>
+<b>i/</b><i>integer</i> |
+<b>s/</b><i>string</i> |
+<b>h/</b><i>hexstring</i> |
+<b>b/</b>{<b>true</b>|<b>false</b>|<b>t</b>|<b>f</b>} |
+<b>d/</b><i>realnum</i> |
+<b>n/</b> |
+<b><i>string</i></b>
+
+
+<P>Minimum unique abbreviation of option is acceptable. You may use double
+hyphens instead of single hyphen to denote options. You may use white
+space in place of the equals sign to separate an option name from its value.
+
+
+<h2>Description</h2>
+
+<p>This program is mainly useful for debugging and learning about
+XML-RPC servers. XML-RPC is such that the RPCs normally need to be made
+by a program rather than a person to be of use.
+
+<p>You supply a TCP connection to the server as an open file descriptor.
+<b>socketexec</b> is a good way to create that socket and pass it to
+<b>xmlrpc_pstream</b>.
+
+<p>You run <b>xmlrpc_pstream</b> in one of two modes: interactive and
+single RPC.
+
+<p>In interactive mode, which you select by giving no arguments to the
+program, <b>xmlrpc_pstream</b> prompts you for RPCs using the Readline
+library. You type in an RPC description and <b>xmlrpc_pstream</b>
+executes it, then asks you for another. This continues until you close
+the readline session (usually by typing Control-D). Then, the program
+exits, which causes the server file descriptor to close, which causes the
+client-server TCP connection to close, which means the client-server
+XML-RPC connection terminates.
+
+<p>In single RPC mode, you give the RPC information as arguments to
+the program. <b>xmlrpc_pstream</b> executes one RPC, then exits.
+But note that when you invoke <b>xmlrpc_pstream</b> with
+<b>socketexec</b> in single RPC mode, you can't exploit one of the
+main purposes of a pstream transport: it lets you establish an RPC
+session with the server. With the single RPC <b>socketexec</b>
+method, <b>socketexec</b> establishes a session with the server (by
+creating the TCP connection), then <b>xmlrpc_pstream</b> performs one
+RPC in that session, then the OS closes the session as
+<b>xmlrpc_pstream</b> exits (by virtue of closing the TCP socket).
+
+
+<h2>Arguments</h2>
+
+<p>There are no arguments in interactive mode. The fact that there are
+no arguments is what tells <b>xmlrpc_pstream</b> you want interactive mode.
+
+<p>For single RPC mode, the arguments are as follows.
+
+<dl>
+
+<dt><i>methodName</i>
+
+<dd>The name of the XML-RPC method you want to invoke.
+
+<dt><i>parameter</i> ...
+
+<dd>The list of parameters for the RPC. <b>xmlrpc_pstream</b> turns
+each of these arguments into an XML-RPC parameter, in the order given.
+You may specify no parameters if you like.
+
+<p>You specify the data type of the parameter with a prefix ending in
+a slash. Example: <b>i/5</b>. Here, the "i" signifies an
+integer data type. "5" is the value.
+
+<p><b>xmlrpc</b> is capable of only a subset of the
+possible XML-RPC types, as follows by prefix:
+
+<dl>
+<dt>i/
+<dd>integer (<i4>) (32 bit)
+
+<dt>s/
+<dd>string (<string>)
+
+<dt>h/
+<dd>byte string (<base64>). Specify the value in hexadecimal.
+
+<dt>b/
+<dd>boolean (<boolean>). Specify the value as "true" or
+"t" for true; "false" or "f" for false.
+
+<dt>d/
+<dd>double (<double>) (i.e. real number)
+
+<dt>n/
+<dd>nil (<nil>)
+
+<dt>I/
+<dd>64 bit integer (<i8>)
+
+</dl>
+
+<p>As a shortcut, if you don't specify a prefix (i.e. your argument does
+not contain a slash), <b>xmlrpc_pstream</b> assumes string data type.
+
+</dl>
+
+
+<h2>Options</h2>
+
+<dl>
+<dt><b>-serverfd=</b><i>integer</i>
+
+<dd>This identifies the client-server connection (and thus identifies the
+server). It is the file descriptor (an integer file handle) of the socket
+associated with an established TCP connection that you set up before
+invoking <b>xmlrpc_pstream</b>.
+
+<p>In interactive mode, don't use 0 or 1, because those are Standard Input
+and Standard Output and are used to communicate with you. 2 is a bad choice
+any time, because that is Standard Error and <b>xmlrpc_pstream</b> uses
+that to communicate with you.
+
+<p><b>socketexec</b> is a good way to create the required socket. Use
+the <b>socketexec</b>'s <b>-filedes</b> option to tell it what file descriptor
+to use for the socket, then use that same value on <b>xmlrpc_pstream</b>'s
+<b>-serverfd</b> option.
+
+<P>The default is 3.
+
+</dl>
+
+<h2>Interactive Commands</h2>
+
+<p>Example:
+
+<kbd>
+> sample_add i/5 i/7
+</kbd>
+
+<p>In interactive mode, <b>xmlrpc_pstream</b> prompts you for RPC calls
+with the prompt ">".
+
+<p>At the prompt, type a series of words, delimited by one or more blanks.
+
+<p>The first word is the XML-RPC method name.
+
+<p>The remaining words are the parameters of the XML-RPC method, in the
+same form as the <b>xmlrpc_pstream</b> arguments for single RPC mode.
+
+</body>
Modified: freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_transport/Makefile
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_transport/Makefile (original)
+++ freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_transport/Makefile Fri May 23 16:56:24 2008
@@ -1,35 +1,59 @@
-ifeq ($(SRCDIR)x,x)
-SRCDIR = $(CURDIR)/../..
-BUILDDIR = $(SRCDIR)
+ifeq ($(SRCDIR),)
+ updir = $(shell echo $(dir $(1)) | sed 's/.$$//')
+ TOOLSDIR := $(call updir,$(CURDIR))
+ SRCDIR := $(call updir,$(TOOLSDIR))
+ BLDDIR := $(SRCDIR)
endif
+SUBDIR := tools/xmlrpc_transport
-all: xmlrpc_transport
+default: all
-include $(BUILDDIR)/Makefile.config
+include $(BLDDIR)/config.mk
PROGRAMS_TO_INSTALL = xmlrpc_transport
-include ../Makefile.common
+include $(SRCDIR)/tools/common.mk
-INCLUDES = -I$(SRCDIR) -I$(SRCDIR)/include -I$(SRCDIR)/lib/util/include
+INCLUDES = \
+ -I$(BLDDIR) \
+ -I$(BLDDIR)/include \
+ -I$(SRCDIR)/include \
+ -I$(SRCDIR)/lib/util/include
CFLAGS = $(CFLAGS_COMMON) $(INCLUDES) $(CFLAGS_PERSONAL) $(CADD)
-LDFLAGS = $(CLIENT_LDFLAGS) $(LADD)
+LDFLAGS = $(LADD)
+
+all: xmlrpc_transport
+
+UTIL_OBJS = \
+ casprintf.o \
+ cmdline_parser.o \
+ getoptx.o \
+ stripcaseeq.o \
+ string_parser.o \
-UTIL_OBJS = cmdline_parser.o getoptx.o
UTILS = $(UTIL_OBJS:%=$(UTIL_DIR)/%)
-xmlrpc_transport:%:%.o $(LIBXMLRPC_CLIENT) $(LIBXMLRPC) $(LIBXML) $(UTILS)
- $(LIBTOOL) --mode=link $(CCLD) -o $@ $(LDFLAGS) $^
+# These are the Libtool .la files. We use them only for make dependencies.
+# We'd like to use these in the link rule, by using libtool --link, but
+# Libtool adds -l options to the link to cover the dependencies that are
+# recorded inside the shared libraries. And it doesn't add the necessary
+# -L options (it can't), so we end up with a messy mixture of the two
+# forms of specifying libraries.
+
+LIBS = $(LIBXMLRPC_CLIENT) $(LIBXMLRPC) $(LIBXMLRPC_XML) $(LIBXMLRPC_UTIL)
+
+xmlrpc_transport:%:%.o $(LIBS) $(UTILS)
+ $(CCLD) -o $@ $(LDFLAGS) $< $(CLIENT_LDLIBS) $(UTILS)
%.o:%.c
- $(LIBTOOL) --mode=compile $(CC) -c $(CFLAGS) $<
+ $(CC) -c $(CFLAGS) $<
-*.c: config.h
+# This common.mk dependency makes sure the symlinks get built before
+# this make file is used for anything.
-config.h:
- $(LN_S) $(BUILDDIR)/xmlrpc_config.h $@
+$(SRCDIR)/tools/common.mk: srcdir blddir
include Makefile.depend
@@ -38,7 +62,7 @@
.PHONY: clean
clean: clean-common
- rm -f xmlrpc config.h
+ rm -f xmlrpc_transport config.h
.PHONY: distclean
distclean: clean distclean-common
Modified: freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_transport/xmlrpc_transport.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_transport/xmlrpc_transport.c (original)
+++ freeswitch/trunk/libs/xmlrpc-c/tools/xmlrpc_transport/xmlrpc_transport.c Fri May 23 16:56:24 2008
@@ -8,7 +8,7 @@
#include <stdio.h>
#include <string.h>
-#include "config.h" /* information about this build environment */
+#include "xmlrpc_config.h" /* information about this build environment */
#include "casprintf.h"
#include "mallocvar.h"
#include "cmdline_parser.h"
Added: freeswitch/trunk/libs/xmlrpc-c/transport_config.make
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/transport_config.make Fri May 23 16:56:24 2008
@@ -0,0 +1,39 @@
+# -*-makefile-*- <-- an Emacs control
+
+
+# The make variables herein come from config.mk, which is included
+# by the make file that includes us.
+
+transport_config.h: $(BLDDIR)/config.mk
+ rm -f $@
+ echo '/* This file was generated by a make rule */' >>$@
+ifeq ($(MUST_BUILD_WININET_CLIENT),yes)
+ echo '#define MUST_BUILD_WININET_CLIENT 1' >>$@
+else
+ echo '#define MUST_BUILD_WININET_CLIENT 0' >>$@
+endif
+ifeq ($(MUST_BUILD_CURL_CLIENT),yes)
+ echo '#define MUST_BUILD_CURL_CLIENT 1' >>$@
+else
+ echo '#define MUST_BUILD_CURL_CLIENT 0' >>$@
+endif
+ifeq ($(MUST_BUILD_LIBWWW_CLIENT),yes)
+ echo '#define MUST_BUILD_LIBWWW_CLIENT 1' >>$@
+else
+ echo '#define MUST_BUILD_LIBWWW_CLIENT 0' >>$@
+endif
+ echo "static const char * const XMLRPC_DEFAULT_TRANSPORT =" >>$@
+ifeq ($(MUST_BUILD_LIBWWW_CLIENT),yes)
+ echo '"libwww";' >>$@
+else
+ ifeq ($(MUST_BUILD_CURL_CLIENT),yes)
+ echo '"curl";' >>$@
+ else
+ ifeq ($(MUST_BUILD_WININET_CLIENT),yes)
+ echo '"wininet";' >>$@
+ else
+ @echo 'ERROR: no client XML transport configured'; rm $@; false
+ endif
+ endif
+endif
+
Added: freeswitch/trunk/libs/xmlrpc-c/unix-common.make
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/unix-common.make Fri May 23 16:56:24 2008
@@ -0,0 +1,79 @@
+# -*-makefile-*- <-- an Emacs control
+
+# The including make file must define these make variables:
+#
+# SHARED_LIBS_TO_BUILD: List of the shared libraries that need to be
+# built -- just the basic library names. E.g. "libfoo libbar"
+#
+# SHARED_LIBS_TO_INSTALL: List of the shared libraries that need to be
+# installed -- just the basic library names. E.g. "libfoo libbar"
+#
+# SHLIB_SUFFIX: Shared library filename suffix, e.g. "so".
+#
+# MAJ: Library major version number, e.g. "3" in file name "libfoo.3.1"
+#
+# MIN: Library minor version number, e.g. "1" in file name "libfoo.3.1"
+#
+# LDFLAGS_SHLIB: linker (Ld) flags needed to link object files together into
+# a shared library. May use $(SONAME) for the soname of the library.
+# Include -lc if appropriate.
+#
+# LADD: Additional linker flags (normally set on the make command line).
+#
+# INSTALL_DATA: beginning of shell command to install a library file.
+#
+# DESTDIR: main installation directory
+#
+# LIBINST_DIR: directory in which to install libraries, relative to DESTDIR.
+#
+# LN_S: beginning of shell command to make symbolic link (e.g. "ln -s").
+#
+# CXXLD: beginning of shell command to link, e.g. "g++".
+
+# This make file defines these make variables that the including make file
+# can use:
+#
+# SHLIB_CMD: a command to build a shared library for C linkage
+# You can use this in a rule to build a shared library
+# SHLIBPP_CMD: Same, but for C++ linkage
+
+# Including make file must contain a rule to build each library file
+# (e.g. libfoo.3.1)
+
+# This make file provides these rules:
+#
+# install-shared-libraries: install all shared libraries and the necessary
+# symbolic links.
+
+# SONAME is to be referenced by $(LDFLAGS_SHLIB) in $(SHLIB_RULE)
+# SONAME is the name of the library file being built, with the minor
+# version number cut off. E.g. if we're building libfoo.so.1.2, SONAME
+# is libfoo.so.1 .
+SONAME = $(@:%.$(MIN)=%)
+
+SHLIB_CMD = $(CCLD) $(LDFLAGS_SHLIB) -o $@ $^ $(LADD)
+
+SHLIB_LE_TARGETS = $(call shliblefn, $(SHARED_LIBS_TO_BUILD))
+
+$(SHLIB_LE_TARGETS):%:%.$(MAJ).$(MIN)
+ rm -f $@
+ $(LN_S) $< $@
+
+.PHONY: $(SHLIB_INSTALL_TARGETS)
+.PHONY: install-shared-libraries
+
+SHLIB_INSTALL_TARGETS = $(SHARED_LIBS_TO_INSTALL:%=%/install)
+
+#SHLIB_INSTALL_TARGETS is like "libfoo/install libbar/install"
+
+install-shared-libraries: $(SHLIB_INSTALL_TARGETS)
+
+$(SHLIB_INSTALL_TARGETS):%/install:%.$(SHLIB_SUFFIX).$(MAJ).$(MIN)
+# $< is a library file name, e.g. libfoo.so.3.1 .
+ $(INSTALL_SHLIB) $< $(DESTDIR)$(LIBINST_DIR)/$<
+ cd $(DESTDIR)$(LIBINST_DIR); \
+ rm -f $(<:%.$(MIN)=%); \
+ $(LN_S) $< $(<:%.$(MIN)=%)
+ cd $(DESTDIR)$(LIBINST_DIR); \
+ rm -f $(<:%.$(MAJ).$(MIN)=%); \
+ $(LN_S) $(<:%.$(MIN)=%) $(<:%.$(MAJ).$(MIN)=%)
Added: freeswitch/trunk/libs/xmlrpc-c/xmlrpc-c-config.main
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/xmlrpc-c-config.main Fri May 23 16:56:24 2008
@@ -0,0 +1,183 @@
+usage="Usage: xmlrpc-c-config <feature> ... <option> ...
+
+The features are:
+ c++ legacy C++ wrapper API
+ c++2 modern C++ API
+ client client functions
+ cgi-server CGI-based server functions
+ abyss-server ABYSS-based server functions
+ pstream-server pstream-based server functions
+ server-util basic server functions (implied by *-server)
+
+Options are:
+ --version The version number of the package
+ --features List all features (aka modules) currently installed
+ --cflags C compiler flags to use when '#include'ing package headers
+ --libs Libraries and flags to use when linking programs normally
+ --ldadd Libraries to use with automake
+ --ldflags Flags to use with automake & libtool
+ --prefix The prefix under which the package was installed
+"
+
+if test $# -eq 0; then
+ echo "You must specify at least one option."
+ echo "${usage}" 1>&2
+ exit 1
+fi
+
+if test "${ENABLE_LIBXML2_BACKEND}" = "yes"; then
+ LIBXML=`xml2-config --libs`
+else
+ LIBXML="-lxmlrpc_xmlparse -lxmlrpc_xmltok"
+fi
+
+needCpp=no
+
+the_libdirs=
+the_rpath=
+the_wl_rpath=
+cpp_libs=
+# It's important that packetsocket lib go after client, server libs
+packetsocket_lib=
+
+# If Xmlrpc-c libraries are installed in the standard linker search
+# path on this system, you should remove the following line:
+
+the_libdirs="-L$LIBINST_DIR $the_libdirs"
+
+the_libs="-lxmlrpc -lxmlrpc_util ${LIBXML}"
+the_rpath="-R$LIBINST_DIR $the_rpath"
+the_wl_rpath="-Wl,-rpath,$LIBINST_DIR $the_wl_rpath"
+
+cflags=
+# If Xmlrpc-c library interface header files are installed in the standard
+# compiler search path on this system, you should remove the following line:
+cflags="-I$HEADERINST_DIR $cflags"
+
+while test $# -gt 0; do
+ case $1 in
+ c++)
+ the_libs="-lxmlrpc_cpp $the_libs"
+
+ # Unfortunately, there is just one legacy CPP library for
+ # everything, and it needs all the C libraries -- base, client,
+ # and server. So all legacy C++ programs get linked with client
+ # and server libraries, whether they need them or not.
+
+ the_libs="-lxmlrpc_server_abyss $the_libs"
+ the_libs="-lxmlrpc_server $the_libs"
+ the_libs="-lxmlrpc_client $the_libs"
+ ;;
+ c++2)
+ needCpp=yes
+ the_libs="-lxmlrpc++ $the_libs"
+ ;;
+ server-util)
+ the_libs="-lxmlrpc_server $the_libs"
+ ;;
+ cgi-server)
+ the_libs="-lxmlrpc_server $the_libs"
+ the_libs="-lxmlrpc_server_cgi $the_libs"
+ ;;
+ abyss-server)
+ if test "${ENABLE_ABYSS_THREADS}" = "yes"; then
+ the_libs="-lpthread $the_libs"
+ fi
+ the_libs="${LSOCKET} $the_libs"
+ the_libs="-lxmlrpc_abyss $the_libs"
+ the_libs="-lxmlrpc_server $the_libs"
+ the_libs="-lxmlrpc_server_abyss $the_libs"
+ if test "${needCpp}" = "yes"; then
+ the_libs="-lxmlrpc_server++ $the_libs"
+ the_libs="-lxmlrpc_server_abyss++ $the_libs"
+ fi
+ ;;
+ pstream-server)
+ if test "${needCpp}" = "no"; then
+ echo "You must specify the 'c++2' feature before 'pstream-server'."
+ echo "Pstream server facilities are available only in a C++ version."
+ exit 10
+ fi
+ the_libs="${LSOCKET} $the_libs"
+ the_libs="-lxmlrpc_server $the_libs"
+ the_libs="-lxmlrpc_server++ $the_libs"
+ the_libs="-lxmlrpc_server_pstream++ $the_libs"
+ packetsocket_lib="-lxmlrpc_packetsocket"
+ ;;
+ client|libwww-client)
+ # libwww-client is for backward compatibility
+ the_libs="-lxmlrpc_client $the_libs"
+
+ if test "${MUST_BUILD_WININET_CLIENT}" = "yes"; then
+ the_libs="$the_libs $WININET_LDADD"
+ the_rpath="$WININET_RPATH $the_rpath"
+ the_wl_rpath="$WININET_WL_RPATH $the_wl_rpath"
+ fi
+ if test "${MUST_BUILD_CURL_CLIENT}" = "yes"; then
+ the_libs="$the_libs $CURL_LDADD"
+ the_rpath="$CURL_RPATH $the_rpath"
+ the_wl_rpath="$CURL_WL_RPATH $the_wl_rpath"
+ fi
+ if test "${MUST_BUILD_LIBWWW_CLIENT}" = "yes"; then
+ the_libs="$the_libs $LIBWWW_LDADD"
+ the_rpath="$LIBWWW_RPATH $the_rpath"
+ the_wl_rpath="$LIBWWW_WL_RPATH $the_wl_rpath"
+ fi
+ if test "${needCpp}" = "yes"; then
+ the_libs="-lxmlrpc_client++ $the_libs"
+ packetsocket_lib="-lxmlrpc_packetsocket"
+ fi
+ ;;
+ --version)
+ echo "$XMLRPC_MAJOR_RELEASE.$XMLRPC_MINOR_RELEASE.$XMLRPC_POINT_RELEASE"
+ ;;
+ --modules)
+ echo "$FEATURE_LIST"
+ ;;
+ --features)
+ echo "$FEATURE_LIST"
+ ;;
+ --cflags)
+ echo "$cflags"
+ ;;
+ --libs)
+ if test "$NEED_WL_RPATH" = "yes"; then
+ rpath=$the_wl_rpath
+ elif test "$NEED_RPATH" = "yes"; then
+ rpath=$the_rpath
+ else
+ rpath=
+ fi
+
+ echo "$the_libdirs $rpath $the_libs $packetsocket_lib"
+ ;;
+ --ldadd)
+ echo "$the_libdirs $the_libs $packetsocket_lib"
+ ;;
+ --ldflags)
+ echo "$the_rpath"
+ ;;
+ --prefix)
+ echo "$PREFIX"
+ ;;
+ --exec-prefix)
+ # This is just here for compatibility. In a conventional autoconf
+ # system, "prefix" is the prefix specified at 'configure' time and
+ # "exec_prefix" is the prefix as overridden at 'make install' time.
+ # The only reason I can think that this program historically had both
+ # is that the author didn't understand that.
+ echo "$PREFIX"
+ ;;
+ --help)
+ echo "${usage}" 1>&2
+ ;;
+ *)
+ echo "Unrecognized token '$1'"
+ echo "${usage}" 1>&2
+ exit 1
+ ;;
+ esac
+ shift
+done
+
+exit 0
Added: freeswitch/trunk/libs/xmlrpc-c/xmlrpc-c-config.test.main
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/xmlrpc-c-config.test.main Fri May 23 16:56:24 2008
@@ -0,0 +1,144 @@
+# This is like 'xmlrpc-c-config', but for testing Xmlrpc-c from its build
+# directory instead of for an installed instance of Xmlrpc-c.
+#
+# For example, the make file in the src/test/ directory uses this program
+# to link the test programs with the Xmlrpc-c libraries in the build
+# directory. A real application program would instead use xmlrpc-c-config
+# and get the Xmlrpc-c libraries from their installed home.
+
+if test $# -eq 0; then
+ echo "You need to specify arguments"
+ exit 1
+fi
+
+the_libs=
+the_includes=
+the_rpath=
+the_wl_rpath=
+sopath=
+# It's important that packetsocket lib go after client, server libs
+packetsocket_lib=
+
+if test "${ENABLE_LIBXML2_BACKEND}" = "yes"; then
+ LIBXML=`xml2-config --libs`
+else
+ LIBXML="${BLDDIR}/lib/expat/xmlparse/libxmlrpc_xmlparse.a"
+ sopath="${BLDDIR}/lib/expat/xmlparse:$sopath"
+ LIBXML="${LIBXML} ${BLDDIR}/lib/expat/xmltok/libxmlrpc_xmltok.a"
+ sopath="${BLDDIR}/lib/expat/xmltok:$sopath"
+fi
+
+needCpp=no
+
+LIBXMLRPC="${BLDDIR}/src/libxmlrpc.a"
+LIBXMLRPC_UTIL="${BLDDIR}/lib/libutil/libxmlrpc_util.a"
+
+the_libs="${LIBXMLRPC} ${LIBXMLRPC_UTIL} ${LIBXML} $the_libs"
+the_includes="-I${BLDDIR}/include -I${ABS_SRCDIR}/include $the_includes"
+sopath="${BLDDIR}/src:$sopath"
+
+while test $# -gt 0; do
+ case $1 in
+ c++)
+ # Unfortunately, there is just one legacy CPP library for
+ # everything, and it needs all the C libraries -- base, client,
+ # and server. So all legacy C++ programs get linked with client
+ # and server libraries, whether they need them or not.
+
+ the_libs="${BLDDIR}/src/libxmlrpc_server.a $the_libs"
+ the_libs="${BLDDIR}/src/libxmlrpc_server_abyss.a $the_libs"
+ the_libs="${BLDDIR}/src/libxmlrpc_client.a $the_libs"
+ the_libs="${BLDDIR}/src/cpp/libxmlrpc_cpp.a $the_libs"
+ ;;
+ c++2)
+ needCpp=yes
+ the_libs="${BLDDIR}/src/cpp/libxmlrpc++.a $the_libs"
+ ;;
+ server-util)
+ the_libs="${BLDDIR}/src/libxmlrpc_server.a $the_libs"
+ ;;
+ cgi-server)
+ the_libs="${BLDDIR}/src/libxmlrpc_server.a $the_libs"
+ the_libs="${BLDDIR}/src/libxmlrpc_server_cgi.a $the_libs"
+ ;;
+ abyss-server)
+ if test "${ENABLE_ABYSS_THREADS}" = "yes"; then
+ the_libs="-lpthread $the_libs"
+ fi
+ the_libs="${LSOCKET} $the_libs"
+ the_libs="${BLDDIR}/lib/abyss/src/libxmlrpc_abyss.a $the_libs"
+ the_libs="${BLDDIR}/src/libxmlrpc_server.a $the_libs"
+ the_libs="${BLDDIR}/src/libxmlrpc_server_abyss.a $the_libs"
+ if test "${needCpp}" = "yes"; then
+ the_libs="${BLDDIR}/src/cpp/libxmlrpc_server++.a $the_libs"
+ the_libs="${BLDDIR}/src/cpp/libxmlrpc_server_abyss++.a $the_libs"
+ fi
+ sopath="${BLDDIR}/lib/abyss/src:$sopath"
+ ;;
+ pstream-server)
+ the_libs="${LSOCKET} $the_libs"
+ the_libs="${BLDDIR}/src/cpp/libxmlrpc_server_pstream++.a $the_libs"
+ the_libs="${BLDDIR}/src/libxmlrpc_server.a $the_libs"
+ the_libs="${BLDDIR}/src/cpp/libxmlrpc_server++.a $the_libs"
+ the_libs="${BLDDIR}/src/cpp/libxmlrpc_server_pstream++.a $the_libs"
+ packetsocket_lib="${BLDDIR}/src/cpp/libxmlrpc_packetsocket.a"
+ ;;
+ client)
+ the_libs="${BLDDIR}/src/libxmlrpc_client.a $the_libs"
+ if test "${MUST_BUILD_WININET_CLIENT}" = "yes"; then
+ the_libs="$the_libs $WININET_LDADD"
+ the_rpath="$WININET_RPATH $the_rpath"
+ the_wl_rpath="$WININET_WL_RPATH $the_wl_rpath"
+ fi
+ if test "${MUST_BUILD_CURL_CLIENT}" = "yes"; then
+ the_libs="$the_libs $CURL_LDADD"
+ the_rpath="$CURL_RPATH $the_rpath"
+ the_wl_rpath="$CURL_WL_RPATH $the_wl_rpath"
+ fi
+ if test "${MUST_BUILD_LIBWWW_CLIENT}" = "yes"; then
+ the_libs="$the_libs $LIBWWW_LDADD"
+ the_rpath="$LIBWWW_RPATH $the_rpath"
+ the_wl_rpath="$LIBWWW_WL_RPATH $the_wl_rpath"
+ fi
+ if test "${needCpp}" = "yes"; then
+ the_libs="${BLDDIR}/src/cpp/libxmlrpc_client++.a $the_libs"
+ packetsocket_lib="${BLDDIR}/src/cpp/libxmlrpc_packetsocket.a"
+ fi
+ ;;
+ --version)
+ echo "$XMLRPC_MAJOR_RELEASE.$XMLRPC_MINOR_RELEASE.$XMLRPC_POINT_RELEASE"
+ ;;
+ --modules)
+ echo "$FEATURE_LIST"
+ ;;
+ --features)
+ echo "$FEATURE_LIST"
+ ;;
+ --cflags)
+ echo "$the_includes"
+ ;;
+ --libs)
+ echo "$the_libdirs $the_libs $packetsocket_lib $the_wl_rpath"
+ ;;
+ --ldadd)
+ echo "$the_libdirs $the_libs $packetsocket_lib"
+ ;;
+ --ldflags)
+ echo "$the_rpath"
+ ;;
+ --sopath)
+ echo "$sopath"
+ ;;
+ --help)
+ echo "See the real xmlrpc-c-config program" 1>&2
+ ;;
+ *)
+ echo "Unrecognized token '$1'"
+ echo "${usage}" 1>&2
+ exit 1
+ ;;
+ esac
+ shift
+done
+
+exit 0
Added: freeswitch/trunk/libs/xmlrpc-c/xmlrpc_amconfig.h.in
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/xmlrpc-c/xmlrpc_amconfig.h.in Fri May 23 16:56:24 2008
@@ -0,0 +1,31 @@
+/* xmlrpc_amconfig.h is generated by 'configure' from the template
+ xmlrpc_amconfig.h.in, by virtue of the AM_CONFIG_HEADER() macro in
+ configure.in.
+
+ In the future, we plan to eliminate this file, because it is a special
+ tool that requires extra learning. Instead, we will just put logic
+ directly in configure.in like that for wchar.h, etc.
+*/
+
+/* The following are related to AC_CHECK_FUNCS macro calls in
+ configure.in
+*/
+
+#undef HAVE_SETGROUPS
+#undef HAVE_ASPRINTF
+#undef HAVE_SETENV
+#undef HAVE_PSELECT
+#undef HAVE_WCSNCMP
+#undef HAVE_GETTIMEOFDAY
+#undef HAVE_LOCALTIME_R
+#undef HAVE_GMTIME_R
+#undef HAVE_STRCASECMP
+#undef HAVE_STRICMP
+#undef HAVE__STRICMP
+
+
+/* Define if you have the socket library (-lsocket). */
+#undef HAVE_LIBSOCKET
+
+/* Name of package */
+#undef PACKAGE
Modified: freeswitch/trunk/libs/xmlrpc-c/xmlrpc_config.h.in
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/xmlrpc_config.h.in (original)
+++ freeswitch/trunk/libs/xmlrpc-c/xmlrpc_config.h.in Fri May 23 16:56:24 2008
@@ -1,5 +1,19 @@
/* xmlrpc_config.h is generated from xmlrpc_config.h.in by 'configure'.
+ The purpose of this file is to define stuff particular to the build
+ environment being used to build Xmlrpc-c. Xmlrpc-c source files can
+ #include this file and have build-environment-independent source code.
+
+ A major goal of this file is to reduce conditional compilation in
+ the other source files as much as possible. Even more, we want to avoid
+ having to generate source code particular to a build environment
+ except in this file.
+
+ This file is NOT meant to be used by any code outside of the
+ Xmlrpc-c source tree. There is a similar file that gets installed
+ as <xmlrpc-c/config.h> that performs the same function for Xmlrpc-c
+ interface header files that get compiled as part of a user's program.
+
This file just uses plain AC_SUBST substitution, the same as
Makefile.config. Wherever you see @XXX@, that gets replaced by the
value of 'configure' variable XXX.
@@ -9,28 +23,64 @@
"false" and some problem with the code.
*/
+#ifndef XMLRPC_CONFIG_H_INCLUDED
+#define XMLRPC_CONFIG_H_INCLUDED
/* We hope to replace xmlrpc_amconfig.h some day with something that
doesn't require a whole special set of software to build, to make
- xmlrpc-c approachable by dumber developers.
+ Xmlrpc-c approachable by dumber developers.
*/
#include "xmlrpc_amconfig.h"
+#ifndef HAVE_SETGROUPS
+#define HAVE_SETGROUPS 0
+#endif
+#ifndef HAVE_ASPRINTF
+#define HAVE_ASPRINTF 0
+#endif
+#ifndef HAVE_SETENV
+#define HAVE_SETENV 0
+#endif
+#ifndef HAVE_PSELECT
+#define HAVE_PSELECT 0
+#endif
+#ifndef HAVE_WCSNCMP
+#define HAVE_WCSNCMP 1
+#endif
+#ifndef HAVE_GETTIMEOFDAY
+#define HAVE_GETTIMEOFDAY 0
+#endif
+#ifndef HAVE_LOCALTIME_R
+#define HAVE_LOCALTIME_R 0
+#endif
+#ifndef HAVE_GMTIME_R
+#define HAVE_GMTIME_R 0
+#endif
+#ifndef HAVE_STRCASECMP
+#define HAVE_STRCASECMP 0
+#endif
+#ifndef HAVE_STRICMP
+#define HAVE_STRICMP 0
+#endif
+#ifndef HAVE__STRICMP
+#define HAVE__STRICMP 0
+#endif
+
+#define HAVE_WCHAR_H @HAVE_WCHAR_H_DEFINE@
+#define HAVE_SYS_FILIO_H @HAVE_SYS_FILIO_H_DEFINE@
+#define HAVE_SYS_IOCTL_H @HAVE_SYS_IOCTL_H_DEFINE@
#define VA_LIST_IS_ARRAY @VA_LIST_IS_ARRAY_DEFINE@
#define HAVE_LIBWWW_SSL @HAVE_LIBWWW_SSL_DEFINE@
+/* Used to mark an unused function parameter */
#define ATTR_UNUSED @ATTR_UNUSED@
-#define HAVE_UNICODE_WCHAR @HAVE_UNICODE_WCHAR_DEFINE@
-/* This is a hack in the name of stability -- saves modifying a lot of code */
-#if !HAVE_UNICODE_WCHAR
-#undef HAVE_UNICODE_WCHAR
-#endif
-
#define DIRECTORY_SEPARATOR "@DIRECTORY_SEPARATOR@"
+#define HAVE_UNICODE_WCHAR HAVE_WCHAR_H
+
/* Xmlrpc-c code uses __inline__ to declare functions that should
be compiled as inline code. GNU C recognizes the __inline__ keyword.
Others recognize 'inline' or '__inline' or nothing at all to say
@@ -41,10 +91,60 @@
*/
#if (!defined(__GNUC__))
#if (!defined(__inline__))
- #if (defined(__sgi) || defined(_AIX))
+ #if (defined(__sgi) || defined(_AIX) || defined(_MSC_VER))
#define __inline__ __inline
#else
#define __inline__
#endif
#endif
#endif
+
+/* MSVCRT means we're using the Microsoft Visual C++ runtime library */
+
+#ifdef _MSC_VER
+/* The compiler is Microsoft Visual C++. */
+ #define MSVCRT _MSC_VER
+#else
+ #define MSVCRT 0
+#endif
+
+#if MSVCRT
+ /* The MSVC runtime library _does_ have a 'struct timeval', but it is
+ part of the Winsock interface (along with select(), which is probably
+ its intended use), so isn't intended for use for general timekeeping.
+ */
+ #define HAVE_TIMEVAL 0
+ #define HAVE_TIMESPEC 0
+#else
+ #define HAVE_TIMEVAL 1
+ /* timespec is Posix.1b. If we need to work on a non-Posix.1b non-Windows
+ system, we'll have to figure out how to make Configure determine this.
+ */
+ #define HAVE_TIMESPEC 1
+#endif
+
+#if MSVCRT
+ #define XMLRPC_VSNPRINTF _vsnprintf
+#else
+ #define XMLRPC_VSNPRINTF vsnprintf
+#endif
+
+#if defined(_MSC_VER)
+/* Starting with MSVC 8, the runtime library defines various POSIX functions
+ such as strdup() whose names violate the ISO C standard (the standard
+ says the strXXX names are reserved for the standard), but warns you of
+ the standards violation. That warning is 4996, along with other warnings
+ that tell you you're using a function that Microsoft thinks you
+ shouldn't.
+
+ Well, POSIX is more important than that element of ISO C, so we disable
+ that warning.
+
+ FYI, msvcrt also defines _strdup(), etc, which doesn't violate the
+ naming standard. But since other environments don't define _strdup(),
+ we can't use it in portable code.
+*/
+#pragma warning(disable:4996)
+#endif
+
+#endif
More information about the Freeswitch-svn
mailing list