.gitignore | 71 +- Freeswitch.2008.sln | 142 +- Freeswitch.2010.sln | 202 +- configure.in | 33 +- libs/.gitignore | 8 +- .../win32/apr-util/libaprutil.2010.vcxproj.filters | 7 +- libs/win32/xmlrpc-c/abyss.2008.vcproj | 410 +++ libs/win32/xmlrpc-c/abyss.2010.vcxproj | 197 ++ libs/win32/xmlrpc-c/abyss.2010.vcxproj.filters | 69 + libs/win32/xmlrpc-c/gennmtab.2008.vcproj | 404 +++ libs/win32/xmlrpc-c/gennmtab.2010.vcxproj | 304 ++ libs/win32/xmlrpc-c/xmlparse.2008.vcproj | 394 +++ libs/win32/xmlrpc-c/xmlparse.2010.vcxproj | 254 ++ libs/win32/xmlrpc-c/xmlrpc.2008.vcproj | 490 ++++ libs/win32/xmlrpc-c/xmlrpc.2010.vcxproj | 240 ++ libs/win32/xmlrpc-c/xmlrpc.2010.vcxproj.filters | 125 + libs/win32/xmlrpc-c/xmltok.2008.vcproj | 378 +++ libs/win32/xmlrpc-c/xmltok.2010.vcxproj | 199 ++ libs/win32/xmlrpc-c/xmltok.2010.vcxproj.filters | 45 + libs/xmlrpc-c/.cvsignore | 18 - libs/xmlrpc-c/.update | 1 - libs/xmlrpc-c/GNUmakefile | 53 +- libs/xmlrpc-c/Makefile.common | 272 -- libs/xmlrpc-c/Makefile.config.in | 79 - libs/xmlrpc-c/Makefile.srcdir.in | 1 - libs/xmlrpc-c/Makefile.version | 11 - libs/xmlrpc-c/Windows/CleanWin32.bat | 73 +- libs/xmlrpc-c/Windows/ReadMeWin32.txt | 12 +- libs/xmlrpc-c/Windows/abyss.2008.vcproj | 1298 --------- libs/xmlrpc-c/Windows/abyss.2010.vcxproj | 437 --- libs/xmlrpc-c/Windows/abyss.2010.vcxproj.filters | 131 - libs/xmlrpc-c/Windows/cpptest.dsp | 9 +- libs/xmlrpc-c/Windows/curllink.h | 36 +- libs/xmlrpc-c/Windows/dll/cpptest.vcproj | 482 +++ libs/xmlrpc-c/Windows/dll/gennmtab.vcproj | 449 +++ libs/xmlrpc-c/Windows/dll/rpctest.vcproj | 574 ++++ .../Windows/dll/sample_add_asynch_client.vcproj | 443 +++ libs/xmlrpc-c/Windows/dll/sample_add_server.vcproj | 433 +++ .../dll/sample_add_server_w32httpsys.vcproj | 433 +++ .../Windows/dll/sample_add_sync_client.vcproj | 435 +++ .../xmlrpc-c/Windows/dll/sample_auth_client.vcproj | 435 +++ .../Windows/dll/tool_xmlrpc-transport.vcproj | 430 +++ libs/xmlrpc-c/Windows/dll/tool_xmlrpc.vcproj | 430 +++ libs/xmlrpc-c/Windows/dll/xmlrpc.sln | 327 +++ libs/xmlrpc-c/Windows/dll/xmlrpc.vcproj | 479 +++ libs/xmlrpc-c/Windows/dll/xmlrpc__.vcproj | 1296 +++++++++ libs/xmlrpc-c/Windows/dll/xmlrpc_abyss.vcproj | 1342 +++++++++ libs/xmlrpc-c/Windows/dll/xmlrpc_client.vcproj | 425 +++ libs/xmlrpc-c/Windows/dll/xmlrpc_server.vcproj | 413 +++ .../Windows/dll/xmlrpc_server_abyss.vcproj | 401 +++ libs/xmlrpc-c/Windows/dll/xmlrpc_server_cgi.vcproj | 401 +++ .../Windows/dll/xmlrpc_server_w32httpsys.vcproj | 405 +++ libs/xmlrpc-c/Windows/dll/xmlrpc_util.vcproj | 449 +++ libs/xmlrpc-c/Windows/dll/xmlrpc_xmlparse.vcproj | 417 +++ libs/xmlrpc-c/Windows/dll/xmlrpc_xmltok.vcproj | 483 +++ libs/xmlrpc-c/Windows/gennmtab.2008.vcproj | 242 -- libs/xmlrpc-c/Windows/mkvers.bat | 8 +- libs/xmlrpc-c/Windows/query_meerkat.dsp | 100 - libs/xmlrpc-c/Windows/rpctest.dsp | 8 + libs/xmlrpc-c/Windows/socketpair.cpp | 71 + libs/xmlrpc-c/Windows/transport_config.h | 13 - libs/xmlrpc-c/Windows/transport_config_win32.h | 26 +- libs/xmlrpc-c/Windows/win32_config.h | 4 + libs/xmlrpc-c/Windows/xmlparse.2008.vcproj | 387 --- libs/xmlrpc-c/Windows/xmlparse.2010.vcxproj | 198 -- libs/xmlrpc-c/Windows/xmlrpc-c/config.h | 38 - libs/xmlrpc-c/Windows/xmlrpc.2008.vcproj | 2042 ------------- libs/xmlrpc-c/Windows/xmlrpc.2010.vcxproj | 620 ---- libs/xmlrpc-c/Windows/xmlrpc.2010.vcxproj.filters | 287 -- libs/xmlrpc-c/Windows/xmlrpc.dsp | 12 + libs/xmlrpc-c/Windows/xmlrpc.dsw | 30 + libs/xmlrpc-c/Windows/xmlrpc_config.h | 158 - libs/xmlrpc-c/Windows/xmlrpc_win32_config.h | 69 +- libs/xmlrpc-c/Windows/xmlrpcclient.dsp | 106 + libs/xmlrpc-c/Windows/xmlrpccpp.dsp | 5 +- libs/xmlrpc-c/Windows/xmltok.2008.vcproj | 455 --- libs/xmlrpc-c/Windows/xmltok.2010.vcxproj | 213 -- libs/xmlrpc-c/Windows/xmltok.dsp | 4 +- libs/xmlrpc-c/common.mk | 130 +- libs/xmlrpc-c/conf/abyss_root/conf/abyss.conf | 56 - libs/xmlrpc-c/conf/abyss_root/conf/mime.types | 276 -- libs/xmlrpc-c/conf/abyss_root/htdocs/index.htm | 21 - libs/xmlrpc-c/config.mk.in | 97 +- libs/xmlrpc-c/configure.gnu | 4 - libs/xmlrpc-c/configure.in | 165 +- libs/xmlrpc-c/debian/README.Debian | 7 - libs/xmlrpc-c/debian/changelog | 22 - libs/xmlrpc-c/debian/control | 30 - libs/xmlrpc-c/debian/copyright | 128 - libs/xmlrpc-c/debian/postinst | 47 - libs/xmlrpc-c/debian/postrm | 39 - libs/xmlrpc-c/debian/rules | 97 - libs/xmlrpc-c/debian/xmlrpc-c-apps.files | 4 - libs/xmlrpc-c/debian/xmlrpc-c-dev.files | 10 - libs/xmlrpc-c/debian/xmlrpc-c0.docs | 6 - libs/xmlrpc-c/debian/xmlrpc-c0.examples | 3 - libs/xmlrpc-c/debian/xmlrpc-c0.files | 2 - libs/xmlrpc-c/dll-common.make | 22 - libs/xmlrpc-c/dll-common.mk | 22 + libs/xmlrpc-c/doc/INSTALL | 44 +- libs/xmlrpc-c/dylib-common.make | 37 - libs/xmlrpc-c/dylib-common.mk | 37 + libs/xmlrpc-c/examples/.cvsignore | 11 - libs/xmlrpc-c/examples/Makefile | 57 +- libs/xmlrpc-c/examples/README | 15 +- libs/xmlrpc-c/examples/auth_client.c | 2 +- libs/xmlrpc-c/examples/compound_value_client.c | 161 + libs/xmlrpc-c/examples/compound_value_server.c | 199 ++ libs/xmlrpc-c/examples/cpp/.cvsignore | 4 - libs/xmlrpc-c/examples/cpp/Makefile | 58 +- .../examples/cpp/callinfo_abyss_server.cpp | 133 + libs/xmlrpc-c/examples/cpp/meerkat-app-list.cpp | 108 - libs/xmlrpc-c/examples/cpp/pstream_client.cpp | 2 +- .../xmlrpc-c/examples/cpp/pstream_inetd_server.cpp | 9 +- .../examples/cpp/pstream_serial_server.cpp | 84 + libs/xmlrpc-c/examples/cpp/xmlrpc_inetd_server.cpp | 25 +- .../examples/cpp/xmlrpc_sample_add_server.cpp | 7 +- .../examples/cpp/xmlrpc_sample_add_server_cgi.cpp | 62 + libs/xmlrpc-c/examples/gen_sample_add_xml.c | 2 +- libs/xmlrpc-c/examples/interrupted_client.c | 3 +- libs/xmlrpc-c/examples/interrupted_server.c | 17 +- libs/xmlrpc-c/examples/json.c | 115 + libs/xmlrpc-c/examples/query-meerkat.c | 156 - libs/xmlrpc-c/examples/synch_client.c | 4 +- libs/xmlrpc-c/examples/xmlrpc_asynch_client.c | 6 +- libs/xmlrpc-c/examples/xmlrpc_inetd_server.c | 15 +- libs/xmlrpc-c/examples/xmlrpc_loop_server.c | 15 +- libs/xmlrpc-c/examples/xmlrpc_sample_add_client.c | 21 +- libs/xmlrpc-c/examples/xmlrpc_sample_add_server.c | 33 +- .../examples/xmlrpc_sample_add_server_cgi.c | 22 +- libs/xmlrpc-c/examples/xmlrpc_server_validatee.c | 18 +- libs/xmlrpc-c/examples/xmlrpc_socket_server.c | 21 +- libs/xmlrpc-c/include/Makefile | 18 +- libs/xmlrpc-c/include/xmlrpc-c/abyss.h | 144 +- libs/xmlrpc-c/include/xmlrpc-c/abyss_winsock.h | 4 +- libs/xmlrpc-c/include/xmlrpc-c/base.h | 282 +- libs/xmlrpc-c/include/xmlrpc-c/base.hpp | 252 +- libs/xmlrpc-c/include/xmlrpc-c/base64.hpp | 5 +- libs/xmlrpc-c/include/xmlrpc-c/base64_int.h | 11 + libs/xmlrpc-c/include/xmlrpc-c/base_int.h | 40 +- libs/xmlrpc-c/include/xmlrpc-c/c_util.h | 23 +- libs/xmlrpc-c/include/xmlrpc-c/client.h | 141 +- libs/xmlrpc-c/include/xmlrpc-c/client.hpp | 59 +- libs/xmlrpc-c/include/xmlrpc-c/client_global.h | 17 + libs/xmlrpc-c/include/xmlrpc-c/client_int.h | 29 + libs/xmlrpc-c/include/xmlrpc-c/client_simple.hpp | 4 +- .../xmlrpc-c/include/xmlrpc-c/client_transport.hpp | 128 +- libs/xmlrpc-c/include/xmlrpc-c/config.h.in | 37 - libs/xmlrpc-c/include/xmlrpc-c/girerr.hpp | 9 +- libs/xmlrpc-c/include/xmlrpc-c/girmem.hpp | 10 +- libs/xmlrpc-c/include/xmlrpc-c/inttypes.h | 3 + libs/xmlrpc-c/include/xmlrpc-c/json.h | 39 + libs/xmlrpc-c/include/xmlrpc-c/oldcppwrapper.hpp | 19 +- libs/xmlrpc-c/include/xmlrpc-c/packetsocket.hpp | 64 +- libs/xmlrpc-c/include/xmlrpc-c/registry.hpp | 90 +- libs/xmlrpc-c/include/xmlrpc-c/select_int.h | 4 +- libs/xmlrpc-c/include/xmlrpc-c/server.h | 42 + libs/xmlrpc-c/include/xmlrpc-c/server_abyss.h | 81 +- libs/xmlrpc-c/include/xmlrpc-c/server_abyss.hpp | 110 +- libs/xmlrpc-c/include/xmlrpc-c/server_cgi.h | 11 +- libs/xmlrpc-c/include/xmlrpc-c/server_cgi.hpp | 45 + libs/xmlrpc-c/include/xmlrpc-c/server_pstream.hpp | 139 +- libs/xmlrpc-c/include/xmlrpc-c/server_w32httpsys.h | 4 +- libs/xmlrpc-c/include/xmlrpc-c/sleep_int.h | 11 + libs/xmlrpc-c/include/xmlrpc-c/string_int.h | 53 +- libs/xmlrpc-c/include/xmlrpc-c/string_number.h | 21 + libs/xmlrpc-c/include/xmlrpc-c/time_int.h | 4 + libs/xmlrpc-c/include/xmlrpc-c/timeout.hpp | 7 +- libs/xmlrpc-c/include/xmlrpc-c/transport.h | 5 + libs/xmlrpc-c/include/xmlrpc-c/transport_int.h | 42 - libs/xmlrpc-c/include/xmlrpc-c/util.h | 36 +- libs/xmlrpc-c/include/xmlrpc-c/util_int.h | 13 +- libs/xmlrpc-c/include/xmlrpc-c/xml.hpp | 24 +- libs/xmlrpc-c/irix-common.make | 31 - libs/xmlrpc-c/irix-common.mk | 31 + libs/xmlrpc-c/lib/abyss/change.log | 34 - libs/xmlrpc-c/lib/abyss/htdocs/index.htm | 21 - libs/xmlrpc-c/lib/abyss/patch_notes.txt | 114 - libs/xmlrpc-c/lib/abyss/readme.txt | 160 - libs/xmlrpc-c/lib/abyss/src/Abyss.dsp | 136 - libs/xmlrpc-c/lib/abyss/src/Abyss.dsw | 29 - libs/xmlrpc-c/lib/abyss/src/Makefile | 28 +- libs/xmlrpc-c/lib/abyss/src/channel.c | 3 +- libs/xmlrpc-c/lib/abyss/src/channel.h | 2 +- libs/xmlrpc-c/lib/abyss/src/chanswitch.c | 3 +- libs/xmlrpc-c/lib/abyss/src/chanswitch.h | 2 +- libs/xmlrpc-c/lib/abyss/src/conf.c | 7 +- libs/xmlrpc-c/lib/abyss/src/conn.c | 302 +- libs/xmlrpc-c/lib/abyss/src/conn.h | 19 +- libs/xmlrpc-c/lib/abyss/src/data.c | 22 +- libs/xmlrpc-c/lib/abyss/src/file.c | 1 + libs/xmlrpc-c/lib/abyss/src/handler.c | 49 +- libs/xmlrpc-c/lib/abyss/src/handler.h | 2 + libs/xmlrpc-c/lib/abyss/src/http.c | 407 +-- libs/xmlrpc-c/lib/abyss/src/http.h | 8 +- libs/xmlrpc-c/lib/abyss/src/main.c | 8 +- libs/xmlrpc-c/lib/abyss/src/response.c | 275 +- libs/xmlrpc-c/lib/abyss/src/server.c | 338 ++- libs/xmlrpc-c/lib/abyss/src/server.h | 8 +- libs/xmlrpc-c/lib/abyss/src/session.c | 55 +- libs/xmlrpc-c/lib/abyss/src/session.h | 24 +- libs/xmlrpc-c/lib/abyss/src/socket.c | 3 +- libs/xmlrpc-c/lib/abyss/src/socket.h | 4 +- libs/xmlrpc-c/lib/abyss/src/socket_openssl.c | 2 + libs/xmlrpc-c/lib/abyss/src/socket_unix.c | 175 +- libs/xmlrpc-c/lib/abyss/src/socket_win.c | 1889 ++++++------ libs/xmlrpc-c/lib/abyss/src/thread.c | 228 -- libs/xmlrpc-c/lib/abyss/src/thread.h | 4 +- libs/xmlrpc-c/lib/abyss/src/thread_fork.c | 11 +- libs/xmlrpc-c/lib/abyss/src/thread_pthread.c | 72 +- libs/xmlrpc-c/lib/abyss/src/thread_windows.c | 27 +- libs/xmlrpc-c/lib/abyss/version.txt | 1 - libs/xmlrpc-c/lib/curl_transport/Makefile | 20 +- libs/xmlrpc-c/lib/curl_transport/curlmulti.c | 313 ++ libs/xmlrpc-c/lib/curl_transport/curlmulti.h | 51 + libs/xmlrpc-c/lib/curl_transport/curltransaction.c | 753 +++++ libs/xmlrpc-c/lib/curl_transport/curltransaction.h | 120 + libs/xmlrpc-c/lib/curl_transport/curlversion.h | 20 + libs/xmlrpc-c/lib/curl_transport/lock.h | 24 + libs/xmlrpc-c/lib/curl_transport/lock_pthread.c | 49 + libs/xmlrpc-c/lib/curl_transport/lock_pthread.h | 9 + .../lib/curl_transport/xmlrpc_curl_transport.c | 1838 +++--------- .../lib/curl_transport/xmlrpc_curl_transport.h | 8 - libs/xmlrpc-c/lib/expat/.cvsignore | 1 - libs/xmlrpc-c/lib/expat/Makefile | 39 + libs/xmlrpc-c/lib/expat/Makefile.in | 314 -- libs/xmlrpc-c/lib/expat/expat.dsw | 74 - libs/xmlrpc-c/lib/expat/gennmtab/.cvsignore | 1 - libs/xmlrpc-c/lib/expat/gennmtab/Makefile | 8 +- libs/xmlrpc-c/lib/expat/gennmtab/gennmtab.dsp | 110 - libs/xmlrpc-c/lib/expat/sample/.cvsignore | 1 - libs/xmlrpc-c/lib/expat/sample/Makefile.in | 208 -- libs/xmlrpc-c/lib/expat/sample/build.bat | 4 - libs/xmlrpc-c/lib/expat/sample/elements.c | 46 - libs/xmlrpc-c/lib/expat/xmlparse/.cvsignore | 1 - libs/xmlrpc-c/lib/expat/xmlparse/Makefile | 93 + libs/xmlrpc-c/lib/expat/xmlparse/Makefile.in | 344 --- libs/xmlrpc-c/lib/expat/xmlparse/xmlparse.c | 207 +- libs/xmlrpc-c/lib/expat/xmlparse/xmlparse.dsp | 279 -- libs/xmlrpc-c/lib/expat/xmlparse/xmlparse.h | 94 +- libs/xmlrpc-c/lib/expat/xmltok/.cvsignore | 1 - libs/xmlrpc-c/lib/expat/xmltok/Makefile | 21 +- libs/xmlrpc-c/lib/expat/xmltok/nametab.h | 150 - libs/xmlrpc-c/lib/expat/xmltok/xmlrole.h | 9 +- libs/xmlrpc-c/lib/expat/xmltok/xmltok.c | 62 +- libs/xmlrpc-c/lib/expat/xmltok/xmltok.dsp | 259 -- libs/xmlrpc-c/lib/expat/xmltok/xmltok.h | 41 +- libs/xmlrpc-c/lib/expat/xmltok/xmltok_impl.c | 391 ++- libs/xmlrpc-c/lib/expat/xmlwf/.cvsignore | 1 - libs/xmlrpc-c/lib/expat/xmlwf/xmlfile.c | 2 +- libs/xmlrpc-c/lib/libutil/Makefile | 18 +- libs/xmlrpc-c/lib/libutil/asprintf.c | 135 +- libs/xmlrpc-c/lib/libutil/base64.c | 49 + libs/xmlrpc-c/lib/libutil/error.c | 4 +- libs/xmlrpc-c/lib/libutil/make_printable.c | 2 +- libs/xmlrpc-c/lib/libutil/memblock.c | 47 +- libs/xmlrpc-c/lib/libutil/select.c | 6 +- libs/xmlrpc-c/lib/libutil/string_number.c | 46 + libs/xmlrpc-c/lib/libutil/utf8.c | 370 ++- libs/xmlrpc-c/lib/libwww_transport/Makefile | 15 +- .../lib/libwww_transport/xmlrpc_libwww_transport.c | 1 + .../lib/libwww_transport/xmlrpc_libwww_transport.h | 8 - libs/xmlrpc-c/lib/util/Makefile | 15 +- libs/xmlrpc-c/lib/util/casprintf.c | 86 +- libs/xmlrpc-c/lib/util/cmdline_parser.c | 2 + libs/xmlrpc-c/lib/util/include/int.h | 16 +- libs/xmlrpc-c/lib/util/include/mallocvar.h | 4 +- libs/xmlrpc-c/lib/util/include/pthreadx.h | 18 +- libs/xmlrpc-c/lib/util/include/sstring.h | 15 - libs/xmlrpc-c/lib/util/include/stdargx.h | 2 +- libs/xmlrpc-c/lib/util/pthreadx_win32.c | 54 +- libs/xmlrpc-c/lib/util/string_parser.c | 10 +- libs/xmlrpc-c/lib/util/stripcaseeq.c | 1 - libs/xmlrpc-c/lib/wininet_transport/Makefile | 13 +- .../wininet_transport/xmlrpc_wininet_transport.c | 19 +- .../wininet_transport/xmlrpc_wininet_transport.h | 8 - libs/xmlrpc-c/ltconfig | 3078 -------------------- libs/xmlrpc-c/src/.cvsignore | 6 - libs/xmlrpc-c/src/Makefile | 64 +- libs/xmlrpc-c/src/cpp/.cvsignore | 1 - libs/xmlrpc-c/src/cpp/Makefile | 179 +- libs/xmlrpc-c/src/cpp/base64.cpp | 2 +- libs/xmlrpc-c/src/cpp/client.cpp | 47 +- libs/xmlrpc-c/src/cpp/cpptest.cpp | 1187 -------- libs/xmlrpc-c/src/cpp/curl.cpp | 147 +- libs/xmlrpc-c/src/cpp/env_wrap.hpp | 3 +- libs/xmlrpc-c/src/cpp/libwww.cpp | 3 +- libs/xmlrpc-c/src/cpp/packetsocket.cpp | 561 +++- libs/xmlrpc-c/src/cpp/pstream.cpp | 49 +- libs/xmlrpc-c/src/cpp/registry.cpp | 170 +- libs/xmlrpc-c/src/cpp/server_abyss.cpp | 571 +++- libs/xmlrpc-c/src/cpp/server_cgi.cpp | 354 +++ libs/xmlrpc-c/src/cpp/server_pstream.cpp | 265 +- libs/xmlrpc-c/src/cpp/server_pstream_conn.cpp | 364 +++ libs/xmlrpc-c/src/cpp/test/Makefile | 33 +- libs/xmlrpc-c/src/cpp/test/base64.cpp | 54 + libs/xmlrpc-c/src/cpp/test/base64.hpp | 9 + libs/xmlrpc-c/src/cpp/test/registry.cpp | 270 +- libs/xmlrpc-c/src/cpp/test/server_abyss.cpp | 61 +- libs/xmlrpc-c/src/cpp/test/server_pstream.cpp | 777 ++++- libs/xmlrpc-c/src/cpp/test/test.cpp | 403 +-- libs/xmlrpc-c/src/cpp/test/testclient.cpp | 81 +- libs/xmlrpc-c/src/cpp/test/value.cpp | 453 +++ libs/xmlrpc-c/src/cpp/test/value.hpp | 9 + libs/xmlrpc-c/src/cpp/test/xml.cpp | 100 + libs/xmlrpc-c/src/cpp/test/xml.hpp | 9 + libs/xmlrpc-c/src/cpp/value.cpp | 232 +- libs/xmlrpc-c/src/cpp/xml.cpp | 155 +- libs/xmlrpc-c/src/double.c | 29 +- libs/xmlrpc-c/src/json.c | 1466 ++++++++++ libs/xmlrpc-c/src/method.c | 18 +- libs/xmlrpc-c/src/method.h | 5 + libs/xmlrpc-c/src/parse_datetime.c | 466 +++ libs/xmlrpc-c/src/parse_datetime.h | 12 + libs/xmlrpc-c/src/parse_value.c | 95 +- libs/xmlrpc-c/src/registry.c | 73 +- libs/xmlrpc-c/src/system_method.c | 172 +- libs/xmlrpc-c/src/test/.cvsignore | 3 - libs/xmlrpc-c/src/test/Makefile | 21 +- libs/xmlrpc-c/src/test/abyss.c | 13 +- libs/xmlrpc-c/src/test/cgi.c | 2 +- libs/xmlrpc-c/src/test/cgitest1.c | 2 +- libs/xmlrpc-c/src/test/client.c | 76 +- libs/xmlrpc-c/src/test/method_registry.c | 201 +- libs/xmlrpc-c/src/test/parse_xml.c | 62 +- libs/xmlrpc-c/src/test/req_out_of_order.xml | 12 - libs/xmlrpc-c/src/test/req_value_name.xml | 14 - libs/xmlrpc-c/src/test/sample_add_call.xml | 8 - libs/xmlrpc-c/src/test/serialize.c | 12 +- libs/xmlrpc-c/src/test/serialize_value.c | 3 +- libs/xmlrpc-c/src/test/server_abyss.c | 43 +- libs/xmlrpc-c/src/test/test.c | 87 +- libs/xmlrpc-c/src/test/test.h | 109 - libs/xmlrpc-c/src/test/testtool.c | 65 + libs/xmlrpc-c/src/test/testtool.h | 80 + libs/xmlrpc-c/src/test/value.c | 258 +- libs/xmlrpc-c/src/test/value_datetime.c | 424 +++ libs/xmlrpc-c/src/test/value_datetime.h | 7 + libs/xmlrpc-c/src/test/xml_data.h | 3 + libs/xmlrpc-c/src/trace.c | 3 +- libs/xmlrpc-c/src/version.c | 11 + libs/xmlrpc-c/src/xmlrpc_array.c | 37 +- libs/xmlrpc-c/src/xmlrpc_base64.c | 195 +- libs/xmlrpc-c/src/xmlrpc_build.c | 26 +- libs/xmlrpc-c/src/xmlrpc_builddecomp.c | 973 ------- libs/xmlrpc-c/src/xmlrpc_client.c | 403 ++- libs/xmlrpc-c/src/xmlrpc_client_global.c | 114 +- libs/xmlrpc-c/src/xmlrpc_data.c | 37 +- libs/xmlrpc-c/src/xmlrpc_datetime.c | 587 ++-- libs/xmlrpc-c/src/xmlrpc_decompose.c | 7 +- libs/xmlrpc-c/src/xmlrpc_expat.c | 32 +- libs/xmlrpc-c/src/xmlrpc_libxml2.c | 15 +- libs/xmlrpc-c/src/xmlrpc_parse.c | 161 +- libs/xmlrpc-c/src/xmlrpc_registry.c | 830 ------ libs/xmlrpc-c/src/xmlrpc_serialize.c | 176 +- libs/xmlrpc-c/src/xmlrpc_server_abyss.c | 672 +++-- libs/xmlrpc-c/src/xmlrpc_server_cgi.c | 13 +- libs/xmlrpc-c/src/xmlrpc_server_info.c | 7 + libs/xmlrpc-c/src/xmlrpc_server_w32httpsys.c | 42 +- libs/xmlrpc-c/src/xmlrpc_string.c | 34 +- libs/xmlrpc-c/src/xmlrpc_struct.c | 114 +- libs/xmlrpc-c/src/xmlrpc_strutil.c | 75 - libs/xmlrpc-c/src/xmlrpc_support.c | 394 --- libs/xmlrpc-c/src/xmlrpc_transport.c | 143 - libs/xmlrpc-c/src/xmlrpc_utf8.c | 376 --- libs/xmlrpc-c/srcdir.mk.in | 1 + libs/xmlrpc-c/tools/.cvsignore | 1 - libs/xmlrpc-c/tools/Makefile | 13 +- libs/xmlrpc-c/tools/Makefile.common | 47 - libs/xmlrpc-c/tools/common.mk | 2 +- libs/xmlrpc-c/tools/lib/Makefile | 8 +- libs/xmlrpc-c/tools/lib/dumpvalue.c | 12 +- libs/xmlrpc-c/tools/turbocharger/.cvsignore | 1 - libs/xmlrpc-c/tools/xml-rpc-api2cpp/.cvsignore | 1 - libs/xmlrpc-c/tools/xml-rpc-api2cpp/Makefile | 29 +- libs/xmlrpc-c/tools/xml-rpc-api2cpp/README | 6 - libs/xmlrpc-c/tools/xml-rpc-api2txt | 147 - libs/xmlrpc-c/tools/xml-rpc-api2txt.1 | 47 - libs/xmlrpc-c/tools/xmlrpc/.cvsignore | 1 - libs/xmlrpc-c/tools/xmlrpc/Makefile | 8 +- libs/xmlrpc-c/tools/xmlrpc/xmlrpc.c | 74 +- libs/xmlrpc-c/tools/xmlrpc/xmlrpc.html | 6 +- libs/xmlrpc-c/tools/xmlrpc_cpp_proxy/Makefile | 10 +- libs/xmlrpc-c/tools/xmlrpc_pstream/Makefile | 10 +- .../tools/xmlrpc_pstream/xmlrpc_pstream.cpp | 7 +- .../tools/xmlrpc_pstream/xmlrpc_pstream.html | 2 +- libs/xmlrpc-c/tools/xmlrpc_transport/.cvsignore | 1 - libs/xmlrpc-c/tools/xmlrpc_transport/Makefile | 17 +- .../tools/xmlrpc_transport/xmlrpc_transport | 120 - .../tools/xmlrpc_transport/xmlrpc_transport.c | 2 +- libs/xmlrpc-c/transport_config.make | 39 - libs/xmlrpc-c/transport_config.mk | 39 + libs/xmlrpc-c/unix-common.make | 79 - libs/xmlrpc-c/unix-common.mk | 82 + libs/xmlrpc-c/version.h | 8 - libs/xmlrpc-c/version.mk | 11 + libs/xmlrpc-c/xmlrpc-c-config.in | 180 -- libs/xmlrpc-c/xmlrpc-c-config.main | 24 +- libs/xmlrpc-c/xmlrpc-c-config.test.in | 153 - libs/xmlrpc-c/xmlrpc-c-config.test.main | 33 +- libs/xmlrpc-c/xmlrpc_amconfig.h.in | 9 +- libs/xmlrpc-c/xmlrpc_config.h.in | 76 +- src/include/switch_event.h | 16 +- src/include/switch_xml.h | 8 +- src/mod/applications/mod_commands/mod_commands.c | 766 ++--- src/mod/languages/mod_lua/mod_lua.cpp | 10 +- src/mod/xml_int/mod_xml_rpc/Makefile | 27 +- .../xml_int/mod_xml_rpc/mod_xml_rpc.2010.vcxproj | 28 +- src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c | 467 +-- src/switch_loadable_module.c | 4 +- src/switch_xml.c | 25 +- w32/xmlrpc.props | 15 + w32/xmlrpc.vsprops | 15 + 413 files changed, 34400 insertions(+), 26419 deletions(-) diff --git a/.gitignore b/.gitignore index 1039628..9df71cc 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,7 @@ *.ilk *.bsc *.pch +*.opensdf *.tar *.gz *.tgz @@ -50,6 +51,7 @@ TAGS *.unsuccessfulbuild *.cache *.lastbuildstate +*.sdf /w32/Library/lastversion /w32/Library/tmpVersion.Bat @@ -81,9 +83,9 @@ TAGS /tone2wav /All/ -/Debug/ +Debug/ /bin/ -/Release/ +Release/ /ipch/ /*.log @@ -165,63 +167,18 @@ TAGS /src/mod/say/mod_say_zh/Makefile BuildLog.htm -/w32/Console/Debug/ -/w32/Console/Release/ -/w32/Library/Debug/ -/w32/Library/Release/ -Freeswitch.2010.sdf +Win32/ +win32/ +!/libs/win32/ +*.suo +*.sdf +x64/ +ipch/ -/Win32/ -/x64/ -src/mod/codecs/mod_celt/*/*/mod_celt.log -src/mod/endpoints/mod_skinny/*/*/mod_skinny_2010.log -src/mod/formats/mod_shout/*/*/mod_shout.log +/libs/xmlrpc-c/tools/xml-rpc-api2txt /w32/Setup/obj -/src/mod/asr_tts/mod_pocketsphinx/x64/Debug/mod_pocketsphinx_manifest.rc -/src/mod/endpoints/mod_h323/x64/Debug/mod_h323_manifest.rc -/src/mod/endpoints/mod_rtmp/Win32/Debug/mod_rtmp_2010.log -/src/mod/endpoints/mod_rtmp/Win32/Release/mod_rtmp_2010.log -/src/mod/endpoints/mod_rtmp/x64/Debug/mod_rtmp_2010.log -/src/mod/endpoints/mod_rtmp/x64/Debug/mod_rtmp_manifest.rc -/src/mod/endpoints/mod_rtmp/x64/Release/mod_rtmp_2010.log -/src/mod/endpoints/mod_skinny/x64/Debug/mod_skinny_manifest.rc -/src/mod/languages/mod_managed/x64/Debug_CLR/FREESWITCH.MANAGED.DLL.metagen -/src/mod/languages/mod_managed/x64/Debug_CLR/RSAENH.DLL.bi -/src/mod/languages/mod_managed/x64/Debug_CLR/TZRES.DLL.bi -/w32/Library/x64/Debug/FreeSwitch_manifest.rc -/src/mod/endpoints/mod_h323/Win32/Debug/mod_h323_manifest.rc -/src/mod/endpoints/mod_rtmp/Win32/Debug/mod_rtmp_manifest.rc -/src/mod/endpoints/mod_skinny/Win32/Debug/mod_skinny_manifest.rc -/src/mod/languages/mod_managed/Win32/Debug_CLR/FREESWITCH.MANAGED.DLL.metagen -/src/mod/languages/mod_managed/Win32/Debug_CLR/RSAENH.DLL.bi -/src/mod/languages/mod_managed/Win32/Debug_CLR/TZRES.DLL.bi -/w32/Library/Win32/Debug/FreeSwitch_manifest.rc -/src/mod/languages/mod_managed/Win32/Release_CLR/FREESWITCH.MANAGED.DLL.metagen -/src/mod/languages/mod_managed/Win32/Release_CLR/RSAENH.DLL.bi -/src/mod/languages/mod_managed/Win32/Release_CLR/TZRES.DLL.bi -/src/mod/languages/mod_managed/x64/Release_CLR/FREESWITCH.MANAGED.DLL.metagen -/src/mod/languages/mod_managed/x64/Release_CLR/RSAENH.DLL.bi -/src/mod/languages/mod_managed/x64/Release_CLR/TZRES.DLL.bi -libs/apr-util/a.out.dSYM/Contents/Info.plist -libs/apr-util/a.out.dSYM/Contents/Resources/DWARF/a.out -libs/apr/a.out.dSYM/Contents/Info.plist -libs/apr/a.out.dSYM/Contents/Resources/DWARF/a.out -libs/iksemel/a.out.dSYM/Contents/Info.plist -libs/iksemel/a.out.dSYM/Contents/Resources/DWARF/a.out -libs/ilbc/a.out.dSYM/Contents/Info.plist -libs/ilbc/a.out.dSYM/Contents/Resources/DWARF/a.out -libs/libedit/a.out.dSYM/Contents/Info.plist -libs/libedit/a.out.dSYM/Contents/Resources/DWARF/a.out -libs/pcre/a.out.dSYM/Contents/Info.plist -libs/pcre/a.out.dSYM/Contents/Resources/DWARF/a.out -libs/sqlite/lemon.dSYM/Contents/Info.plist -libs/sqlite/lemon.dSYM/Contents/Resources/DWARF/lemon -libs/sqlite/mkkeywordhash.dSYM/Contents/Info.plist -libs/sqlite/mkkeywordhash.dSYM/Contents/Resources/DWARF/mkkeywordhash -libs/sqlite/sqlite3.dSYM/Contents/Info.plist -libs/sqlite/sqlite3.dSYM/Contents/Resources/DWARF/sqlite3 -libs/srtp/a.out.dSYM/Contents/Info.plist -libs/srtp/a.out.dSYM/Contents/Resources/DWARF/a.out +*dSYM* +/libs/xmlrpc-c/lib/expat/xmltok/nametab.h diff --git a/Freeswitch.2008.sln b/Freeswitch.2008.sln index 62b2459..edb049f 100644 --- a/Freeswitch.2008.sln +++ b/Freeswitch.2008.sln @@ -281,12 +281,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_console", "src\mod\logg EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_xml_rpc", "src\mod\xml_int\mod_xml_rpc\mod_xml_rpc.2008.vcproj", "{CBEC7225-0C21-4DA8-978E-1F158F8AD950}" ProjectSection(ProjectDependencies) = postProject - {0D108721-EAE8-4BAF-8102-D8960EC93647} = {0D108721-EAE8-4BAF-8102-D8960EC93647} - {B535402E-38D2-4D54-8360-423ACBD17192} = {B535402E-38D2-4D54-8360-423ACBD17192} {202D7A4E-760D-4D0E-AFA1-D7459CED30FF} = {202D7A4E-760D-4D0E-AFA1-D7459CED30FF} - {87EE9DA4-DE1E-4448-8324-183C98DCA588} = {87EE9DA4-DE1E-4448-8324-183C98DCA588} - {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA} = {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA} - {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9} = {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9} + {2390F054-A7F1-4CB9-ACB0-F46EC6E77B5B} = {2390F054-A7F1-4CB9-ACB0-F46EC6E77B5B} + {A4D67895-E709-40C7-82B6-DE1D12DDDE04} = {A4D67895-E709-40C7-82B6-DE1D12DDDE04} + {510BDAA8-C04D-47DB-8482-E6AF380D3E07} = {510BDAA8-C04D-47DB-8482-E6AF380D3E07} + {E5A9BCDA-B82D-4B08-B23E-9A782E367888} = {E5A9BCDA-B82D-4B08-B23E-9A782E367888} + {3CF7C0E0-07C2-473A-A1E4-2274AEEC1268} = {3CF7C0E0-07C2-473A-A1E4-2274AEEC1268} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_rss", "src\mod\applications\mod_rss\mod_rss.2008.vcproj", "{B69247FA-ECD6-40ED-8E44-5CA6C3BAF9A4}" @@ -549,14 +549,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_lua", "src\mod\language {D0B36172-CD76-454A-9B89-990025266C2A} = {D0B36172-CD76-454A-9B89-990025266C2A} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "abyss", "libs\xmlrpc-c\Windows\abyss.2008.vcproj", "{D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xmlrpc", "libs\xmlrpc-c\Windows\xmlrpc.2008.vcproj", "{CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xmlparse", "libs\xmlrpc-c\Windows\xmlparse.2008.vcproj", "{0D108721-EAE8-4BAF-8102-D8960EC93647}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xmltok", "libs\xmlrpc-c\Windows\xmltok.2008.vcproj", "{B535402E-38D2-4D54-8360-423ACBD17192}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Download sphinxbase", "libs\win32\Download sphinxbase.2008.vcproj", "{4F92B672-DADB-4047-8D6A-4BB3796733FD}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Download sphinxmodel", "libs\win32\Download sphinxmodel.2008.vcproj", "{2DEE4895-1134-439C-B688-52203E57D878}" @@ -968,6 +960,21 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libjpeg", "libs\win32\libjp EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Download libjpeg", "libs\win32\Download libjpeg.2008.vcproj", "{21A7DA70-555E-49FA-942B-D84A38B61243}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "xmlrpc-c", "xmlrpc-c", "{3783935D-7C0A-4166-A376-C3D8E64F3A9C}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "abyss", "libs\win32\xmlrpc-c\abyss.2008.vcproj", "{A4D67895-E709-40C7-82B6-DE1D12DDDE04}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gennmtab", "libs\win32\xmlrpc-c\gennmtab.2008.vcproj", "{2390F054-A7F1-4CB9-ACB0-F46EC6E77B5B}" + ProjectSection(ProjectDependencies) = postProject + {E5A9BCDA-B82D-4B08-B23E-9A782E367888} = {E5A9BCDA-B82D-4B08-B23E-9A782E367888} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xmlparse", "libs\win32\xmlrpc-c\xmlparse.2008.vcproj", "{E5A9BCDA-B82D-4B08-B23E-9A782E367888}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xmlrpc", "libs\win32\xmlrpc-c\xmlrpc.2008.vcproj", "{510BDAA8-C04D-47DB-8482-E6AF380D3E07}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xmltok", "libs\win32\xmlrpc-c\xmltok.2008.vcproj", "{3CF7C0E0-07C2-473A-A1E4-2274AEEC1268}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution All|Win32 = All|Win32 @@ -1728,50 +1735,6 @@ Global {7B077E7F-1BE7-4291-AB86-55E527B25CAC}.Release|Win32.Build.0 = Release|Win32 {7B077E7F-1BE7-4291-AB86-55E527B25CAC}.Release|x64.ActiveCfg = Release|x64 {7B077E7F-1BE7-4291-AB86-55E527B25CAC}.Release|x64.Build.0 = Release|x64 - {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.All|Win32.ActiveCfg = Release|x64 - {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.All|x64.ActiveCfg = Release|x64 - {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.All|x64.Build.0 = Release|x64 - {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Debug|Win32.ActiveCfg = Debug|Win32 - {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Debug|Win32.Build.0 = Debug|Win32 - {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Debug|x64.ActiveCfg = Debug|x64 - {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Debug|x64.Build.0 = Debug|x64 - {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Release|Win32.ActiveCfg = Release|Win32 - {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Release|Win32.Build.0 = Release|Win32 - {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Release|x64.ActiveCfg = Release|x64 - {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Release|x64.Build.0 = Release|x64 - {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.All|Win32.ActiveCfg = Release|x64 - {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.All|x64.ActiveCfg = Release|x64 - {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.All|x64.Build.0 = Release|x64 - {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Debug|Win32.ActiveCfg = Debug|Win32 - {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Debug|Win32.Build.0 = Debug|Win32 - {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Debug|x64.ActiveCfg = Debug|x64 - {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Debug|x64.Build.0 = Debug|x64 - {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Release|Win32.ActiveCfg = Release|Win32 - {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Release|Win32.Build.0 = Release|Win32 - {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Release|x64.ActiveCfg = Release|x64 - {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Release|x64.Build.0 = Release|x64 - {0D108721-EAE8-4BAF-8102-D8960EC93647}.All|Win32.ActiveCfg = Debug|x64 - {0D108721-EAE8-4BAF-8102-D8960EC93647}.All|x64.ActiveCfg = Debug|x64 - {0D108721-EAE8-4BAF-8102-D8960EC93647}.All|x64.Build.0 = Debug|x64 - {0D108721-EAE8-4BAF-8102-D8960EC93647}.Debug|Win32.ActiveCfg = Debug|Win32 - {0D108721-EAE8-4BAF-8102-D8960EC93647}.Debug|Win32.Build.0 = Debug|Win32 - {0D108721-EAE8-4BAF-8102-D8960EC93647}.Debug|x64.ActiveCfg = Debug|x64 - {0D108721-EAE8-4BAF-8102-D8960EC93647}.Debug|x64.Build.0 = Debug|x64 - {0D108721-EAE8-4BAF-8102-D8960EC93647}.Release|Win32.ActiveCfg = Release|Win32 - {0D108721-EAE8-4BAF-8102-D8960EC93647}.Release|Win32.Build.0 = Release|Win32 - {0D108721-EAE8-4BAF-8102-D8960EC93647}.Release|x64.ActiveCfg = Release|x64 - {0D108721-EAE8-4BAF-8102-D8960EC93647}.Release|x64.Build.0 = Release|x64 - {B535402E-38D2-4D54-8360-423ACBD17192}.All|Win32.ActiveCfg = Release|x64 - {B535402E-38D2-4D54-8360-423ACBD17192}.All|x64.ActiveCfg = Release|x64 - {B535402E-38D2-4D54-8360-423ACBD17192}.All|x64.Build.0 = Release|x64 - {B535402E-38D2-4D54-8360-423ACBD17192}.Debug|Win32.ActiveCfg = Debug|Win32 - {B535402E-38D2-4D54-8360-423ACBD17192}.Debug|Win32.Build.0 = Debug|Win32 - {B535402E-38D2-4D54-8360-423ACBD17192}.Debug|x64.ActiveCfg = Debug|x64 - {B535402E-38D2-4D54-8360-423ACBD17192}.Debug|x64.Build.0 = Debug|x64 - {B535402E-38D2-4D54-8360-423ACBD17192}.Release|Win32.ActiveCfg = Release|Win32 - {B535402E-38D2-4D54-8360-423ACBD17192}.Release|Win32.Build.0 = Release|Win32 - {B535402E-38D2-4D54-8360-423ACBD17192}.Release|x64.ActiveCfg = Release|x64 - {B535402E-38D2-4D54-8360-423ACBD17192}.Release|x64.Build.0 = Release|x64 {4F92B672-DADB-4047-8D6A-4BB3796733FD}.All|Win32.ActiveCfg = Release|Win32 {4F92B672-DADB-4047-8D6A-4BB3796733FD}.All|Win32.Build.0 = Release|Win32 {4F92B672-DADB-4047-8D6A-4BB3796733FD}.All|x64.ActiveCfg = Release|Win32 @@ -2749,6 +2712,61 @@ Global {21A7DA70-555E-49FA-942B-D84A38B61243}.Release|Win32.Build.0 = Release|Win32 {21A7DA70-555E-49FA-942B-D84A38B61243}.Release|x64.ActiveCfg = Release|Win32 {21A7DA70-555E-49FA-942B-D84A38B61243}.Release|x64.Build.0 = Release|Win32 + {A4D67895-E709-40C7-82B6-DE1D12DDDE04}.All|Win32.ActiveCfg = Release|x64 + {A4D67895-E709-40C7-82B6-DE1D12DDDE04}.All|x64.ActiveCfg = Release|x64 + {A4D67895-E709-40C7-82B6-DE1D12DDDE04}.All|x64.Build.0 = Release|x64 + {A4D67895-E709-40C7-82B6-DE1D12DDDE04}.Debug|Win32.ActiveCfg = Debug|Win32 + {A4D67895-E709-40C7-82B6-DE1D12DDDE04}.Debug|Win32.Build.0 = Debug|Win32 + {A4D67895-E709-40C7-82B6-DE1D12DDDE04}.Debug|x64.ActiveCfg = Debug|x64 + {A4D67895-E709-40C7-82B6-DE1D12DDDE04}.Debug|x64.Build.0 = Debug|x64 + {A4D67895-E709-40C7-82B6-DE1D12DDDE04}.Release|Win32.ActiveCfg = Release|Win32 + {A4D67895-E709-40C7-82B6-DE1D12DDDE04}.Release|Win32.Build.0 = Release|Win32 + {A4D67895-E709-40C7-82B6-DE1D12DDDE04}.Release|x64.ActiveCfg = Release|x64 + {A4D67895-E709-40C7-82B6-DE1D12DDDE04}.Release|x64.Build.0 = Release|x64 + {2390F054-A7F1-4CB9-ACB0-F46EC6E77B5B}.All|Win32.ActiveCfg = Release|x64 + {2390F054-A7F1-4CB9-ACB0-F46EC6E77B5B}.All|x64.ActiveCfg = Release|x64 + {2390F054-A7F1-4CB9-ACB0-F46EC6E77B5B}.All|x64.Build.0 = Release|x64 + {2390F054-A7F1-4CB9-ACB0-F46EC6E77B5B}.Debug|Win32.ActiveCfg = Debug|Win32 + {2390F054-A7F1-4CB9-ACB0-F46EC6E77B5B}.Debug|Win32.Build.0 = Debug|Win32 + {2390F054-A7F1-4CB9-ACB0-F46EC6E77B5B}.Debug|x64.ActiveCfg = Debug|x64 + {2390F054-A7F1-4CB9-ACB0-F46EC6E77B5B}.Debug|x64.Build.0 = Debug|x64 + {2390F054-A7F1-4CB9-ACB0-F46EC6E77B5B}.Release|Win32.ActiveCfg = Release|Win32 + {2390F054-A7F1-4CB9-ACB0-F46EC6E77B5B}.Release|Win32.Build.0 = Release|Win32 + {2390F054-A7F1-4CB9-ACB0-F46EC6E77B5B}.Release|x64.ActiveCfg = Release|x64 + {2390F054-A7F1-4CB9-ACB0-F46EC6E77B5B}.Release|x64.Build.0 = Release|x64 + {E5A9BCDA-B82D-4B08-B23E-9A782E367888}.All|Win32.ActiveCfg = Debug|x64 + {E5A9BCDA-B82D-4B08-B23E-9A782E367888}.All|x64.ActiveCfg = Debug|x64 + {E5A9BCDA-B82D-4B08-B23E-9A782E367888}.All|x64.Build.0 = Debug|x64 + {E5A9BCDA-B82D-4B08-B23E-9A782E367888}.Debug|Win32.ActiveCfg = Debug|Win32 + {E5A9BCDA-B82D-4B08-B23E-9A782E367888}.Debug|Win32.Build.0 = Debug|Win32 + {E5A9BCDA-B82D-4B08-B23E-9A782E367888}.Debug|x64.ActiveCfg = Debug|x64 + {E5A9BCDA-B82D-4B08-B23E-9A782E367888}.Debug|x64.Build.0 = Debug|x64 + {E5A9BCDA-B82D-4B08-B23E-9A782E367888}.Release|Win32.ActiveCfg = Release|Win32 + {E5A9BCDA-B82D-4B08-B23E-9A782E367888}.Release|Win32.Build.0 = Release|Win32 + {E5A9BCDA-B82D-4B08-B23E-9A782E367888}.Release|x64.ActiveCfg = Release|x64 + {E5A9BCDA-B82D-4B08-B23E-9A782E367888}.Release|x64.Build.0 = Release|x64 + {510BDAA8-C04D-47DB-8482-E6AF380D3E07}.All|Win32.ActiveCfg = Release|x64 + {510BDAA8-C04D-47DB-8482-E6AF380D3E07}.All|x64.ActiveCfg = Release|x64 + {510BDAA8-C04D-47DB-8482-E6AF380D3E07}.All|x64.Build.0 = Release|x64 + {510BDAA8-C04D-47DB-8482-E6AF380D3E07}.Debug|Win32.ActiveCfg = Debug|Win32 + {510BDAA8-C04D-47DB-8482-E6AF380D3E07}.Debug|Win32.Build.0 = Debug|Win32 + {510BDAA8-C04D-47DB-8482-E6AF380D3E07}.Debug|x64.ActiveCfg = Debug|x64 + {510BDAA8-C04D-47DB-8482-E6AF380D3E07}.Debug|x64.Build.0 = Debug|x64 + {510BDAA8-C04D-47DB-8482-E6AF380D3E07}.Release|Win32.ActiveCfg = Release|Win32 + {510BDAA8-C04D-47DB-8482-E6AF380D3E07}.Release|Win32.Build.0 = Release|Win32 + {510BDAA8-C04D-47DB-8482-E6AF380D3E07}.Release|x64.ActiveCfg = Release|x64 + {510BDAA8-C04D-47DB-8482-E6AF380D3E07}.Release|x64.Build.0 = Release|x64 + {3CF7C0E0-07C2-473A-A1E4-2274AEEC1268}.All|Win32.ActiveCfg = Release|x64 + {3CF7C0E0-07C2-473A-A1E4-2274AEEC1268}.All|x64.ActiveCfg = Release|x64 + {3CF7C0E0-07C2-473A-A1E4-2274AEEC1268}.All|x64.Build.0 = Release|x64 + {3CF7C0E0-07C2-473A-A1E4-2274AEEC1268}.Debug|Win32.ActiveCfg = Debug|Win32 + {3CF7C0E0-07C2-473A-A1E4-2274AEEC1268}.Debug|Win32.Build.0 = Debug|Win32 + {3CF7C0E0-07C2-473A-A1E4-2274AEEC1268}.Debug|x64.ActiveCfg = Debug|x64 + {3CF7C0E0-07C2-473A-A1E4-2274AEEC1268}.Debug|x64.Build.0 = Debug|x64 + {3CF7C0E0-07C2-473A-A1E4-2274AEEC1268}.Release|Win32.ActiveCfg = Release|Win32 + {3CF7C0E0-07C2-473A-A1E4-2274AEEC1268}.Release|Win32.Build.0 = Release|Win32 + {3CF7C0E0-07C2-473A-A1E4-2274AEEC1268}.Release|x64.ActiveCfg = Release|x64 + {3CF7C0E0-07C2-473A-A1E4-2274AEEC1268}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -2846,10 +2864,6 @@ Global {70A49BC2-7500-41D0-B75D-EDCC5BE987A0} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} {DF018947-0FFF-4EB3-BDEE-441DC81DA7A4} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} {0A18A071-125E-442F-AFF7-A3F68ABECF99} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} - {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} - {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} - {0D108721-EAE8-4BAF-8102-D8960EC93647} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} - {B535402E-38D2-4D54-8360-423ACBD17192} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} {2F025EAD-99BD-40F5-B2CC-F0A28CAD7F2D} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} {94001A0E-A837-445C-8004-F918F10D0226} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} {0AD1177E-1FD8-4643-9391-431467A11084} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} @@ -2876,6 +2890,7 @@ Global {23B4D303-79FC-49E0-89E2-2280E7E28940} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} {26C82FCE-E0CF-4D10-A00C-D8E582FFEB53} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} {FE02CD06-DD97-489C-8F61-B5E7F89BCC0A} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} + {3783935D-7C0A-4166-A376-C3D8E64F3A9C} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} {8B3B4C4C-13C2-446C-BEB0-F412CC2CFB9A} = {C120A020-773F-4EA3-923F-B67AF28B750D} {4F92B672-DADB-4047-8D6A-4BB3796733FD} = {C120A020-773F-4EA3-923F-B67AF28B750D} {2DEE4895-1134-439C-B688-52203E57D878} = {C120A020-773F-4EA3-923F-B67AF28B750D} @@ -2937,5 +2952,10 @@ Global {D331904D-A00A-4694-A5A3-FCFF64AB5DBE} = {B376D494-D7DD-4B2A-99E2-52916D5A8CD8} {B4B62169-5AD4-4559-8707-3D933AC5DB39} = {B376D494-D7DD-4B2A-99E2-52916D5A8CD8} {25BD39B1-C8BF-4676-A738-9CABD9C6BC79} = {B376D494-D7DD-4B2A-99E2-52916D5A8CD8} + {A4D67895-E709-40C7-82B6-DE1D12DDDE04} = {3783935D-7C0A-4166-A376-C3D8E64F3A9C} + {2390F054-A7F1-4CB9-ACB0-F46EC6E77B5B} = {3783935D-7C0A-4166-A376-C3D8E64F3A9C} + {E5A9BCDA-B82D-4B08-B23E-9A782E367888} = {3783935D-7C0A-4166-A376-C3D8E64F3A9C} + {510BDAA8-C04D-47DB-8482-E6AF380D3E07} = {3783935D-7C0A-4166-A376-C3D8E64F3A9C} + {3CF7C0E0-07C2-473A-A1E4-2274AEEC1268} = {3783935D-7C0A-4166-A376-C3D8E64F3A9C} EndGlobalSection EndGlobal diff --git a/Freeswitch.2010.sln b/Freeswitch.2010.sln index fd8eda1..c232e9a 100644 --- a/Freeswitch.2010.sln +++ b/Freeswitch.2010.sln @@ -315,14 +315,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_spidermonkey_curl", "sr EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_lua", "src\mod\languages\mod_lua\mod_lua.2010.vcxproj", "{7B077E7F-1BE7-4291-AB86-55E527B25CAC}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "abyss", "libs\xmlrpc-c\Windows\abyss.2010.vcxproj", "{D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xmlrpc", "libs\xmlrpc-c\Windows\xmlrpc.2010.vcxproj", "{CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xmlparse", "libs\xmlrpc-c\Windows\xmlparse.2010.vcxproj", "{0D108721-EAE8-4BAF-8102-D8960EC93647}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xmltok", "libs\xmlrpc-c\Windows\xmltok.2010.vcxproj", "{B535402E-38D2-4D54-8360-423ACBD17192}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Download sphinxbase", "libs\win32\Download sphinxbase.2010.vcxproj", "{4F92B672-DADB-4047-8D6A-4BB3796733FD}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Download sphinxmodel", "libs\win32\Download sphinxmodel.2010.vcxproj", "{2DEE4895-1134-439C-B688-52203E57D878}" @@ -529,6 +521,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_abstraction", "src\mod\ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_sms", "src\mod\applications\mod_sms\mod_sms.2010.vcxproj", "{2469B306-B027-4FF2-8815-C9C1EA2CAE79}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "xmlrpc-c", "xmlrpc-c", "{9DE35039-A8F6-4FBF-B1B6-EB527F802411}" +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gsmlib", "src\mod\endpoints\mod_gsmopen\gsmlib\gsmlib-1.10-patched-13ubuntu\win32\gsmlib.2010.vcxproj", "{26C82FCE-E0CF-4D10-A00C-D8E582FFEB53}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_gsmopen", "src\mod\endpoints\mod_gsmopen\mod_gsmopen.2010.vcxproj", "{74B120FF-6935-4DFE-A142-CDB6BEA99C90}" @@ -544,6 +538,31 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libjpeg", "libs\win32\libjp {652AD5F7-8488-489F-AAD0-7FBE064703B6} = {652AD5F7-8488-489F-AAD0-7FBE064703B6} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "abyss", "libs\win32\xmlrpc-c\abyss.2010.vcxproj", "{D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}" + ProjectSection(ProjectDependencies) = postProject + {0D108721-EAE8-4BAF-8102-D8960EC93647} = {0D108721-EAE8-4BAF-8102-D8960EC93647} + {B535402E-38D2-4D54-8360-423ACBD17192} = {B535402E-38D2-4D54-8360-423ACBD17192} + {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA} = {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gennmtab", "libs\win32\xmlrpc-c\gennmtab.2010.vcxproj", "{BED7539C-0099-4A14-AD5D-30828F15A171}" + ProjectSection(ProjectDependencies) = postProject + {0D108721-EAE8-4BAF-8102-D8960EC93647} = {0D108721-EAE8-4BAF-8102-D8960EC93647} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xmlparse", "libs\win32\xmlrpc-c\xmlparse.2010.vcxproj", "{0D108721-EAE8-4BAF-8102-D8960EC93647}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xmlrpc", "libs\win32\xmlrpc-c\xmlrpc.2010.vcxproj", "{CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}" + ProjectSection(ProjectDependencies) = postProject + {0D108721-EAE8-4BAF-8102-D8960EC93647} = {0D108721-EAE8-4BAF-8102-D8960EC93647} + {B535402E-38D2-4D54-8360-423ACBD17192} = {B535402E-38D2-4D54-8360-423ACBD17192} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xmltok", "libs\win32\xmlrpc-c\xmltok.2010.vcxproj", "{B535402E-38D2-4D54-8360-423ACBD17192}" + ProjectSection(ProjectDependencies) = postProject + {BED7539C-0099-4A14-AD5D-30828F15A171} = {BED7539C-0099-4A14-AD5D-30828F15A171} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution All|Win32 = All|Win32 @@ -1826,78 +1845,6 @@ Global {7B077E7F-1BE7-4291-AB86-55E527B25CAC}.Release|x64.Build.0 = Release|x64 {7B077E7F-1BE7-4291-AB86-55E527B25CAC}.Release|x64 Setup.ActiveCfg = Release|x64 {7B077E7F-1BE7-4291-AB86-55E527B25CAC}.Release|x86 Setup.ActiveCfg = Release|Win32 - {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.All|Win32.ActiveCfg = Release|x64 - {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.All|x64.ActiveCfg = Release|x64 - {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.All|x64.Build.0 = Release|x64 - {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.All|x64 Setup.ActiveCfg = Release|x64 - {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.All|x64 Setup.Build.0 = Release|x64 - {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.All|x86 Setup.ActiveCfg = Release|x64 - {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Debug|Win32.ActiveCfg = Debug|Win32 - {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Debug|Win32.Build.0 = Debug|Win32 - {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Debug|x64.ActiveCfg = Debug|x64 - {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Debug|x64.Build.0 = Debug|x64 - {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Debug|x64 Setup.ActiveCfg = Debug|x64 - {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Debug|x86 Setup.ActiveCfg = Debug|Win32 - {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Release|Win32.ActiveCfg = Release|Win32 - {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Release|Win32.Build.0 = Release|Win32 - {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Release|x64.ActiveCfg = Release|x64 - {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Release|x64.Build.0 = Release|x64 - {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Release|x64 Setup.ActiveCfg = Release|x64 - {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Release|x86 Setup.ActiveCfg = Release|Win32 - {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.All|Win32.ActiveCfg = Release|x64 - {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.All|x64.ActiveCfg = Release|x64 - {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.All|x64.Build.0 = Release|x64 - {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.All|x64 Setup.ActiveCfg = Release|x64 - {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.All|x64 Setup.Build.0 = Release|x64 - {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.All|x86 Setup.ActiveCfg = Release|x64 - {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Debug|Win32.ActiveCfg = Debug|Win32 - {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Debug|Win32.Build.0 = Debug|Win32 - {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Debug|x64.ActiveCfg = Debug|x64 - {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Debug|x64.Build.0 = Debug|x64 - {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Debug|x64 Setup.ActiveCfg = Debug|x64 - {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Debug|x86 Setup.ActiveCfg = Debug|Win32 - {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Release|Win32.ActiveCfg = Release|Win32 - {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Release|Win32.Build.0 = Release|Win32 - {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Release|x64.ActiveCfg = Release|x64 - {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Release|x64.Build.0 = Release|x64 - {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Release|x64 Setup.ActiveCfg = Release|x64 - {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Release|x86 Setup.ActiveCfg = Release|Win32 - {0D108721-EAE8-4BAF-8102-D8960EC93647}.All|Win32.ActiveCfg = Debug|x64 - {0D108721-EAE8-4BAF-8102-D8960EC93647}.All|x64.ActiveCfg = Debug|x64 - {0D108721-EAE8-4BAF-8102-D8960EC93647}.All|x64.Build.0 = Debug|x64 - {0D108721-EAE8-4BAF-8102-D8960EC93647}.All|x64 Setup.ActiveCfg = Debug|x64 - {0D108721-EAE8-4BAF-8102-D8960EC93647}.All|x64 Setup.Build.0 = Debug|x64 - {0D108721-EAE8-4BAF-8102-D8960EC93647}.All|x86 Setup.ActiveCfg = Debug|x64 - {0D108721-EAE8-4BAF-8102-D8960EC93647}.Debug|Win32.ActiveCfg = Debug|Win32 - {0D108721-EAE8-4BAF-8102-D8960EC93647}.Debug|Win32.Build.0 = Debug|Win32 - {0D108721-EAE8-4BAF-8102-D8960EC93647}.Debug|x64.ActiveCfg = Debug|x64 - {0D108721-EAE8-4BAF-8102-D8960EC93647}.Debug|x64.Build.0 = Debug|x64 - {0D108721-EAE8-4BAF-8102-D8960EC93647}.Debug|x64 Setup.ActiveCfg = Debug|x64 - {0D108721-EAE8-4BAF-8102-D8960EC93647}.Debug|x86 Setup.ActiveCfg = Debug|Win32 - {0D108721-EAE8-4BAF-8102-D8960EC93647}.Release|Win32.ActiveCfg = Release|Win32 - {0D108721-EAE8-4BAF-8102-D8960EC93647}.Release|Win32.Build.0 = Release|Win32 - {0D108721-EAE8-4BAF-8102-D8960EC93647}.Release|x64.ActiveCfg = Release|x64 - {0D108721-EAE8-4BAF-8102-D8960EC93647}.Release|x64.Build.0 = Release|x64 - {0D108721-EAE8-4BAF-8102-D8960EC93647}.Release|x64 Setup.ActiveCfg = Release|x64 - {0D108721-EAE8-4BAF-8102-D8960EC93647}.Release|x86 Setup.ActiveCfg = Release|Win32 - {B535402E-38D2-4D54-8360-423ACBD17192}.All|Win32.ActiveCfg = Release|x64 - {B535402E-38D2-4D54-8360-423ACBD17192}.All|x64.ActiveCfg = Release|x64 - {B535402E-38D2-4D54-8360-423ACBD17192}.All|x64.Build.0 = Release|x64 - {B535402E-38D2-4D54-8360-423ACBD17192}.All|x64 Setup.ActiveCfg = Release|x64 - {B535402E-38D2-4D54-8360-423ACBD17192}.All|x64 Setup.Build.0 = Release|x64 - {B535402E-38D2-4D54-8360-423ACBD17192}.All|x86 Setup.ActiveCfg = Release|x64 - {B535402E-38D2-4D54-8360-423ACBD17192}.Debug|Win32.ActiveCfg = Debug|Win32 - {B535402E-38D2-4D54-8360-423ACBD17192}.Debug|Win32.Build.0 = Debug|Win32 - {B535402E-38D2-4D54-8360-423ACBD17192}.Debug|x64.ActiveCfg = Debug|x64 - {B535402E-38D2-4D54-8360-423ACBD17192}.Debug|x64.Build.0 = Debug|x64 - {B535402E-38D2-4D54-8360-423ACBD17192}.Debug|x64 Setup.ActiveCfg = Debug|x64 - {B535402E-38D2-4D54-8360-423ACBD17192}.Debug|x86 Setup.ActiveCfg = Debug|Win32 - {B535402E-38D2-4D54-8360-423ACBD17192}.Release|Win32.ActiveCfg = Release|Win32 - {B535402E-38D2-4D54-8360-423ACBD17192}.Release|Win32.Build.0 = Release|Win32 - {B535402E-38D2-4D54-8360-423ACBD17192}.Release|x64.ActiveCfg = Release|x64 - {B535402E-38D2-4D54-8360-423ACBD17192}.Release|x64.Build.0 = Release|x64 - {B535402E-38D2-4D54-8360-423ACBD17192}.Release|x64 Setup.ActiveCfg = Release|x64 - {B535402E-38D2-4D54-8360-423ACBD17192}.Release|x86 Setup.ActiveCfg = Release|Win32 {4F92B672-DADB-4047-8D6A-4BB3796733FD}.All|Win32.ActiveCfg = Release|Win32 {4F92B672-DADB-4047-8D6A-4BB3796733FD}.All|Win32.Build.0 = Release|Win32 {4F92B672-DADB-4047-8D6A-4BB3796733FD}.All|x64.ActiveCfg = Release|Win32 @@ -3718,6 +3665,91 @@ Global {019DBD2A-273D-4BA4-BF86-B5EFE2ED76B1}.Release|x64.Build.0 = Release|x64 {019DBD2A-273D-4BA4-BF86-B5EFE2ED76B1}.Release|x64 Setup.ActiveCfg = Release|Win32 {019DBD2A-273D-4BA4-BF86-B5EFE2ED76B1}.Release|x86 Setup.ActiveCfg = Release|Win32 + {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.All|Win32.ActiveCfg = Release|x64 + {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.All|x64.ActiveCfg = Release|x64 + {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.All|x64.Build.0 = Release|x64 + {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.All|x64 Setup.ActiveCfg = Release|x64 + {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.All|x86 Setup.ActiveCfg = Release|x64 + {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Debug|Win32.ActiveCfg = Debug|Win32 + {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Debug|Win32.Build.0 = Debug|Win32 + {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Debug|x64.ActiveCfg = Debug|x64 + {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Debug|x64.Build.0 = Debug|x64 + {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Debug|x86 Setup.ActiveCfg = Debug|x64 + {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Release|Win32.ActiveCfg = Release|Win32 + {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Release|Win32.Build.0 = Release|Win32 + {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Release|x64.ActiveCfg = Release|x64 + {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Release|x64.Build.0 = Release|x64 + {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Release|x64 Setup.ActiveCfg = Release|x64 + {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Release|x86 Setup.ActiveCfg = Release|x64 + {BED7539C-0099-4A14-AD5D-30828F15A171}.All|Win32.ActiveCfg = Release|x64 + {BED7539C-0099-4A14-AD5D-30828F15A171}.All|x64.ActiveCfg = Release|x64 + {BED7539C-0099-4A14-AD5D-30828F15A171}.All|x64.Build.0 = Release|x64 + {BED7539C-0099-4A14-AD5D-30828F15A171}.All|x64 Setup.ActiveCfg = Release|x64 + {BED7539C-0099-4A14-AD5D-30828F15A171}.All|x86 Setup.ActiveCfg = Release|x64 + {BED7539C-0099-4A14-AD5D-30828F15A171}.Debug|Win32.ActiveCfg = Debug|Win32 + {BED7539C-0099-4A14-AD5D-30828F15A171}.Debug|Win32.Build.0 = Debug|Win32 + {BED7539C-0099-4A14-AD5D-30828F15A171}.Debug|x64.ActiveCfg = Debug|x64 + {BED7539C-0099-4A14-AD5D-30828F15A171}.Debug|x64.Build.0 = Debug|x64 + {BED7539C-0099-4A14-AD5D-30828F15A171}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {BED7539C-0099-4A14-AD5D-30828F15A171}.Debug|x86 Setup.ActiveCfg = Debug|x64 + {BED7539C-0099-4A14-AD5D-30828F15A171}.Release|Win32.ActiveCfg = Release|Win32 + {BED7539C-0099-4A14-AD5D-30828F15A171}.Release|Win32.Build.0 = Release|Win32 + {BED7539C-0099-4A14-AD5D-30828F15A171}.Release|x64.ActiveCfg = Release|x64 + {BED7539C-0099-4A14-AD5D-30828F15A171}.Release|x64.Build.0 = Release|x64 + {BED7539C-0099-4A14-AD5D-30828F15A171}.Release|x64 Setup.ActiveCfg = Release|x64 + {BED7539C-0099-4A14-AD5D-30828F15A171}.Release|x86 Setup.ActiveCfg = Release|x64 + {0D108721-EAE8-4BAF-8102-D8960EC93647}.All|Win32.ActiveCfg = Release|x64 + {0D108721-EAE8-4BAF-8102-D8960EC93647}.All|x64.ActiveCfg = Release|x64 + {0D108721-EAE8-4BAF-8102-D8960EC93647}.All|x64.Build.0 = Release|x64 + {0D108721-EAE8-4BAF-8102-D8960EC93647}.All|x64 Setup.ActiveCfg = Release|x64 + {0D108721-EAE8-4BAF-8102-D8960EC93647}.All|x86 Setup.ActiveCfg = Release|x64 + {0D108721-EAE8-4BAF-8102-D8960EC93647}.Debug|Win32.ActiveCfg = Debug|Win32 + {0D108721-EAE8-4BAF-8102-D8960EC93647}.Debug|Win32.Build.0 = Debug|Win32 + {0D108721-EAE8-4BAF-8102-D8960EC93647}.Debug|x64.ActiveCfg = Debug|x64 + {0D108721-EAE8-4BAF-8102-D8960EC93647}.Debug|x64.Build.0 = Debug|x64 + {0D108721-EAE8-4BAF-8102-D8960EC93647}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {0D108721-EAE8-4BAF-8102-D8960EC93647}.Debug|x86 Setup.ActiveCfg = Debug|x64 + {0D108721-EAE8-4BAF-8102-D8960EC93647}.Release|Win32.ActiveCfg = Release|Win32 + {0D108721-EAE8-4BAF-8102-D8960EC93647}.Release|Win32.Build.0 = Release|Win32 + {0D108721-EAE8-4BAF-8102-D8960EC93647}.Release|x64.ActiveCfg = Release|x64 + {0D108721-EAE8-4BAF-8102-D8960EC93647}.Release|x64.Build.0 = Release|x64 + {0D108721-EAE8-4BAF-8102-D8960EC93647}.Release|x64 Setup.ActiveCfg = Release|x64 + {0D108721-EAE8-4BAF-8102-D8960EC93647}.Release|x86 Setup.ActiveCfg = Release|x64 + {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.All|Win32.ActiveCfg = Release|x64 + {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.All|x64.ActiveCfg = Release|x64 + {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.All|x64.Build.0 = Release|x64 + {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.All|x64 Setup.ActiveCfg = Release|x64 + {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.All|x86 Setup.ActiveCfg = Release|x64 + {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Debug|Win32.ActiveCfg = Debug|Win32 + {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Debug|Win32.Build.0 = Debug|Win32 + {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Debug|x64.ActiveCfg = Debug|x64 + {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Debug|x64.Build.0 = Debug|x64 + {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Debug|x86 Setup.ActiveCfg = Debug|x64 + {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Release|Win32.ActiveCfg = Release|Win32 + {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Release|Win32.Build.0 = Release|Win32 + {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Release|x64.ActiveCfg = Release|x64 + {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Release|x64.Build.0 = Release|x64 + {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Release|x64 Setup.ActiveCfg = Release|x64 + {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Release|x86 Setup.ActiveCfg = Release|x64 + {B535402E-38D2-4D54-8360-423ACBD17192}.All|Win32.ActiveCfg = Release|x64 + {B535402E-38D2-4D54-8360-423ACBD17192}.All|x64.ActiveCfg = Release|x64 + {B535402E-38D2-4D54-8360-423ACBD17192}.All|x64.Build.0 = Release|x64 + {B535402E-38D2-4D54-8360-423ACBD17192}.All|x64 Setup.ActiveCfg = Release|x64 + {B535402E-38D2-4D54-8360-423ACBD17192}.All|x86 Setup.ActiveCfg = Release|x64 + {B535402E-38D2-4D54-8360-423ACBD17192}.Debug|Win32.ActiveCfg = Debug|Win32 + {B535402E-38D2-4D54-8360-423ACBD17192}.Debug|Win32.Build.0 = Debug|Win32 + {B535402E-38D2-4D54-8360-423ACBD17192}.Debug|x64.ActiveCfg = Debug|x64 + {B535402E-38D2-4D54-8360-423ACBD17192}.Debug|x64.Build.0 = Debug|x64 + {B535402E-38D2-4D54-8360-423ACBD17192}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {B535402E-38D2-4D54-8360-423ACBD17192}.Debug|x86 Setup.ActiveCfg = Debug|x64 + {B535402E-38D2-4D54-8360-423ACBD17192}.Release|Win32.ActiveCfg = Release|Win32 + {B535402E-38D2-4D54-8360-423ACBD17192}.Release|Win32.Build.0 = Release|Win32 + {B535402E-38D2-4D54-8360-423ACBD17192}.Release|x64.ActiveCfg = Release|x64 + {B535402E-38D2-4D54-8360-423ACBD17192}.Release|x64.Build.0 = Release|x64 + {B535402E-38D2-4D54-8360-423ACBD17192}.Release|x64 Setup.ActiveCfg = Release|x64 + {B535402E-38D2-4D54-8360-423ACBD17192}.Release|x86 Setup.ActiveCfg = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -3804,10 +3836,6 @@ Global {DF018947-0FFF-4EB3-BDEE-441DC81DA7A4} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} {4043FC6A-9A30-4577-8AD5-9B233C9575D8} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} {0A18A071-125E-442F-AFF7-A3F68ABECF99} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} - {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} - {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} - {0D108721-EAE8-4BAF-8102-D8960EC93647} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} - {B535402E-38D2-4D54-8360-423ACBD17192} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} {2F025EAD-99BD-40F5-B2CC-F0A28CAD7F2D} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} {94001A0E-A837-445C-8004-F918F10D0226} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} {0AD1177E-1FD8-4643-9391-431467A11084} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} @@ -3832,6 +3860,7 @@ Global {E4D29906-8B73-4F8A-B5F4-CA8BFA648F5A} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} {70A49BC2-7500-41D0-B75D-EDCC5BE987A0} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} {23B4D303-79FC-49E0-89E2-2280E7E28940} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} + {9DE35039-A8F6-4FBF-B1B6-EB527F802411} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} {26C82FCE-E0CF-4D10-A00C-D8E582FFEB53} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} {C13CC324-0032-4492-9A30-310A6BD64FF5} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} {019DBD2A-273D-4BA4-BF86-B5EFE2ED76B1} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B} @@ -3917,5 +3946,10 @@ Global {D331904D-A00A-4694-A5A3-FCFF64AB5DBE} = {E4D29906-8B73-4F8A-B5F4-CA8BFA648F5A} {B4B62169-5AD4-4559-8707-3D933AC5DB39} = {E4D29906-8B73-4F8A-B5F4-CA8BFA648F5A} {25BD39B1-C8BF-4676-A738-9CABD9C6BC79} = {E4D29906-8B73-4F8A-B5F4-CA8BFA648F5A} + {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9} = {9DE35039-A8F6-4FBF-B1B6-EB527F802411} + {BED7539C-0099-4A14-AD5D-30828F15A171} = {9DE35039-A8F6-4FBF-B1B6-EB527F802411} + {0D108721-EAE8-4BAF-8102-D8960EC93647} = {9DE35039-A8F6-4FBF-B1B6-EB527F802411} + {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA} = {9DE35039-A8F6-4FBF-B1B6-EB527F802411} + {B535402E-38D2-4D54-8360-423ACBD17192} = {9DE35039-A8F6-4FBF-B1B6-EB527F802411} EndGlobalSection EndGlobal diff --git a/configure.in b/configure.in index b8db9bc..89cf47d 100644 --- a/configure.in +++ b/configure.in @@ -497,9 +497,8 @@ AC_SUBST(LIBTOOL_LIB_EXTEN) # Checks for header files. AC_HEADER_DIRENT AC_HEADER_STDC -AC_CHECK_HEADERS([sys/types.h sys/resource.h sched.h wchar.h sys/filio.h sys/ioctl.h netdb.h execinfo.h]) +AC_CHECK_HEADERS([sys/types.h sys/resource.h sched.h wchar.h sys/filio.h sys/ioctl.h sys/select.h netdb.h execinfo.h]) -# for xmlrpc-c config.h if test x"$ac_cv_header_wchar_h" = xyes; then HAVE_WCHAR_H_DEFINE=1 else @@ -507,6 +506,31 @@ else fi AC_SUBST(HAVE_WCHAR_H_DEFINE) +# Needed by Abyss on Solaris: + +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: + +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) + +if test x"$ac_cv_header_sys_select_h" = xyes; then + HAVE_SYS_SELECT_H_DEFINE=1 +else + HAVE_SYS_SELECT_H_DEFINE=0 +fi +AC_SUBST(HAVE_SYS_SELECT_H_DEFINE) + # Checks for typedefs, structures, and compiler characteristics. AC_C_CONST AC_C_INLINE @@ -610,6 +634,7 @@ fi # xmlrpc-c checks # +AC_CHECK_FUNCS(setenv strtoll strtoull strtoq strtouq __strtoll __strtoull) HAVE_LIBWWW_SSL_DEFINE=0 AC_SUBST(HAVE_LIBWWW_SSL_DEFINE) @@ -1056,8 +1081,10 @@ AC_CONFIG_FILES([Makefile build/getg729.sh build/freeswitch.pc build/modmake.rules - libs/xmlrpc-c/include/xmlrpc-c/config.h libs/xmlrpc-c/xmlrpc_config.h + libs/xmlrpc-c/config.mk + libs/xmlrpc-c/srcdir.mk + libs/xmlrpc-c/stamp-h scripts/gentls_cert]) AM_CONDITIONAL(ISLINUX, [test `uname -s` = Linux]) diff --git a/libs/.gitignore b/libs/.gitignore index 1bc99bc..ed326e9 100644 --- a/libs/.gitignore +++ b/libs/.gitignore @@ -884,11 +884,14 @@ opal /win32/libshout/*/*/libshout.log /win32/pcre/pcre_chartables.c /win32/tmp*.bat -/xmlrpc-c/include/xmlrpc-c/config.h !/xmlrpc-c/include/xmlrpc-c/config.h.in /xmlrpc-c/stamp-h2 -/xmlrpc-c/xmlrpc_amconfig.h +/xmlrpc-c/examples/config.h +/xmlrpc-c/include/xmlrpc-c/config.h +/xmlrpc-c/transport_config.h +/xmlrpc-c/version.h /xmlrpc-c/xmlrpc_config.h +# /xmlrpc-c/xmlrpc_amconfig.h /yaml/ /yaml/config.h /yaml/stamp-h1 @@ -944,4 +947,3 @@ opal !/yaml/config/ltmain.sh !/yaml/config/missing !/yaml/configure - diff --git a/libs/win32/apr-util/libaprutil.2010.vcxproj.filters b/libs/win32/apr-util/libaprutil.2010.vcxproj.filters index 9ba92f9..c7cf5f2 100644 --- a/libs/win32/apr-util/libaprutil.2010.vcxproj.filters +++ b/libs/win32/apr-util/libaprutil.2010.vcxproj.filters @@ -46,6 +46,9 @@ {ee62af10-73ee-4af5-85d1-442efcd33aa2} + + {0ea472ce-22be-43c7-b06d-a50dd027a9fe} + @@ -174,8 +177,8 @@ Source Files\xlate - - + + Public Header Files diff --git a/libs/win32/xmlrpc-c/abyss.2008.vcproj b/libs/win32/xmlrpc-c/abyss.2008.vcproj new file mode 100644 index 0000000..4ade18c --- /dev/null +++ b/libs/win32/xmlrpc-c/abyss.2008.vcproj @@ -0,0 +1,410 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/win32/xmlrpc-c/abyss.2010.vcxproj b/libs/win32/xmlrpc-c/abyss.2010.vcxproj new file mode 100644 index 0000000..e35b99f --- /dev/null +++ b/libs/win32/xmlrpc-c/abyss.2010.vcxproj @@ -0,0 +1,197 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + abyss + {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9} + abyss + + + + StaticLibrary + false + MultiByte + + + StaticLibrary + false + MultiByte + + + StaticLibrary + false + MultiByte + + + StaticLibrary + false + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(PlatformName)\abyss\$(Configuration)\ + $(PlatformName)\abyss\$(Configuration)\ + $(PlatformName)\abyss\$(Configuration)\ + $(PlatformName)\abyss\$(Configuration)\ + + + + Disabled + ..\;..\include;..\lib\util\include;.;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_LIB;ABYSS_WIN32;_THREAD;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + Level3 + true + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + true + + + true + + + + + X64 + + + Disabled + ..\;..\include;..\lib\util\include;.;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_LIB;ABYSS_WIN32;_THREAD;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + Level3 + true + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + true + + + true + + + + + MaxSpeed + OnlyExplicitInline + ..\;..\include;..\lib\util\include;.;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;ABYSS_WIN32;_THREAD;%(PreprocessorDefinitions) + true + MultiThreadedDLL + true + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + true + + + true + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + ..\;..\include;..\lib\util\include;.;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;ABYSS_WIN32;_THREAD;%(PreprocessorDefinitions) + true + MultiThreadedDLL + true + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + true + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/win32/xmlrpc-c/abyss.2010.vcxproj.filters b/libs/win32/xmlrpc-c/abyss.2010.vcxproj.filters new file mode 100644 index 0000000..f73f272 --- /dev/null +++ b/libs/win32/xmlrpc-c/abyss.2010.vcxproj.filters @@ -0,0 +1,69 @@ + + + + + {8ac4971f-a9ba-4930-a7e3-b291ad24d6ca} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {05489d43-6c6b-4bb8-95db-414e8137ee9e} + h;hpp;hxx;hm;inl + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/libs/win32/xmlrpc-c/gennmtab.2008.vcproj b/libs/win32/xmlrpc-c/gennmtab.2008.vcproj new file mode 100644 index 0000000..a4a5b35 --- /dev/null +++ b/libs/win32/xmlrpc-c/gennmtab.2008.vcproj @@ -0,0 +1,404 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/win32/xmlrpc-c/gennmtab.2010.vcxproj b/libs/win32/xmlrpc-c/gennmtab.2010.vcxproj new file mode 100644 index 0000000..cb99ac4 --- /dev/null +++ b/libs/win32/xmlrpc-c/gennmtab.2010.vcxproj @@ -0,0 +1,304 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {BED7539C-0099-4A14-AD5D-30828F15A171} + gennmtab + + + + Application + false + + + Application + false + + + Application + false + + + Application + false + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(PlatformName)\$(Configuration)\ + $(PlatformName)\$(Configuration)\ + $(PlatformName)\gennmtab\$(Configuration)\ + $(PlatformName)\gennmtab\$(Configuration)\ + true + true + $(PlatformName)\$(Configuration)\ + $(PlatformName)\$(Configuration)\ + $(PlatformName)\gennmtab\$(Configuration)\ + $(PlatformName)\gennmtab\$(Configuration)\ + false + false + AllRules.ruleset + AllRules.ruleset + + + + + AllRules.ruleset + AllRules.ruleset + + + + + true + true + true + true + Clean + Clean + Clean + Clean + + + + .\Debug\gennmtab/gennmtab.tlb + + + + + Disabled + ..;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreadedDebug + Level3 + true + EditAndContinue + + + + + _DEBUG;%(PreprocessorDefinitions) + 0x0809 + + + true + true + Console + false + + + MachineX86 + + + true + .\Debug\gennmtab/gennmtab.bsc + + + Generating nametab.h ... + $(OutDir)$(TargetName) > $(XMLRPCDir)lib\expat\xmltok\nametab.h + + + + + + + del $(XMLRPCDir)lib\expat\xmltok\nametab.h + + + NoOutput + + + + + .\Debug\gennmtab/gennmtab.tlb + + + + + Disabled + ..;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDebug + + + Level3 + true + ProgramDatabase + + + _DEBUG;%(PreprocessorDefinitions) + 0x0809 + + + $(OutDir)$(TargetName)$(TargetExt) + true + true + Console + false + + + + + true + .\Debug\gennmtab/gennmtab.bsc + + + Generating nametab.h ... + $(OutDir)$(TargetName) > $(XMLRPCDir)lib\expat\xmltok\nametab.h + + + + + + + del $(XMLRPCDir)lib\expat\xmltok\nametab.h + + + NoOutput + + + + + .\Release\gennmtab/gennmtab.tlb + + + + + MaxSpeed + OnlyExplicitInline + ..;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + true + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x0809 + + + true + Console + false + + + MachineX86 + + + true + .\Release\gennmtab/gennmtab.bsc + + + Generating nametab.h ... + $(OutDir)$(TargetName) > $(XMLRPCDir)lib\expat\xmltok\nametab.h + + + + + + + NoOutput + del $(XMLRPCDir)lib\expat\xmltok\nametab.h + + + + + .\Release\gennmtab/gennmtab.tlb + + + + + MaxSpeed + OnlyExplicitInline + ..;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + true + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x0809 + + + $(OutDir)$(TargetName)$(TargetExt) + true + Console + false + + + + + true + .\Release\gennmtab/gennmtab.bsc + + + Generating nametab.h ... + $(OutDir)$(TargetName) > $(XMLRPCDir)lib\expat\xmltok\nametab.h + + + + + + + del $(XMLRPCDir)lib\expat\xmltok\nametab.h + + + NoOutput + + + + + + + + + \ No newline at end of file diff --git a/libs/win32/xmlrpc-c/xmlparse.2008.vcproj b/libs/win32/xmlrpc-c/xmlparse.2008.vcproj new file mode 100644 index 0000000..009c66a --- /dev/null +++ b/libs/win32/xmlrpc-c/xmlparse.2008.vcproj @@ -0,0 +1,394 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/win32/xmlrpc-c/xmlparse.2010.vcxproj b/libs/win32/xmlrpc-c/xmlparse.2010.vcxproj new file mode 100644 index 0000000..4d1b9ce --- /dev/null +++ b/libs/win32/xmlrpc-c/xmlparse.2010.vcxproj @@ -0,0 +1,254 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + xmlparse + {0D108721-EAE8-4BAF-8102-D8960EC93647} + xmlparse + + + + StaticLibrary + false + MultiByte + + + StaticLibrary + false + MultiByte + + + StaticLibrary + false + MultiByte + + + StaticLibrary + false + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(PlatformName)\xmlparse\$(Configuration)\ + $(PlatformName)\xmlparse\$(Configuration)\ + $(PlatformName)\xmlparse\$(Configuration)\ + $(PlatformName)\xmlparse\$(Configuration)\ + $(ProjectDir)..\version.h;$(ExtensionsToDeleteOnClean) + Clean + Clean + Clean + Clean + + + + MaxSpeed + OnlyExplicitInline + $(XMLRPCDir)lib\expat\xmltok;$(XMLRPCDir)lib\expat\xmlwf;%(AdditionalIncludeDirectories) + NDEBUG;WIN32;_WINDOWS;XML_DTD;_LIB;%(PreprocessorDefinitions) + true + MultiThreaded + true + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + true + + + true + + + if not exist "$(XMLRPCDir)version.h" ( +pushd $(XMLRPCDir)Windows +"ConfigureWin32.bat" +popd +) + + + + pushd $(XMLRPCDir)Windows +"$(XMLRPCDir)Windows\CleanWin32.bat" +popd + + NoOutput + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + $(XMLRPCDir)lib\expat\xmltok;$(XMLRPCDir)lib\expat\xmlwf;%(AdditionalIncludeDirectories) + NDEBUG;WIN32;_WINDOWS;XML_DTD;_LIB;%(PreprocessorDefinitions) + true + MultiThreaded + true + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + true + + + true + + + if not exist "$(XMLRPCDir)version.h" ( +pushd $(XMLRPCDir)Windows +"ConfigureWin32.bat" +popd +) + + + + pushd $(XMLRPCDir)Windows +"$(XMLRPCDir)Windows\CleanWin32.bat" +popd + + NoOutput + + + + + Disabled + $(XMLRPCDir)lib\expat\xmltok;$(XMLRPCDir)lib\expat\xmlwf;%(AdditionalIncludeDirectories) + WIN32;_WINDOWS;XML_DTD;_LIB;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + Level3 + true + ProgramDatabase + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + true + + + true + + + if not exist "$(XMLRPCDir)version.h" ( +pushd $(XMLRPCDir)Windows +"ConfigureWin32.bat" +popd +) + + + + pushd $(XMLRPCDir)Windows +"$(XMLRPCDir)Windows\CleanWin32.bat" +popd + + NoOutput + + + + + X64 + + + Disabled + $(XMLRPCDir)lib\expat\xmltok;$(XMLRPCDir)lib\expat\xmlwf;%(AdditionalIncludeDirectories) + WIN32;_WINDOWS;XML_DTD;_LIB;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + Level3 + true + ProgramDatabase + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + true + + + true + + + if not exist "$(XMLRPCDir)version.h" ( +pushd $(XMLRPCDir)Windows +"ConfigureWin32.bat" +popd +) + + + + pushd $(XMLRPCDir)Windows +"$(XMLRPCDir)Windows\CleanWin32.bat" +popd + + NoOutput + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/win32/xmlrpc-c/xmlrpc.2008.vcproj b/libs/win32/xmlrpc-c/xmlrpc.2008.vcproj new file mode 100644 index 0000000..2de82d7 --- /dev/null +++ b/libs/win32/xmlrpc-c/xmlrpc.2008.vcproj @@ -0,0 +1,490 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/win32/xmlrpc-c/xmlrpc.2010.vcxproj b/libs/win32/xmlrpc-c/xmlrpc.2010.vcxproj new file mode 100644 index 0000000..9902363 --- /dev/null +++ b/libs/win32/xmlrpc-c/xmlrpc.2010.vcxproj @@ -0,0 +1,240 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + xmlrpc + {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA} + xmlrpc + + + + StaticLibrary + false + MultiByte + + + StaticLibrary + false + MultiByte + + + StaticLibrary + false + MultiByte + + + StaticLibrary + false + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(PlatformName)\xmlrpc\$(Configuration)\ + $(PlatformName)\xmlrpc\$(Configuration)\ + $(PlatformName)\xmlrpc\$(Configuration)\ + $(PlatformName)\xmlrpc\$(Configuration)\ + + + + + + Disabled + $(XMLRPCDir)lib\expat\xmlparse;%(AdditionalIncludeDirectories) + _DEBUG;WIN32;_LIB;ABYSS_WIN32;CURL_STATICLIB;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + Level3 + true + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + true + + + true + + + + + + + + + X64 + + + Disabled + $(XMLRPCDir)lib\expat\xmlparse;%(AdditionalIncludeDirectories) + _DEBUG;WIN32;_LIB;ABYSS_WIN32;CURL_STATICLIB;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + Level3 + true + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + true + + + true + .\Debug\xmlrpc/xmlrpc.bsc + + + + + + + + + MaxSpeed + OnlyExplicitInline + $(XMLRPCDir)lib\expat\xmlparse;%(AdditionalIncludeDirectories) + NDEBUG;WIN32;_LIB;ABYSS_WIN32;CURL_STATICLIB;%(PreprocessorDefinitions) + true + MultiThreadedDLL + true + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + true + + + true + + + + + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + $(XMLRPCDir)lib\expat\xmlparse;%(AdditionalIncludeDirectories) + NDEBUG;WIN32;_LIB;ABYSS_WIN32;CURL_STATICLIB;%(PreprocessorDefinitions) + true + MultiThreadedDLL + true + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + true + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/win32/xmlrpc-c/xmlrpc.2010.vcxproj.filters b/libs/win32/xmlrpc-c/xmlrpc.2010.vcxproj.filters new file mode 100644 index 0000000..aa044ff --- /dev/null +++ b/libs/win32/xmlrpc-c/xmlrpc.2010.vcxproj.filters @@ -0,0 +1,125 @@ + + + + + {7ca2b8b9-bf59-4407-aedf-588e548fe34a} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;cc + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/libs/win32/xmlrpc-c/xmltok.2008.vcproj b/libs/win32/xmlrpc-c/xmltok.2008.vcproj new file mode 100644 index 0000000..71be879 --- /dev/null +++ b/libs/win32/xmlrpc-c/xmltok.2008.vcproj @@ -0,0 +1,378 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/win32/xmlrpc-c/xmltok.2010.vcxproj b/libs/win32/xmlrpc-c/xmltok.2010.vcxproj new file mode 100644 index 0000000..119ca26 --- /dev/null +++ b/libs/win32/xmlrpc-c/xmltok.2010.vcxproj @@ -0,0 +1,199 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + xmltok + {B535402E-38D2-4D54-8360-423ACBD17192} + xmltok + + + + StaticLibrary + false + MultiByte + + + StaticLibrary + false + MultiByte + + + StaticLibrary + false + MultiByte + + + StaticLibrary + false + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(PlatformName)\xmltok\$(Configuration)\ + $(PlatformName)\xmltok\$(Configuration)\ + $(PlatformName)\xmltok\$(Configuration)\ + $(PlatformName)\xmltok\$(Configuration)\ + + + + Disabled + %(AdditionalIncludeDirectories) + _DEBUG;WIN32;_WINDOWS;XML_DTD;XML_NS;_LIB;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + Level3 + true + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + true + + + true + .\Debug\xmltok/xmltok.bsc + + + + + X64 + + + Disabled + %(AdditionalIncludeDirectories) + _DEBUG;WIN32;_WINDOWS;XML_DTD;XML_NS;_LIB;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + Level3 + true + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + true + + + true + .\Debug\xmltok/xmltok.bsc + + + + + MaxSpeed + OnlyExplicitInline + %(AdditionalIncludeDirectories) + NDEBUG;XML_NS;WIN32;_WINDOWS;XML_DTD;_LIB;%(PreprocessorDefinitions) + true + MultiThreaded + true + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + true + + + true + .\Release\xmltok/xmltok.bsc + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + %(AdditionalIncludeDirectories) + NDEBUG;XML_NS;WIN32;_WINDOWS;XML_DTD;_LIB;%(PreprocessorDefinitions) + true + MultiThreaded + true + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + true + + + true + .\Release\xmltok/xmltok.bsc + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/win32/xmlrpc-c/xmltok.2010.vcxproj.filters b/libs/win32/xmlrpc-c/xmltok.2010.vcxproj.filters new file mode 100644 index 0000000..98d22a2 --- /dev/null +++ b/libs/win32/xmlrpc-c/xmltok.2010.vcxproj.filters @@ -0,0 +1,45 @@ + + + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + {e8ec3017-8580-49f6-b5b5-4ba1c66c9b58} + + + {cf3bec2c-9e12-4a6c-8d1c-495721118adf} + + + \ No newline at end of file diff --git a/libs/xmlrpc-c/.cvsignore b/libs/xmlrpc-c/.cvsignore deleted file mode 100644 index f007c35..0000000 --- a/libs/xmlrpc-c/.cvsignore +++ /dev/null @@ -1,18 +0,0 @@ -Makefile.config -autogen.sh -autom4te.cache -configure -config.log -stamp-h -stamp-h1 -config.cache -libtool -config.status -xmlrpc_config.h -xmlrpc_amconfig.h -xmlrpc-c-config -xmlrpc-c-config.test -xmlrpc-c-*.tar.gz -xmlrpc-c.spec -transport_config.h - diff --git a/libs/xmlrpc-c/.update b/libs/xmlrpc-c/.update deleted file mode 100644 index 60fffd1..0000000 --- a/libs/xmlrpc-c/.update +++ /dev/null @@ -1 +0,0 @@ -date diff --git a/libs/xmlrpc-c/GNUmakefile b/libs/xmlrpc-c/GNUmakefile index be7e423..976e92c 100644 --- a/libs/xmlrpc-c/GNUmakefile +++ b/libs/xmlrpc-c/GNUmakefile @@ -1,4 +1,4 @@ -include Makefile.srcdir +include srcdir.mk BLDDIR = $(CURDIR) SUBDIR = @@ -6,7 +6,6 @@ SUBDIR = export SRCDIR export BLDDIR -include $(BLDDIR)/Makefile.version include $(BLDDIR)/config.mk SUBDIRS = include lib src tools examples @@ -24,10 +23,25 @@ SUBDIRS = include lib src tools examples DEFAULT_SUBDIRS = include lib src +ifeq ($(BUILD_TOOLS),yes) + DEFAULT_SUBDIRS += tools +endif + PROGRAMS_TO_INSTALL = xmlrpc-c-config default: xmlrpc-c-config xmlrpc-c-config.test $(DEFAULT_SUBDIRS:%=%/all) +# 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 + +# We don't want common.mk's rule for xmlrpc-c-config.test: +OMIT_XMLRPC_C_CONFIG_TEST = Y + +include $(SRCDIR)/common.mk + .PHONY: all all: xmlrpc-c-config xmlrpc-c-config.test $(SUBDIRS:%=%/all) @@ -61,22 +75,15 @@ src/all: lib/all MAJOR := $(XMLRPC_MAJOR_RELEASE) MINOR := $(XMLRPC_MINOR_RELEASE) POINT := $(XMLRPC_POINT_RELEASE) -version.h: $(SRCDIR)/Makefile.version +version.h: $(SRCDIR)/version.mk rm -f $@ echo "/* Generated by make file rule */" >>$@ - echo "#define XMLRPC_C_VERSION" \ - \"Xmlrpc-c $(MAJOR).$(MINOR).$(POINT)"\"" >>$@ + echo "#define XMLRPC_C_VERSION" \"$(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 - -include transport_config.make +include transport_config.mk # shell_config is a fragment to place inside a Bourne shell program that # sets variables that tell how the build is configured. @@ -94,17 +101,15 @@ shell_config: $(BLDDIR)/config.mk @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 'NEED_WL_RPATH="$(NEED_WL_RPATH)"' >>$@ + @echo 'LIBXMLRPCPP_NAME="$(LIBXMLRPCPP_NAME)"' >>$@ @echo 'LSOCKET="$(LSOCKET)"' >>$@ @echo 'WININET_LDADD="$(WININET_LDADD)"' >>$@ - @echo 'WININET_RPATH="$(WININET_RPATH)"' >>$@ - @echo 'WININET_WL_RPATH="$(WININET_WL_RPATH)"' >>$@ + @echo 'WININET_LIBDIR="$(WININET_LIBDIR)"' >>$@ @echo 'CURL_LDADD="$(CURL_LDADD)"' >>$@ - @echo 'CURL_RPATH="$(CURL_RPATH)"' >>$@ - @echo 'CURL_WL_RPATH="$(CURL_WL_RPATH)"' >>$@ + @echo 'CURL_LIBDIR="$(CURL_LIBDIR)"' >>$@ @echo 'LIBWWW_LDADD="$(LIBWWW_LDADD)"' >>$@ - @echo 'LIBWWW_RPATH="$(LIBWWW_RPATH)"' >>$@ - @echo 'LIBWWW_WL_RPATH="$(LIBWWW_WL_RPATH)"' >>$@ + @echo 'LIBWWW_LIBDIR="$(LIBWWW_LIBDIR)"' >>$@ @echo 'XMLRPC_MAJOR_RELEASE="$(XMLRPC_MAJOR_RELEASE)"' >>$@ @echo 'XMLRPC_MINOR_RELEASE="$(XMLRPC_MINOR_RELEASE)"' >>$@ @echo 'XMLRPC_POINT_RELEASE="$(XMLRPC_POINT_RELEASE)"' >>$@ @@ -116,9 +121,6 @@ shell_config: $(BLDDIR)/config.mk @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 "Echoes to '$@' suppressed here ..." @@ -140,7 +142,7 @@ clean-local: distclean: $(SUBDIRS:%=%/distclean) distclean-common distclean-local distclean-local: clean-local - rm -f config.log config.status config.mk Makefile.srcdir + rm -f config.log config.status config.mk srcdir.mk rm -f xmlrpc_config.h xmlrpc_amconfig.h stamp-h rm -f shell_config xmlrpc-c-config xmlrpc-c-config.test rm -f TAGS @@ -162,11 +164,8 @@ xmlrpc_config.h xmlrpc_amconfig.h \ :%:%.in $(SRCDIR)/configure $(SRCDIR)/configure -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. +# you don't have a srcdir.mk, which means $(SRCDIR) is null. /common.mk: @echo ======================================= diff --git a/libs/xmlrpc-c/Makefile.common b/libs/xmlrpc-c/Makefile.common deleted file mode 100644 index bf51040..0000000 --- a/libs/xmlrpc-c/Makefile.common +++ /dev/null @@ -1,272 +0,0 @@ -# -*-makefile-*- <-- an Emacs control - -# 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. -# BUILDDIR: Name of directory which is the top of the Xmlrpc-c build tree. - -LIBTOOL = $(SRCDIR)/libtool -LINK = $(LIBTOOL) --mode=link $(CCLD) - -GCC_WARNINGS = -Wall -Wundef -Wimplicit -W -Winline - # 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 - -ifeq ($(C_COMPILER_GNU),yes) - CFLAGS_COMMON = $(GCC_C_WARNINGS) $(COMPILER_CFLAGS) -fno-common -g -else - CFLAGS_COMMON = $(COMPILER_CFLAGS) -endif - -ifeq ($(CXX_COMPILER_GNU),yes) - CXXFLAGS_COMMON = $(GCC_CXX_WARNINGS) $(COMPILER_CXXFLAGS) -else - CXXFLAGS_COMMON = $(COMPILER_CXXFLAGS) -endif - -DISTDIR = $(BUILDDIR)/$(PACKAGE)-$(VERSION)/$(SUBDIR) - -LDFLAGS_VERSINFO = -version-info 7:0:4 - -# CURDIR was introduced in GNU Make 3.77. -ifeq ($(CURDIR)x,x) - CURDIR := $(shell /bin/pwd) -endif - -############################################################################## -# RULES # -############################################################################## - -$(SUBDIRS:%=%/all): %/all: $(CURDIR)/% - $(MAKE) -C $(dir $@) -f $(SRCDIR)/$(SUBDIR)/$(dir $@)Makefile \ - $(notdir $@) - -$(SUBDIRS:%=%/install): %/install: $(CURDIR)/% - $(MAKE) -C $(dir $@) -f $(SRCDIR)/$(SUBDIR)/$(dir $@)Makefile \ - $(notdir $@) - -$(SUBDIRS:%=%/clean): %/clean: $(CURDIR)/% - $(MAKE) -C $(dir $@) -f $(SRCDIR)/$(SUBDIR)/$(dir $@)Makefile \ - $(notdir $@) - -$(SUBDIRS:%=%/distclean): %/distclean: $(CURDIR)/% - $(MAKE) -C $(dir $@) -f $(SRCDIR)/$(SUBDIR)/$(dir $@)Makefile \ - $(notdir $@) - -$(SUBDIRS:%=%/distdir): %/distdir: $(CURDIR)/% - $(MAKE) -C $(dir $@) -f $(SRCDIR)/$(SUBDIR)/$(dir $@)Makefile \ - $(notdir $@) - -$(SUBDIRS:%=%/dep): %/dep: $(CURDIR)/% - $(MAKE) -C $(dir $@) -f $(SRCDIR)/$(SUBDIR)/$(dir $@)Makefile \ - $(notdir $@) - -$(BUILDDIR)/lib/util/casprintf.lo: FORCE - $(MAKE) -C $(dir $@) -f $(SRCDIR)/lib/util/Makefile $(notdir $@) - -$(BUILDDIR)/lib/expat/xmlparse/libxmlrpc_xmlparse.la: FORCE - $(MAKE) -C $(dir $@) -f $(SRCDIR)/lib/expat/xmlparse/Makefile \ - $(notdir $@) - -$(BUILDDIR)/lib/expat/xmltok/libxmlrpc_xmltok.la: FORCE - $(MAKE) -C $(dir $@) -f $(SRCDIR)/lib/expat/xmltok/Makefile \ - $(notdir $@) - -$(BUILDDIR)/lib/wininet_transport/xmlrpc_wininet_transport.lo: FORCE - $(MAKE) -C $(dir $@) -f $(SRCDIR)/lib/wininet_transport/Makefile \ - $(notdir $@) - -$(BUILDDIR)/lib/curl_transport/xmlrpc_curl_transport.lo: FORCE - $(MAKE) -C $(dir $@) -f $(SRCDIR)/lib/curl_transport/Makefile \ - $(notdir $@) - -$(BUILDDIR)/lib/libwww_transport/xmlrpc_libwww_transport.lo: FORCE - $(MAKE) -C $(dir $@) -f $(SRCDIR)/lib/libwww_transport/Makefile \ - $(notdir $@) - -$(BUILDDIR)/src/libxmlrpc.la: FORCE - $(MAKE) -C $(dir $@) -f $(SRCDIR)/src/Makefile \ - $(notdir $@) - -$(BUILDDIR)/src/libxmlrpc_client.la: FORCE - $(MAKE) -C $(dir $@) -f $(SRCDIR)/src/Makefile \ - $(notdir $@) - -$(BUILDDIR)/src/libxmlrpc_server.la: FORCE - $(MAKE) -C $(dir $@) -f $(SRCDIR)/src/Makefile \ - $(notdir $@) - -ifneq ($(OMIT_TRANSPORT_CONFIG_H),Y) -$(BUILDDIR)/transport_config.h: - $(MAKE) -C $(dir $@) $(notdir $@) -endif - -MKINSTALLDIRS = $(SHELL) $(SRCDIR)/mkinstalldirs - -.PHONY: install-common install-libraries install-headers install-bin -install-common: \ - install-ltlibraries install-libraries install-headers install-bin - -INSTALL_LIB_CMD = $(INSTALL_DATA) $$p $(DESTDIR)$(LIBINST_DIR)/$$p -RANLIB_CMD = $(RANLIB) $(DESTDIR)$(LIBINST_DIR)/$$p - -install-libraries: $(LIBRARIES_TO_INSTALL) - $(MKINSTALLDIRS) $(DESTDIR)$(LIBINST_DIR) - @list='$(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='$(LIBRARIES_TO_INSTALL)'; for p in $$list; do \ - if test -f $$p; then \ - echo " $(RANLIB_CMD)"; \ - $(RANLIB_CMD); \ - else :; fi; \ - done - -LIBTOOL_INSTALL_CMD = $(LIBTOOL) --mode=install \ - $(INSTALL) $$p $(DESTDIR)$(LIBINST_DIR)/$$p - -install-ltlibraries: $(LTLIBRARIES_TO_INSTALL) - $(MKINSTALLDIRS) $(DESTDIR)$(LIBINST_DIR) - @list='$(LTLIBRARIES_TO_INSTALL)'; for p in $$list; do \ - if test -f $$p; then \ - echo " $(LIBTOOL_INSTALL_CMD)"; \ - $(LIBTOOL_INSTALL_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)/"; fi; \ - echo " $(INSTALL_HDR_CMD)"; \ - $(INSTALL_HDR_CMD); \ - done - - -INSTALL_PROGRAM_CMD = $(LIBTOOL) --mode=install $(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) $@ - - -.PHONY: clean-common -clean-common: - rm -f *.o *.a *.s *.i *.la *.lo - rm -rf .libs - -.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 empty out Makefile.depend here. The developer must do 'make dep' if -# he wants to edit and rebuild. -# -# Other projects have 'make distclean' _remove_ Makefile.depend and then -# have 'make' automatically build Makefile.depend. 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. -# - cat /dev/null >Makefile.depend - rm -f TAGS - - -.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 - -TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) - tags=; \ - here=`pwd`; \ - list='$(SUBDIRS)'; for subdir in $$list; do \ - if test "$$subdir" = .; then :; else \ - test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ - fi; \ - done; \ - list='$(SOURCES) $(HEADERS)'; \ - unique=`for i in $$list; do echo $$i; done | \ - awk ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ - test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ - || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) - -DEP_SOURCES = $(wildcard *.c *.cpp) - -# This is a filter to turn "foo.o:" rules into "foo.o foo.lo:" because Libtool -# uses .lo for object files. I'd like to purge the build of Libtool some day -# and eliminate this complication. - -LIBTOOL_DEPEND_MASSAGER = perl -walnpe's{^(.*)\.o:}{$$1.o $$1.lo:}' - - - -.PHONY: dep-common -dep-common: FORCE -ifneq ($(DEP_SOURCES)x,x) - -$(CC) -MM -MG -I. $(INCLUDES) $(DEP_SOURCES) | \ - $(LIBTOOL_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: diff --git a/libs/xmlrpc-c/Makefile.config.in b/libs/xmlrpc-c/Makefile.config.in deleted file mode 100644 index efdcf4f..0000000 --- a/libs/xmlrpc-c/Makefile.config.in +++ /dev/null @@ -1,79 +0,0 @@ -# Makefile.config is generated by 'configure' using Makefile.config.in -# as a template and information that 'configure' gathers from the build -# system and from user options. - -# Makefile.config should someday replace most of the other files that -# 'configure' generates, thus simplifying development and customization. -# Makefile.config 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. Makefile.config -# 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@ -ENABLE_EFENCE = @ENABLE_EFENCE@ - -MUST_BUILD_WININET_CLIENT = @MUST_BUILD_WININET_CLIENT@ -MUST_BUILD_CURL_CLIENT = @MUST_BUILD_CURL_CLIENT@ -MUST_BUILD_LIBWWW_CLIENT = @MUST_BUILD_LIBWWW_CLIENT@ - -LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ -LIBXML2_LIBS = @LIBXML2_LIBS@ - -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 - -# 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 = @INSTALL@ - -C_COMPILER_GNU = @C_COMPILER_GNU@ -CXX_COMPILER_GNU = @CXX_COMPILER_GNU@ -COMPILER_CFLAGS = @COMPILER_CFLAGS@ -COMPILER_CXXFLAGS = @COMPILER_CXXFLAGS@ - -# Here are the commands 'make install' uses to install various kinds of files: - -INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ - -# Here are the locations at which 'make install' puts files: - -# DESTDIR is designed to be overriden at make time in order to relocate -# the entire install into a subdirectory. -DESTDIR = - -exec_prefix = @exec_prefix@ -prefix = @prefix@ -LIBINST_DIR = @libdir@ -HEADERINST_DIR = @includedir@ -PROGRAMINST_DIR = @bindir@ diff --git a/libs/xmlrpc-c/Makefile.depend b/libs/xmlrpc-c/Makefile.depend deleted file mode 100644 index e69de29..0000000 diff --git a/libs/xmlrpc-c/Makefile.srcdir.in b/libs/xmlrpc-c/Makefile.srcdir.in deleted file mode 100644 index d389df1..0000000 --- a/libs/xmlrpc-c/Makefile.srcdir.in +++ /dev/null @@ -1 +0,0 @@ -SRCDIR=@abs_srcdir@ diff --git a/libs/xmlrpc-c/Makefile.version b/libs/xmlrpc-c/Makefile.version deleted file mode 100644 index 6dc75a2..0000000 --- a/libs/xmlrpc-c/Makefile.version +++ /dev/null @@ -1,11 +0,0 @@ -############################################################################### -# 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 diff --git a/libs/xmlrpc-c/Windows/CleanWin32.bat b/libs/xmlrpc-c/Windows/CleanWin32.bat index 907b32b..181c3aa 100644 --- a/libs/xmlrpc-c/Windows/CleanWin32.bat +++ b/libs/xmlrpc-c/Windows/CleanWin32.bat @@ -1,43 +1,30 @@ -@echo Windows build -@echo This batch file deletes the copied header files, -@echo Deleting Win32 header files... -@echo ##################################################### -@echo IF YOU HAVE MADE CHANGES IN ..\xmlrpc_config.h, ..\include\xmlrpc-c\config.h etc ... -@echo THESE CHANGES WILL BE LOST! -@echo You should run diffcfg.bat first to check for changes, -@echo and updcfg.bat if you have made changes ... -@echo ##################################################### -@echo ARE YOU SURE YOU WANT TO DO THIS? Ctrl+C to abort ... -@echo ##################################################### -@pause -@set TEMP1= -@if NOT EXIST ..\include\xmlrpc-c\config.h goto DN1 -del ..\include\xmlrpc-c\config.h > nul -@set TEMP1=%TEMP1% ..\include\xmlrpc-c\config.h -:DN1 -@if NOT EXIST ..\xmlrpc_config.h goto DN2 -del ..\xmlrpc_config.h > nul -@set TEMP1=%TEMP1% ..\xmlrpc_config.h -:DN2 -@if NOT EXIST ..\transport_config.h goto DN3 -del ..\transport_config.h > nul -@set TEMP1=%TEMP1% ..\transport_config.h -:DN3 -@if NOT EXIST ..\version.h goto DN4 -del ..\version.h > nul -@set TEMP1=%TEMP1% ..\version.h -:DN4 -@if NOT EXIST ..\examples\config.h goto DN5 -del ..\examples\config.h > nul -@set TEMP1=%TEMP1% ..\examples\config.h -:DN5 -@if "%TEMP1%." == "." goto ALLDN -@echo DELETED win32 header files. -@echo %TEMP1% -@goto END - -:ALLDN -@echo NOne to DELETE ... -@goto END - -:END +@if NOT EXIST ..\include\xmlrpc-c\config.h goto DN1 +del ..\include\xmlrpc-c\config.h > nul +@set TEMP1=%TEMP1% ..\include\xmlrpc-c\config.h +:DN1 +@if NOT EXIST ..\xmlrpc_config.h goto DN2 +del ..\xmlrpc_config.h > nul +@set TEMP1=%TEMP1% ..\xmlrpc_config.h +:DN2 +@if NOT EXIST ..\transport_config.h goto DN3 +del ..\transport_config.h > nul +@set TEMP1=%TEMP1% ..\transport_config.h +:DN3 +@if NOT EXIST ..\version.h goto DN4 +del ..\version.h > nul +@set TEMP1=%TEMP1% ..\version.h +:DN4 +@if NOT EXIST ..\examples\config.h goto DN5 +del ..\examples\config.h > nul +@set TEMP1=%TEMP1% ..\examples\config.h +:DN5 +@if "%TEMP1%." == "." goto ALLDN +@echo DELETED win32 header files. +@echo %TEMP1% +@goto END + +:ALLDN +@echo NOne to DELETE ... +@goto END + +:END diff --git a/libs/xmlrpc-c/Windows/ReadMeWin32.txt b/libs/xmlrpc-c/Windows/ReadMeWin32.txt index 2da1575..1178159 100644 --- a/libs/xmlrpc-c/Windows/ReadMeWin32.txt +++ b/libs/xmlrpc-c/Windows/ReadMeWin32.txt @@ -1,11 +1,13 @@ 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 +------------------------------------------------------------------------- +These instructions are for static link libraries, using Microsoft Visual +Studio 7 and later. There are project files to create DLLs, using +Visual Studio 2008 or later, in the 'dll' subdirectory. People maintain +those project files separately from the rest of the build system, so it's +not uncommon for something to work with one but not the other. +------------------------------------------------------------------------- 1. Run the batch file ConfigureWin32.bat, found in the Windows diff --git a/libs/xmlrpc-c/Windows/abyss.2008.vcproj b/libs/xmlrpc-c/Windows/abyss.2008.vcproj deleted file mode 100644 index 45508db..0000000 --- a/libs/xmlrpc-c/Windows/abyss.2008.vcproj +++ /dev/null @@ -1,1298 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libs/xmlrpc-c/Windows/abyss.2010.vcxproj b/libs/xmlrpc-c/Windows/abyss.2010.vcxproj deleted file mode 100644 index 8f366a8..0000000 --- a/libs/xmlrpc-c/Windows/abyss.2010.vcxproj +++ /dev/null @@ -1,437 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - abyss - {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9} - abyss - - - - StaticLibrary - false - MultiByte - - - StaticLibrary - false - MultiByte - - - StaticLibrary - false - MultiByte - - - StaticLibrary - false - MultiByte - - - - - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(PlatformName)\abyss\$(Configuration)\ - $(PlatformName)\abyss\$(Configuration)\ - $(PlatformName)\abyss\$(Configuration)\ - $(PlatformName)\abyss\$(Configuration)\ - - - - Disabled - ..\;..\include;..\lib\util\include;.;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_LIB;ABYSS_WIN32;_THREAD;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebugDLL - Level3 - true - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - true - - - true - .\Debug\abyss/abyss.bsc - - - - - X64 - - - Disabled - ..\;..\include;..\lib\util\include;.;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_LIB;ABYSS_WIN32;_THREAD;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebugDLL - Level3 - true - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - true - - - true - .\Debug\abyss/abyss.bsc - - - - - MaxSpeed - OnlyExplicitInline - ..\;..\include;..\lib\util\include;.;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_LIB;ABYSS_WIN32;_THREAD;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level3 - true - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - - true - - - true - .\Release\Abyss/abyss.bsc - - - - - X64 - - - MaxSpeed - OnlyExplicitInline - ..\;..\include;..\lib\util\include;.;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_LIB;ABYSS_WIN32;_THREAD;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level3 - true - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - - true - - - true - .\Release\Abyss/abyss.bsc - - - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/libs/xmlrpc-c/Windows/abyss.2010.vcxproj.filters b/libs/xmlrpc-c/Windows/abyss.2010.vcxproj.filters deleted file mode 100644 index 63a3cb3..0000000 --- a/libs/xmlrpc-c/Windows/abyss.2010.vcxproj.filters +++ /dev/null @@ -1,131 +0,0 @@ - - - - - {8ac4971f-a9ba-4930-a7e3-b291ad24d6ca} - cpp;c;cxx;rc;def;r;odl;idl;hpj;bat - - - {05489d43-6c6b-4bb8-95db-414e8137ee9e} - h;hpp;hxx;hm;inl - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - \ No newline at end of file diff --git a/libs/xmlrpc-c/Windows/cpptest.dsp b/libs/xmlrpc-c/Windows/cpptest.dsp index 9db8ccc..4058491 100644 --- a/libs/xmlrpc-c/Windows/cpptest.dsp +++ b/libs/xmlrpc-c/Windows/cpptest.dsp @@ -85,6 +85,10 @@ LINK32=link.exe # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File +SOURCE=..\src\cpp\test\value.cpp +# End Source File +# Begin Source File + SOURCE=..\src\cpp\test\registry.cpp # End Source File # Begin Source File @@ -94,7 +98,6 @@ SOURCE=..\src\cpp\test\server_abyss.cpp # Begin Source File SOURCE=..\src\cpp\test\server_pstream.cpp -# PROP Exclude_From_Build 1 # End Source File # Begin Source File @@ -108,6 +111,10 @@ SOURCE=..\src\cpp\test\testclient_dummy.cpp SOURCE=..\src\cpp\test\tools.cpp # End Source File +# Begin Source File + +SOURCE=.\socketpair.cpp +# End Source File # End Group # Begin Group "Header Files" diff --git a/libs/xmlrpc-c/Windows/curllink.h b/libs/xmlrpc-c/Windows/curllink.h index 516fec0..090e4bf 100644 --- a/libs/xmlrpc-c/Windows/curllink.h +++ b/libs/xmlrpc-c/Windows/curllink.h @@ -1,18 +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" ) +/* 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" ) diff --git a/libs/xmlrpc-c/Windows/dll/cpptest.vcproj b/libs/xmlrpc-c/Windows/dll/cpptest.vcproj new file mode 100644 index 0000000..dcffa92 --- /dev/null +++ b/libs/xmlrpc-c/Windows/dll/cpptest.vcproj @@ -0,0 +1,482 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/xmlrpc-c/Windows/dll/gennmtab.vcproj b/libs/xmlrpc-c/Windows/dll/gennmtab.vcproj new file mode 100644 index 0000000..0336147 --- /dev/null +++ b/libs/xmlrpc-c/Windows/dll/gennmtab.vcproj @@ -0,0 +1,449 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/xmlrpc-c/Windows/dll/rpctest.vcproj b/libs/xmlrpc-c/Windows/dll/rpctest.vcproj new file mode 100644 index 0000000..3b5bfba --- /dev/null +++ b/libs/xmlrpc-c/Windows/dll/rpctest.vcproj @@ -0,0 +1,574 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/xmlrpc-c/Windows/dll/sample_add_asynch_client.vcproj b/libs/xmlrpc-c/Windows/dll/sample_add_asynch_client.vcproj new file mode 100644 index 0000000..d5145ae --- /dev/null +++ b/libs/xmlrpc-c/Windows/dll/sample_add_asynch_client.vcproj @@ -0,0 +1,443 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/xmlrpc-c/Windows/dll/sample_add_server.vcproj b/libs/xmlrpc-c/Windows/dll/sample_add_server.vcproj new file mode 100644 index 0000000..6060a06 --- /dev/null +++ b/libs/xmlrpc-c/Windows/dll/sample_add_server.vcproj @@ -0,0 +1,433 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/xmlrpc-c/Windows/dll/sample_add_server_w32httpsys.vcproj b/libs/xmlrpc-c/Windows/dll/sample_add_server_w32httpsys.vcproj new file mode 100644 index 0000000..e4e7a74 --- /dev/null +++ b/libs/xmlrpc-c/Windows/dll/sample_add_server_w32httpsys.vcproj @@ -0,0 +1,433 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/xmlrpc-c/Windows/dll/sample_add_sync_client.vcproj b/libs/xmlrpc-c/Windows/dll/sample_add_sync_client.vcproj new file mode 100644 index 0000000..9151e8e --- /dev/null +++ b/libs/xmlrpc-c/Windows/dll/sample_add_sync_client.vcproj @@ -0,0 +1,435 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/xmlrpc-c/Windows/dll/sample_auth_client.vcproj b/libs/xmlrpc-c/Windows/dll/sample_auth_client.vcproj new file mode 100644 index 0000000..07aeb90 --- /dev/null +++ b/libs/xmlrpc-c/Windows/dll/sample_auth_client.vcproj @@ -0,0 +1,435 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/xmlrpc-c/Windows/dll/tool_xmlrpc-transport.vcproj b/libs/xmlrpc-c/Windows/dll/tool_xmlrpc-transport.vcproj new file mode 100644 index 0000000..1f35057 --- /dev/null +++ b/libs/xmlrpc-c/Windows/dll/tool_xmlrpc-transport.vcproj @@ -0,0 +1,430 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/xmlrpc-c/Windows/dll/tool_xmlrpc.vcproj b/libs/xmlrpc-c/Windows/dll/tool_xmlrpc.vcproj new file mode 100644 index 0000000..9708e11 --- /dev/null +++ b/libs/xmlrpc-c/Windows/dll/tool_xmlrpc.vcproj @@ -0,0 +1,430 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/xmlrpc-c/Windows/dll/xmlrpc.sln b/libs/xmlrpc-c/Windows/dll/xmlrpc.sln new file mode 100644 index 0000000..814b373 --- /dev/null +++ b/libs/xmlrpc-c/Windows/dll/xmlrpc.sln @@ -0,0 +1,327 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libxmlrpc_xmlparse", "xmlrpc_xmlparse.vcproj", "{40B0756D-AFEE-4A38-9F38-A372CE431404}" + ProjectSection(ProjectDependencies) = postProject + {BD9F6041-A272-462D-8C41-87CEF1F11408} = {BD9F6041-A272-462D-8C41-87CEF1F11408} + {29FBABB6-E36A-4559-9514-B3DAF6AE1416} = {29FBABB6-E36A-4559-9514-B3DAF6AE1416} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libxmlrpc_xmltok", "xmlrpc_xmltok.vcproj", "{BD9F6041-A272-462D-8C41-87CEF1F11408}" + ProjectSection(ProjectDependencies) = postProject + {99BD200E-A4D5-4ED4-9D00-A6A19EFE1412} = {99BD200E-A4D5-4ED4-9D00-A6A19EFE1412} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gennmtab", "gennmtab.vcproj", "{99BD200E-A4D5-4ED4-9D00-A6A19EFE1412}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libxmlrpc_util", "xmlrpc_util.vcproj", "{29FBABB6-E36A-4559-9514-B3DAF6AE1416}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libxmlrpc", "xmlrpc.vcproj", "{226AB06F-60CA-4B21-9040-C6ECC0581522}" + ProjectSection(ProjectDependencies) = postProject + {40B0756D-AFEE-4A38-9F38-A372CE431404} = {40B0756D-AFEE-4A38-9F38-A372CE431404} + {29FBABB6-E36A-4559-9514-B3DAF6AE1416} = {29FBABB6-E36A-4559-9514-B3DAF6AE1416} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libxmlrpc_abyss", "xmlrpc_abyss.vcproj", "{20A8F64B-F738-4D32-A798-A65AD8291541}" + ProjectSection(ProjectDependencies) = postProject + {29FBABB6-E36A-4559-9514-B3DAF6AE1416} = {29FBABB6-E36A-4559-9514-B3DAF6AE1416} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libxmlrpc_server", "xmlrpc_server.vcproj", "{74B67128-BC84-4BCB-A256-9286B6371552}" + ProjectSection(ProjectDependencies) = postProject + {226AB06F-60CA-4B21-9040-C6ECC0581522} = {226AB06F-60CA-4B21-9040-C6ECC0581522} + {29FBABB6-E36A-4559-9514-B3DAF6AE1416} = {29FBABB6-E36A-4559-9514-B3DAF6AE1416} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libxmlrpc_server_abyss", "xmlrpc_server_abyss.vcproj", "{E98186CB-F1B0-40A6-87A5-77B13A3F1600}" + ProjectSection(ProjectDependencies) = postProject + {74B67128-BC84-4BCB-A256-9286B6371552} = {74B67128-BC84-4BCB-A256-9286B6371552} + {20A8F64B-F738-4D32-A798-A65AD8291541} = {20A8F64B-F738-4D32-A798-A65AD8291541} + {226AB06F-60CA-4B21-9040-C6ECC0581522} = {226AB06F-60CA-4B21-9040-C6ECC0581522} + {29FBABB6-E36A-4559-9514-B3DAF6AE1416} = {29FBABB6-E36A-4559-9514-B3DAF6AE1416} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libxmlrpc_server_cgi", "xmlrpc_server_cgi.vcproj", "{A2AAAF37-F382-4A11-8D86-53B589921616}" + ProjectSection(ProjectDependencies) = postProject + {74B67128-BC84-4BCB-A256-9286B6371552} = {74B67128-BC84-4BCB-A256-9286B6371552} + {226AB06F-60CA-4B21-9040-C6ECC0581522} = {226AB06F-60CA-4B21-9040-C6ECC0581522} + {29FBABB6-E36A-4559-9514-B3DAF6AE1416} = {29FBABB6-E36A-4559-9514-B3DAF6AE1416} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libxmlrpc_server_w32httpsys", "xmlrpc_server_w32httpsys.vcproj", "{0EECB080-FC8F-4C46-9FB7-5DB22F9D1622}" + ProjectSection(ProjectDependencies) = postProject + {74B67128-BC84-4BCB-A256-9286B6371552} = {74B67128-BC84-4BCB-A256-9286B6371552} + {226AB06F-60CA-4B21-9040-C6ECC0581522} = {226AB06F-60CA-4B21-9040-C6ECC0581522} + {29FBABB6-E36A-4559-9514-B3DAF6AE1416} = {29FBABB6-E36A-4559-9514-B3DAF6AE1416} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libxmlrpc_client", "xmlrpc_client.vcproj", "{28BB53D9-D487-41DF-BBB3-FDB5846D1630}" + ProjectSection(ProjectDependencies) = postProject + {226AB06F-60CA-4B21-9040-C6ECC0581522} = {226AB06F-60CA-4B21-9040-C6ECC0581522} + {29FBABB6-E36A-4559-9514-B3DAF6AE1416} = {29FBABB6-E36A-4559-9514-B3DAF6AE1416} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample_add_asynch_client", "sample_add_asynch_client.vcproj", "{2D4A179E-E2BA-4ED9-934E-7E54C08F1652}" + ProjectSection(ProjectDependencies) = postProject + {226AB06F-60CA-4B21-9040-C6ECC0581522} = {226AB06F-60CA-4B21-9040-C6ECC0581522} + {29FBABB6-E36A-4559-9514-B3DAF6AE1416} = {29FBABB6-E36A-4559-9514-B3DAF6AE1416} + {28BB53D9-D487-41DF-BBB3-FDB5846D1630} = {28BB53D9-D487-41DF-BBB3-FDB5846D1630} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample_add_server", "sample_add_server.vcproj", "{BEEB1B9C-BAF4-4B54-AB51-891156301702}" + ProjectSection(ProjectDependencies) = postProject + {74B67128-BC84-4BCB-A256-9286B6371552} = {74B67128-BC84-4BCB-A256-9286B6371552} + {226AB06F-60CA-4B21-9040-C6ECC0581522} = {226AB06F-60CA-4B21-9040-C6ECC0581522} + {29FBABB6-E36A-4559-9514-B3DAF6AE1416} = {29FBABB6-E36A-4559-9514-B3DAF6AE1416} + {E98186CB-F1B0-40A6-87A5-77B13A3F1600} = {E98186CB-F1B0-40A6-87A5-77B13A3F1600} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample_add_server_w32httpsys", "sample_add_server_w32httpsys.vcproj", "{B6887828-9480-4D4D-9CFC-AE4980D41707}" + ProjectSection(ProjectDependencies) = postProject + {74B67128-BC84-4BCB-A256-9286B6371552} = {74B67128-BC84-4BCB-A256-9286B6371552} + {226AB06F-60CA-4B21-9040-C6ECC0581522} = {226AB06F-60CA-4B21-9040-C6ECC0581522} + {0EECB080-FC8F-4C46-9FB7-5DB22F9D1622} = {0EECB080-FC8F-4C46-9FB7-5DB22F9D1622} + {29FBABB6-E36A-4559-9514-B3DAF6AE1416} = {29FBABB6-E36A-4559-9514-B3DAF6AE1416} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample_add_sync_client", "sample_add_sync_client.vcproj", "{A7A81BBD-C84D-479A-A9BD-194ADA3B1710}" + ProjectSection(ProjectDependencies) = postProject + {226AB06F-60CA-4B21-9040-C6ECC0581522} = {226AB06F-60CA-4B21-9040-C6ECC0581522} + {29FBABB6-E36A-4559-9514-B3DAF6AE1416} = {29FBABB6-E36A-4559-9514-B3DAF6AE1416} + {28BB53D9-D487-41DF-BBB3-FDB5846D1630} = {28BB53D9-D487-41DF-BBB3-FDB5846D1630} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample_auth_client", "sample_auth_client.vcproj", "{29A2BBC4-9ED9-4162-817C-FEEB36FB1714}" + ProjectSection(ProjectDependencies) = postProject + {226AB06F-60CA-4B21-9040-C6ECC0581522} = {226AB06F-60CA-4B21-9040-C6ECC0581522} + {29FBABB6-E36A-4559-9514-B3DAF6AE1416} = {29FBABB6-E36A-4559-9514-B3DAF6AE1416} + {28BB53D9-D487-41DF-BBB3-FDB5846D1630} = {28BB53D9-D487-41DF-BBB3-FDB5846D1630} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rpctest", "rpctest.vcproj", "{4CFB235E-56AE-4BF2-BE67-8FD4AF5F1722}" + ProjectSection(ProjectDependencies) = postProject + {74B67128-BC84-4BCB-A256-9286B6371552} = {74B67128-BC84-4BCB-A256-9286B6371552} + {20A8F64B-F738-4D32-A798-A65AD8291541} = {20A8F64B-F738-4D32-A798-A65AD8291541} + {40B0756D-AFEE-4A38-9F38-A372CE431404} = {40B0756D-AFEE-4A38-9F38-A372CE431404} + {226AB06F-60CA-4B21-9040-C6ECC0581522} = {226AB06F-60CA-4B21-9040-C6ECC0581522} + {29FBABB6-E36A-4559-9514-B3DAF6AE1416} = {29FBABB6-E36A-4559-9514-B3DAF6AE1416} + {E98186CB-F1B0-40A6-87A5-77B13A3F1600} = {E98186CB-F1B0-40A6-87A5-77B13A3F1600} + {28BB53D9-D487-41DF-BBB3-FDB5846D1630} = {28BB53D9-D487-41DF-BBB3-FDB5846D1630} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libxmlrpc++", "xmlrpc__.vcproj", "{3E7064F3-6200-4C39-85BE-775931D21828}" + ProjectSection(ProjectDependencies) = postProject + {74B67128-BC84-4BCB-A256-9286B6371552} = {74B67128-BC84-4BCB-A256-9286B6371552} + {20A8F64B-F738-4D32-A798-A65AD8291541} = {20A8F64B-F738-4D32-A798-A65AD8291541} + {226AB06F-60CA-4B21-9040-C6ECC0581522} = {226AB06F-60CA-4B21-9040-C6ECC0581522} + {29FBABB6-E36A-4559-9514-B3DAF6AE1416} = {29FBABB6-E36A-4559-9514-B3DAF6AE1416} + {E98186CB-F1B0-40A6-87A5-77B13A3F1600} = {E98186CB-F1B0-40A6-87A5-77B13A3F1600} + {28BB53D9-D487-41DF-BBB3-FDB5846D1630} = {28BB53D9-D487-41DF-BBB3-FDB5846D1630} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpptest", "cpptest.vcproj", "{26FB3E14-7E0C-4B0C-AB1E-CFE4B48A1856}" + ProjectSection(ProjectDependencies) = postProject + {74B67128-BC84-4BCB-A256-9286B6371552} = {74B67128-BC84-4BCB-A256-9286B6371552} + {20A8F64B-F738-4D32-A798-A65AD8291541} = {20A8F64B-F738-4D32-A798-A65AD8291541} + {226AB06F-60CA-4B21-9040-C6ECC0581522} = {226AB06F-60CA-4B21-9040-C6ECC0581522} + {29FBABB6-E36A-4559-9514-B3DAF6AE1416} = {29FBABB6-E36A-4559-9514-B3DAF6AE1416} + {28BB53D9-D487-41DF-BBB3-FDB5846D1630} = {28BB53D9-D487-41DF-BBB3-FDB5846D1630} + {3E7064F3-6200-4C39-85BE-775931D21828} = {3E7064F3-6200-4C39-85BE-775931D21828} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xmlrpc", "tool_xmlrpc.vcproj", "{4CFB235E-56AE-4BF2-BE67-8FD4AF5F1940}" + ProjectSection(ProjectDependencies) = postProject + {226AB06F-60CA-4B21-9040-C6ECC0581522} = {226AB06F-60CA-4B21-9040-C6ECC0581522} + {29FBABB6-E36A-4559-9514-B3DAF6AE1416} = {29FBABB6-E36A-4559-9514-B3DAF6AE1416} + {28BB53D9-D487-41DF-BBB3-FDB5846D1630} = {28BB53D9-D487-41DF-BBB3-FDB5846D1630} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xmlrpc_transport", "tool_xmlrpc-transport.vcproj", "{4CFB235E-56AE-4BF2-BE67-8FD4AF5F1942}" + ProjectSection(ProjectDependencies) = postProject + {74B67128-BC84-4BCB-A256-9286B6371552} = {74B67128-BC84-4BCB-A256-9286B6371552} + {226AB06F-60CA-4B21-9040-C6ECC0581522} = {226AB06F-60CA-4B21-9040-C6ECC0581522} + {29FBABB6-E36A-4559-9514-B3DAF6AE1416} = {29FBABB6-E36A-4559-9514-B3DAF6AE1416} + {28BB53D9-D487-41DF-BBB3-FDB5846D1630} = {28BB53D9-D487-41DF-BBB3-FDB5846D1630} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {40B0756D-AFEE-4A38-9F38-A372CE431404}.Debug|Win32.ActiveCfg = Debug|Win32 + {40B0756D-AFEE-4A38-9F38-A372CE431404}.Debug|Win32.Build.0 = Debug|Win32 + {40B0756D-AFEE-4A38-9F38-A372CE431404}.Debug|x64.ActiveCfg = Debug|x64 + {40B0756D-AFEE-4A38-9F38-A372CE431404}.Debug|x64.Build.0 = Debug|x64 + {40B0756D-AFEE-4A38-9F38-A372CE431404}.Release|Win32.ActiveCfg = Release|Win32 + {40B0756D-AFEE-4A38-9F38-A372CE431404}.Release|Win32.Build.0 = Release|Win32 + {40B0756D-AFEE-4A38-9F38-A372CE431404}.Release|x64.ActiveCfg = Release|x64 + {40B0756D-AFEE-4A38-9F38-A372CE431404}.Release|x64.Build.0 = Release|x64 + {BD9F6041-A272-462D-8C41-87CEF1F11408}.Debug|Win32.ActiveCfg = Debug|Win32 + {BD9F6041-A272-462D-8C41-87CEF1F11408}.Debug|Win32.Build.0 = Debug|Win32 + {BD9F6041-A272-462D-8C41-87CEF1F11408}.Debug|x64.ActiveCfg = Debug|x64 + {BD9F6041-A272-462D-8C41-87CEF1F11408}.Debug|x64.Build.0 = Debug|x64 + {BD9F6041-A272-462D-8C41-87CEF1F11408}.Release|Win32.ActiveCfg = Release|Win32 + {BD9F6041-A272-462D-8C41-87CEF1F11408}.Release|Win32.Build.0 = Release|Win32 + {BD9F6041-A272-462D-8C41-87CEF1F11408}.Release|x64.ActiveCfg = Release|x64 + {BD9F6041-A272-462D-8C41-87CEF1F11408}.Release|x64.Build.0 = Release|x64 + {99BD200E-A4D5-4ED4-9D00-A6A19EFE1412}.Debug|Win32.ActiveCfg = Debug|Win32 + {99BD200E-A4D5-4ED4-9D00-A6A19EFE1412}.Debug|Win32.Build.0 = Debug|Win32 + {99BD200E-A4D5-4ED4-9D00-A6A19EFE1412}.Debug|x64.ActiveCfg = Debug|x64 + {99BD200E-A4D5-4ED4-9D00-A6A19EFE1412}.Debug|x64.Build.0 = Debug|x64 + {99BD200E-A4D5-4ED4-9D00-A6A19EFE1412}.Release|Win32.ActiveCfg = Release|Win32 + {99BD200E-A4D5-4ED4-9D00-A6A19EFE1412}.Release|Win32.Build.0 = Release|Win32 + {99BD200E-A4D5-4ED4-9D00-A6A19EFE1412}.Release|x64.ActiveCfg = Release|x64 + {99BD200E-A4D5-4ED4-9D00-A6A19EFE1412}.Release|x64.Build.0 = Release|x64 + {29FBABB6-E36A-4559-9514-B3DAF6AE1416}.Debug|Win32.ActiveCfg = Debug|Win32 + {29FBABB6-E36A-4559-9514-B3DAF6AE1416}.Debug|Win32.Build.0 = Debug|Win32 + {29FBABB6-E36A-4559-9514-B3DAF6AE1416}.Debug|x64.ActiveCfg = Debug|x64 + {29FBABB6-E36A-4559-9514-B3DAF6AE1416}.Debug|x64.Build.0 = Debug|x64 + {29FBABB6-E36A-4559-9514-B3DAF6AE1416}.Release|Win32.ActiveCfg = Release|Win32 + {29FBABB6-E36A-4559-9514-B3DAF6AE1416}.Release|Win32.Build.0 = Release|Win32 + {29FBABB6-E36A-4559-9514-B3DAF6AE1416}.Release|x64.ActiveCfg = Release|x64 + {29FBABB6-E36A-4559-9514-B3DAF6AE1416}.Release|x64.Build.0 = Release|x64 + {226AB06F-60CA-4B21-9040-C6ECC0581522}.Debug|Win32.ActiveCfg = Debug|Win32 + {226AB06F-60CA-4B21-9040-C6ECC0581522}.Debug|Win32.Build.0 = Debug|Win32 + {226AB06F-60CA-4B21-9040-C6ECC0581522}.Debug|x64.ActiveCfg = Debug|x64 + {226AB06F-60CA-4B21-9040-C6ECC0581522}.Debug|x64.Build.0 = Debug|x64 + {226AB06F-60CA-4B21-9040-C6ECC0581522}.Release|Win32.ActiveCfg = Release|Win32 + {226AB06F-60CA-4B21-9040-C6ECC0581522}.Release|Win32.Build.0 = Release|Win32 + {226AB06F-60CA-4B21-9040-C6ECC0581522}.Release|x64.ActiveCfg = Release|x64 + {226AB06F-60CA-4B21-9040-C6ECC0581522}.Release|x64.Build.0 = Release|x64 + {20A8F64B-F738-4D32-A798-A65AD8291541}.Debug|Win32.ActiveCfg = Debug|Win32 + {20A8F64B-F738-4D32-A798-A65AD8291541}.Debug|Win32.Build.0 = Debug|Win32 + {20A8F64B-F738-4D32-A798-A65AD8291541}.Debug|x64.ActiveCfg = Debug|x64 + {20A8F64B-F738-4D32-A798-A65AD8291541}.Debug|x64.Build.0 = Debug|x64 + {20A8F64B-F738-4D32-A798-A65AD8291541}.Release|Win32.ActiveCfg = Release|Win32 + {20A8F64B-F738-4D32-A798-A65AD8291541}.Release|Win32.Build.0 = Release|Win32 + {20A8F64B-F738-4D32-A798-A65AD8291541}.Release|x64.ActiveCfg = Release|x64 + {20A8F64B-F738-4D32-A798-A65AD8291541}.Release|x64.Build.0 = Release|x64 + {74B67128-BC84-4BCB-A256-9286B6371552}.Debug|Win32.ActiveCfg = Debug|Win32 + {74B67128-BC84-4BCB-A256-9286B6371552}.Debug|Win32.Build.0 = Debug|Win32 + {74B67128-BC84-4BCB-A256-9286B6371552}.Debug|x64.ActiveCfg = Debug|x64 + {74B67128-BC84-4BCB-A256-9286B6371552}.Debug|x64.Build.0 = Debug|x64 + {74B67128-BC84-4BCB-A256-9286B6371552}.Release|Win32.ActiveCfg = Release|Win32 + {74B67128-BC84-4BCB-A256-9286B6371552}.Release|Win32.Build.0 = Release|Win32 + {74B67128-BC84-4BCB-A256-9286B6371552}.Release|x64.ActiveCfg = Release|x64 + {74B67128-BC84-4BCB-A256-9286B6371552}.Release|x64.Build.0 = Release|x64 + {E98186CB-F1B0-40A6-87A5-77B13A3F1600}.Debug|Win32.ActiveCfg = Debug|Win32 + {E98186CB-F1B0-40A6-87A5-77B13A3F1600}.Debug|Win32.Build.0 = Debug|Win32 + {E98186CB-F1B0-40A6-87A5-77B13A3F1600}.Debug|x64.ActiveCfg = Debug|x64 + {E98186CB-F1B0-40A6-87A5-77B13A3F1600}.Debug|x64.Build.0 = Debug|x64 + {E98186CB-F1B0-40A6-87A5-77B13A3F1600}.Release|Win32.ActiveCfg = Release|Win32 + {E98186CB-F1B0-40A6-87A5-77B13A3F1600}.Release|Win32.Build.0 = Release|Win32 + {E98186CB-F1B0-40A6-87A5-77B13A3F1600}.Release|x64.ActiveCfg = Release|x64 + {E98186CB-F1B0-40A6-87A5-77B13A3F1600}.Release|x64.Build.0 = Release|x64 + {A2AAAF37-F382-4A11-8D86-53B589921616}.Debug|Win32.ActiveCfg = Debug|Win32 + {A2AAAF37-F382-4A11-8D86-53B589921616}.Debug|Win32.Build.0 = Debug|Win32 + {A2AAAF37-F382-4A11-8D86-53B589921616}.Debug|x64.ActiveCfg = Debug|x64 + {A2AAAF37-F382-4A11-8D86-53B589921616}.Debug|x64.Build.0 = Debug|x64 + {A2AAAF37-F382-4A11-8D86-53B589921616}.Release|Win32.ActiveCfg = Release|Win32 + {A2AAAF37-F382-4A11-8D86-53B589921616}.Release|Win32.Build.0 = Release|Win32 + {A2AAAF37-F382-4A11-8D86-53B589921616}.Release|x64.ActiveCfg = Release|x64 + {A2AAAF37-F382-4A11-8D86-53B589921616}.Release|x64.Build.0 = Release|x64 + {0EECB080-FC8F-4C46-9FB7-5DB22F9D1622}.Debug|Win32.ActiveCfg = Debug|Win32 + {0EECB080-FC8F-4C46-9FB7-5DB22F9D1622}.Debug|Win32.Build.0 = Debug|Win32 + {0EECB080-FC8F-4C46-9FB7-5DB22F9D1622}.Debug|x64.ActiveCfg = Debug|x64 + {0EECB080-FC8F-4C46-9FB7-5DB22F9D1622}.Debug|x64.Build.0 = Debug|x64 + {0EECB080-FC8F-4C46-9FB7-5DB22F9D1622}.Release|Win32.ActiveCfg = Release|Win32 + {0EECB080-FC8F-4C46-9FB7-5DB22F9D1622}.Release|Win32.Build.0 = Release|Win32 + {0EECB080-FC8F-4C46-9FB7-5DB22F9D1622}.Release|x64.ActiveCfg = Release|x64 + {0EECB080-FC8F-4C46-9FB7-5DB22F9D1622}.Release|x64.Build.0 = Release|x64 + {28BB53D9-D487-41DF-BBB3-FDB5846D1630}.Debug|Win32.ActiveCfg = Debug|Win32 + {28BB53D9-D487-41DF-BBB3-FDB5846D1630}.Debug|Win32.Build.0 = Debug|Win32 + {28BB53D9-D487-41DF-BBB3-FDB5846D1630}.Debug|x64.ActiveCfg = Debug|x64 + {28BB53D9-D487-41DF-BBB3-FDB5846D1630}.Debug|x64.Build.0 = Debug|x64 + {28BB53D9-D487-41DF-BBB3-FDB5846D1630}.Release|Win32.ActiveCfg = Release|Win32 + {28BB53D9-D487-41DF-BBB3-FDB5846D1630}.Release|Win32.Build.0 = Release|Win32 + {28BB53D9-D487-41DF-BBB3-FDB5846D1630}.Release|x64.ActiveCfg = Release|x64 + {28BB53D9-D487-41DF-BBB3-FDB5846D1630}.Release|x64.Build.0 = Release|x64 + {2D4A179E-E2BA-4ED9-934E-7E54C08F1652}.Debug|Win32.ActiveCfg = Debug|Win32 + {2D4A179E-E2BA-4ED9-934E-7E54C08F1652}.Debug|Win32.Build.0 = Debug|Win32 + {2D4A179E-E2BA-4ED9-934E-7E54C08F1652}.Debug|x64.ActiveCfg = Debug|x64 + {2D4A179E-E2BA-4ED9-934E-7E54C08F1652}.Debug|x64.Build.0 = Debug|x64 + {2D4A179E-E2BA-4ED9-934E-7E54C08F1652}.Release|Win32.ActiveCfg = Release|Win32 + {2D4A179E-E2BA-4ED9-934E-7E54C08F1652}.Release|Win32.Build.0 = Release|Win32 + {2D4A179E-E2BA-4ED9-934E-7E54C08F1652}.Release|x64.ActiveCfg = Release|x64 + {2D4A179E-E2BA-4ED9-934E-7E54C08F1652}.Release|x64.Build.0 = Release|x64 + {BEEB1B9C-BAF4-4B54-AB51-891156301702}.Debug|Win32.ActiveCfg = Debug|Win32 + {BEEB1B9C-BAF4-4B54-AB51-891156301702}.Debug|Win32.Build.0 = Debug|Win32 + {BEEB1B9C-BAF4-4B54-AB51-891156301702}.Debug|x64.ActiveCfg = Debug|x64 + {BEEB1B9C-BAF4-4B54-AB51-891156301702}.Debug|x64.Build.0 = Debug|x64 + {BEEB1B9C-BAF4-4B54-AB51-891156301702}.Release|Win32.ActiveCfg = Release|Win32 + {BEEB1B9C-BAF4-4B54-AB51-891156301702}.Release|Win32.Build.0 = Release|Win32 + {BEEB1B9C-BAF4-4B54-AB51-891156301702}.Release|x64.ActiveCfg = Release|x64 + {BEEB1B9C-BAF4-4B54-AB51-891156301702}.Release|x64.Build.0 = Release|x64 + {B6887828-9480-4D4D-9CFC-AE4980D41707}.Debug|Win32.ActiveCfg = Debug|Win32 + {B6887828-9480-4D4D-9CFC-AE4980D41707}.Debug|Win32.Build.0 = Debug|Win32 + {B6887828-9480-4D4D-9CFC-AE4980D41707}.Debug|x64.ActiveCfg = Debug|x64 + {B6887828-9480-4D4D-9CFC-AE4980D41707}.Debug|x64.Build.0 = Debug|x64 + {B6887828-9480-4D4D-9CFC-AE4980D41707}.Release|Win32.ActiveCfg = Release|Win32 + {B6887828-9480-4D4D-9CFC-AE4980D41707}.Release|Win32.Build.0 = Release|Win32 + {B6887828-9480-4D4D-9CFC-AE4980D41707}.Release|x64.ActiveCfg = Release|x64 + {B6887828-9480-4D4D-9CFC-AE4980D41707}.Release|x64.Build.0 = Release|x64 + {A7A81BBD-C84D-479A-A9BD-194ADA3B1710}.Debug|Win32.ActiveCfg = Debug|Win32 + {A7A81BBD-C84D-479A-A9BD-194ADA3B1710}.Debug|Win32.Build.0 = Debug|Win32 + {A7A81BBD-C84D-479A-A9BD-194ADA3B1710}.Debug|x64.ActiveCfg = Debug|x64 + {A7A81BBD-C84D-479A-A9BD-194ADA3B1710}.Debug|x64.Build.0 = Debug|x64 + {A7A81BBD-C84D-479A-A9BD-194ADA3B1710}.Release|Win32.ActiveCfg = Release|Win32 + {A7A81BBD-C84D-479A-A9BD-194ADA3B1710}.Release|Win32.Build.0 = Release|Win32 + {A7A81BBD-C84D-479A-A9BD-194ADA3B1710}.Release|x64.ActiveCfg = Release|x64 + {A7A81BBD-C84D-479A-A9BD-194ADA3B1710}.Release|x64.Build.0 = Release|x64 + {29A2BBC4-9ED9-4162-817C-FEEB36FB1714}.Debug|Win32.ActiveCfg = Debug|Win32 + {29A2BBC4-9ED9-4162-817C-FEEB36FB1714}.Debug|Win32.Build.0 = Debug|Win32 + {29A2BBC4-9ED9-4162-817C-FEEB36FB1714}.Debug|x64.ActiveCfg = Debug|x64 + {29A2BBC4-9ED9-4162-817C-FEEB36FB1714}.Debug|x64.Build.0 = Debug|x64 + {29A2BBC4-9ED9-4162-817C-FEEB36FB1714}.Release|Win32.ActiveCfg = Release|Win32 + {29A2BBC4-9ED9-4162-817C-FEEB36FB1714}.Release|Win32.Build.0 = Release|Win32 + {29A2BBC4-9ED9-4162-817C-FEEB36FB1714}.Release|x64.ActiveCfg = Release|x64 + {29A2BBC4-9ED9-4162-817C-FEEB36FB1714}.Release|x64.Build.0 = Release|x64 + {4CFB235E-56AE-4BF2-BE67-8FD4AF5F1722}.Debug|Win32.ActiveCfg = Debug|Win32 + {4CFB235E-56AE-4BF2-BE67-8FD4AF5F1722}.Debug|Win32.Build.0 = Debug|Win32 + {4CFB235E-56AE-4BF2-BE67-8FD4AF5F1722}.Debug|x64.ActiveCfg = Debug|x64 + {4CFB235E-56AE-4BF2-BE67-8FD4AF5F1722}.Debug|x64.Build.0 = Debug|x64 + {4CFB235E-56AE-4BF2-BE67-8FD4AF5F1722}.Release|Win32.ActiveCfg = Release|Win32 + {4CFB235E-56AE-4BF2-BE67-8FD4AF5F1722}.Release|Win32.Build.0 = Release|Win32 + {4CFB235E-56AE-4BF2-BE67-8FD4AF5F1722}.Release|x64.ActiveCfg = Release|x64 + {4CFB235E-56AE-4BF2-BE67-8FD4AF5F1722}.Release|x64.Build.0 = Release|x64 + {3E7064F3-6200-4C39-85BE-775931D21828}.Debug|Win32.ActiveCfg = Debug|Win32 + {3E7064F3-6200-4C39-85BE-775931D21828}.Debug|Win32.Build.0 = Debug|Win32 + {3E7064F3-6200-4C39-85BE-775931D21828}.Debug|x64.ActiveCfg = Debug|x64 + {3E7064F3-6200-4C39-85BE-775931D21828}.Debug|x64.Build.0 = Debug|x64 + {3E7064F3-6200-4C39-85BE-775931D21828}.Release|Win32.ActiveCfg = Release|Win32 + {3E7064F3-6200-4C39-85BE-775931D21828}.Release|Win32.Build.0 = Release|Win32 + {3E7064F3-6200-4C39-85BE-775931D21828}.Release|x64.ActiveCfg = Release|x64 + {3E7064F3-6200-4C39-85BE-775931D21828}.Release|x64.Build.0 = Release|x64 + {26FB3E14-7E0C-4B0C-AB1E-CFE4B48A1856}.Debug|Win32.ActiveCfg = Debug|Win32 + {26FB3E14-7E0C-4B0C-AB1E-CFE4B48A1856}.Debug|Win32.Build.0 = Debug|Win32 + {26FB3E14-7E0C-4B0C-AB1E-CFE4B48A1856}.Debug|x64.ActiveCfg = Debug|x64 + {26FB3E14-7E0C-4B0C-AB1E-CFE4B48A1856}.Debug|x64.Build.0 = Debug|x64 + {26FB3E14-7E0C-4B0C-AB1E-CFE4B48A1856}.Release|Win32.ActiveCfg = Release|Win32 + {26FB3E14-7E0C-4B0C-AB1E-CFE4B48A1856}.Release|Win32.Build.0 = Release|Win32 + {26FB3E14-7E0C-4B0C-AB1E-CFE4B48A1856}.Release|x64.ActiveCfg = Release|x64 + {26FB3E14-7E0C-4B0C-AB1E-CFE4B48A1856}.Release|x64.Build.0 = Release|x64 + {4CFB235E-56AE-4BF2-BE67-8FD4AF5F1940}.Debug|Win32.ActiveCfg = Debug|Win32 + {4CFB235E-56AE-4BF2-BE67-8FD4AF5F1940}.Debug|Win32.Build.0 = Debug|Win32 + {4CFB235E-56AE-4BF2-BE67-8FD4AF5F1940}.Debug|x64.ActiveCfg = Debug|x64 + {4CFB235E-56AE-4BF2-BE67-8FD4AF5F1940}.Debug|x64.Build.0 = Debug|x64 + {4CFB235E-56AE-4BF2-BE67-8FD4AF5F1940}.Release|Win32.ActiveCfg = Release|Win32 + {4CFB235E-56AE-4BF2-BE67-8FD4AF5F1940}.Release|Win32.Build.0 = Release|Win32 + {4CFB235E-56AE-4BF2-BE67-8FD4AF5F1940}.Release|x64.ActiveCfg = Release|x64 + {4CFB235E-56AE-4BF2-BE67-8FD4AF5F1940}.Release|x64.Build.0 = Release|x64 + {4CFB235E-56AE-4BF2-BE67-8FD4AF5F1942}.Debug|Win32.ActiveCfg = Debug|Win32 + {4CFB235E-56AE-4BF2-BE67-8FD4AF5F1942}.Debug|Win32.Build.0 = Debug|Win32 + {4CFB235E-56AE-4BF2-BE67-8FD4AF5F1942}.Debug|x64.ActiveCfg = Debug|x64 + {4CFB235E-56AE-4BF2-BE67-8FD4AF5F1942}.Debug|x64.Build.0 = Debug|x64 + {4CFB235E-56AE-4BF2-BE67-8FD4AF5F1942}.Release|Win32.ActiveCfg = Release|Win32 + {4CFB235E-56AE-4BF2-BE67-8FD4AF5F1942}.Release|Win32.Build.0 = Release|Win32 + {4CFB235E-56AE-4BF2-BE67-8FD4AF5F1942}.Release|x64.ActiveCfg = Release|x64 + {4CFB235E-56AE-4BF2-BE67-8FD4AF5F1942}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/libs/xmlrpc-c/Windows/dll/xmlrpc.vcproj b/libs/xmlrpc-c/Windows/dll/xmlrpc.vcproj new file mode 100644 index 0000000..bd1515e --- /dev/null +++ b/libs/xmlrpc-c/Windows/dll/xmlrpc.vcproj @@ -0,0 +1,479 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/xmlrpc-c/Windows/dll/xmlrpc__.vcproj b/libs/xmlrpc-c/Windows/dll/xmlrpc__.vcproj new file mode 100644 index 0000000..7f2732b --- /dev/null +++ b/libs/xmlrpc-c/Windows/dll/xmlrpc__.vcproj @@ -0,0 +1,1296 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/xmlrpc-c/Windows/dll/xmlrpc_abyss.vcproj b/libs/xmlrpc-c/Windows/dll/xmlrpc_abyss.vcproj new file mode 100644 index 0000000..366acde --- /dev/null +++ b/libs/xmlrpc-c/Windows/dll/xmlrpc_abyss.vcproj @@ -0,0 +1,1342 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/xmlrpc-c/Windows/dll/xmlrpc_client.vcproj b/libs/xmlrpc-c/Windows/dll/xmlrpc_client.vcproj new file mode 100644 index 0000000..b8424f2 --- /dev/null +++ b/libs/xmlrpc-c/Windows/dll/xmlrpc_client.vcproj @@ -0,0 +1,425 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/xmlrpc-c/Windows/dll/xmlrpc_server.vcproj b/libs/xmlrpc-c/Windows/dll/xmlrpc_server.vcproj new file mode 100644 index 0000000..d1d7ff5 --- /dev/null +++ b/libs/xmlrpc-c/Windows/dll/xmlrpc_server.vcproj @@ -0,0 +1,413 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/xmlrpc-c/Windows/dll/xmlrpc_server_abyss.vcproj b/libs/xmlrpc-c/Windows/dll/xmlrpc_server_abyss.vcproj new file mode 100644 index 0000000..4c71bc4 --- /dev/null +++ b/libs/xmlrpc-c/Windows/dll/xmlrpc_server_abyss.vcproj @@ -0,0 +1,401 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/xmlrpc-c/Windows/dll/xmlrpc_server_cgi.vcproj b/libs/xmlrpc-c/Windows/dll/xmlrpc_server_cgi.vcproj new file mode 100644 index 0000000..2eb2fae --- /dev/null +++ b/libs/xmlrpc-c/Windows/dll/xmlrpc_server_cgi.vcproj @@ -0,0 +1,401 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/xmlrpc-c/Windows/dll/xmlrpc_server_w32httpsys.vcproj b/libs/xmlrpc-c/Windows/dll/xmlrpc_server_w32httpsys.vcproj new file mode 100644 index 0000000..3e1fab7 --- /dev/null +++ b/libs/xmlrpc-c/Windows/dll/xmlrpc_server_w32httpsys.vcproj @@ -0,0 +1,405 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/xmlrpc-c/Windows/dll/xmlrpc_util.vcproj b/libs/xmlrpc-c/Windows/dll/xmlrpc_util.vcproj new file mode 100644 index 0000000..1f7670f --- /dev/null +++ b/libs/xmlrpc-c/Windows/dll/xmlrpc_util.vcproj @@ -0,0 +1,449 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/xmlrpc-c/Windows/dll/xmlrpc_xmlparse.vcproj b/libs/xmlrpc-c/Windows/dll/xmlrpc_xmlparse.vcproj new file mode 100644 index 0000000..2254c3e --- /dev/null +++ b/libs/xmlrpc-c/Windows/dll/xmlrpc_xmlparse.vcproj @@ -0,0 +1,417 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/xmlrpc-c/Windows/dll/xmlrpc_xmltok.vcproj b/libs/xmlrpc-c/Windows/dll/xmlrpc_xmltok.vcproj new file mode 100644 index 0000000..0e2c4b7 --- /dev/null +++ b/libs/xmlrpc-c/Windows/dll/xmlrpc_xmltok.vcproj @@ -0,0 +1,483 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/xmlrpc-c/Windows/gennmtab.2008.vcproj b/libs/xmlrpc-c/Windows/gennmtab.2008.vcproj deleted file mode 100644 index c4460dd..0000000 --- a/libs/xmlrpc-c/Windows/gennmtab.2008.vcproj +++ /dev/null @@ -1,242 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libs/xmlrpc-c/Windows/mkvers.bat b/libs/xmlrpc-c/Windows/mkvers.bat index 2f6ec1b..3d2fb7f 100644 --- a/libs/xmlrpc-c/Windows/mkvers.bat +++ b/libs/xmlrpc-c/Windows/mkvers.bat @@ -1,9 +1,9 @@ @if EXIST ..\version.h goto SHOW -@if NOT EXIST ..\Makefile.version goto ERR1 +@if NOT EXIST ..\version.mk goto ERR1 @if NOT EXIST mkvers1.bat goto ERR2 @echo updating/creating ..\version.h ... @set TEMP1=1 -@for /F "skip=8 tokens=3" %%i in (..\Makefile.version) do @call mkvers1 %%i +@for /F "skip=8 tokens=3" %%i in (..\version.mk) do @call mkvers1 %%i @if "%TEMPX1%." == "." goto NOX1 @if "%TEMPX2%." == "." goto NOX1 @if "%TEMPX3%." == "." goto NOX1 @@ -11,7 +11,7 @@ @echo #ifndef XMLRPC_C_VERSION_INCLUDED > %TEMP1% @echo #define XMLRPC_C_VERSION_INCLUDED >> %TEMP1% @echo /* generated by Windows/mkvers.bat on %DATE% ... */ >> %TEMP1% -@echo #define XMLRPC_C_VERSION "Xmlrpc-c %TEMPX1%.%TEMPX2%.%TEMPX3%" >> %TEMP1% +@echo #define XMLRPC_C_VERSION "%TEMPX1%.%TEMPX2%.%TEMPX3%" >> %TEMP1% @echo #define XMLRPC_VERSION_MAJOR %TEMPX1% >> %TEMP1% @echo #define XMLRPC_VERSION_MINOR %TEMPX2% >> %TEMP1% @echo #define XMLRPC_VERSION_POINT %TEMPX3% >> %TEMP1% @@ -35,7 +35,7 @@ type %TEMP1% :ERR1 -@echo Can not locate ..\Makefile.version ... check name, location ... +@echo Can not locate ..\version.mk ... check name, location ... @pause @goto END :ERR2 diff --git a/libs/xmlrpc-c/Windows/query_meerkat.dsp b/libs/xmlrpc-c/Windows/query_meerkat.dsp deleted file mode 100644 index 2ffb15b..0000000 --- a/libs/xmlrpc-c/Windows/query_meerkat.dsp +++ /dev/null @@ -1,100 +0,0 @@ -# Microsoft Developer Studio Project File - Name="query_meerkat" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=query_meerkat - 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 "query_meerkat.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 "query_meerkat.mak" CFG="query_meerkat - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "query_meerkat - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "query_meerkat - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "query_meerkat" -# PROP Scc_LocalPath ".." -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "query_meerkat - 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\query_meerkat" -# PROP Intermediate_Dir "Release\query_meerkat" -# 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 winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib WinInet.lib /nologo /subsystem:console /machine:I386 /out:"..\bin\query_meerkat.exe" - -!ELSEIF "$(CFG)" == "query_meerkat - 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\query_meerkat" -# PROP Intermediate_Dir "Debug\query_meerkat" -# 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 winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib WinInet.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\bin\query_meerkatD.exe" /pdbtype:sept - -!ENDIF - -# Begin Target - -# Name "query_meerkat - Win32 Release" -# Name "query_meerkat - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE="..\examples\query-meerkat.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 diff --git a/libs/xmlrpc-c/Windows/rpctest.dsp b/libs/xmlrpc-c/Windows/rpctest.dsp index 159692c..aa8fc4c 100644 --- a/libs/xmlrpc-c/Windows/rpctest.dsp +++ b/libs/xmlrpc-c/Windows/rpctest.dsp @@ -143,6 +143,14 @@ SOURCE=..\src\test\value.c # End Source File # Begin Source File +SOURCE=..\src\test\value_datetime.c +# End Source File +# Begin Source File + +SOURCE=..\src\test\value_datetime.h +# End Source File +# Begin Source File + SOURCE=..\src\test\xml_data.c # End Source File # End Group diff --git a/libs/xmlrpc-c/Windows/socketpair.cpp b/libs/xmlrpc-c/Windows/socketpair.cpp new file mode 100644 index 0000000..77310eb --- /dev/null +++ b/libs/xmlrpc-c/Windows/socketpair.cpp @@ -0,0 +1,71 @@ +#include + + +int +xmlrpc_win32_socketpair(int const domain, + int const type, + int const protocol, + SOCKET socks[2]) { + bool error; + + error = false; // initial value + + SOCKET listener; + listener = socket(AF_INET, SOCK_STREAM, 0); + if (listener == INVALID_SOCKET) + error = true; + else { + struct sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(0x7f000001); + addr.sin_port = 0; + + int rc; + rc = bind(listener, (const struct sockaddr*) &addr, sizeof(addr)); + if (rc == SOCKET_ERROR) + error = true; + else { + int addrlen; + int rc; + addrlen = sizeof(addr); // initial value + rc = getsockname(listener, (struct sockaddr*) &addr, &addrlen); + if (rc == SOCKET_ERROR) + error = true; + else { + int rc; + + rc = listen(listener, 1); + if (rc == SOCKET_ERROR) + error = true; + else { + socks[0] = socket(AF_INET, SOCK_STREAM, 0); + if (socks[0] == INVALID_SOCKET) + error = true; + else { + int rc; + rc = connect(socks[0], + (const struct sockaddr*) &addr, + sizeof(addr)); + if (rc == SOCKET_ERROR) + error = true; + else { + socks[1] = accept(listener, NULL, NULL); + if (socks[1] == INVALID_SOCKET) + error = true; + } + if (error) + closesocket(socks[0]); + } + } + } + } + closesocket(listener); + } + + return error ? -1 : 0; +} + + + + diff --git a/libs/xmlrpc-c/Windows/transport_config.h b/libs/xmlrpc-c/Windows/transport_config.h deleted file mode 100644 index 2642168..0000000 --- a/libs/xmlrpc-c/Windows/transport_config.h +++ /dev/null @@ -1,13 +0,0 @@ -/* 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"; diff --git a/libs/xmlrpc-c/Windows/transport_config_win32.h b/libs/xmlrpc-c/Windows/transport_config_win32.h index 54bb9b5..2642168 100644 --- a/libs/xmlrpc-c/Windows/transport_config_win32.h +++ b/libs/xmlrpc-c/Windows/transport_config_win32.h @@ -1,13 +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"; +/* 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"; diff --git a/libs/xmlrpc-c/Windows/win32_config.h b/libs/xmlrpc-c/Windows/win32_config.h index aabf9c2..d0df55b 100644 --- a/libs/xmlrpc-c/Windows/win32_config.h +++ b/libs/xmlrpc-c/Windows/win32_config.h @@ -20,19 +20,23 @@ #define XMLRPC_SOCKET SOCKET #define XMLRPC_HAVE_TIMEVAL 0 #define XMLRPC_HAVE_TIMESPEC 0 + #define XMLRPC_HAVE_PTHREAD 0 #else #define XMLRPC_SOCKET int #define XMLRPC_HAVE_TIMEVAL 1 #define XMLRPC_HAVE_TIMESPEC 1 + #define XMLRPC_HAVE_PTHREAD 1 #endif #if defined(_MSC_VER) /* Newer MSVC has long long, but MSVC 6 does not */ #define XMLRPC_INT64 __int64 #define XMLRPC_INT32 __int32 + #define XMLRPC_PRId64 PRId64 #else #define XMLRPC_INT64 long long #define XMLRPC_INT32 int + #define XMLRPC_PRId64 "I64d" #endif #endif diff --git a/libs/xmlrpc-c/Windows/xmlparse.2008.vcproj b/libs/xmlrpc-c/Windows/xmlparse.2008.vcproj deleted file mode 100644 index 15adb11..0000000 --- a/libs/xmlrpc-c/Windows/xmlparse.2008.vcproj +++ /dev/null @@ -1,387 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libs/xmlrpc-c/Windows/xmlparse.2010.vcxproj b/libs/xmlrpc-c/Windows/xmlparse.2010.vcxproj deleted file mode 100644 index a747e32..0000000 --- a/libs/xmlrpc-c/Windows/xmlparse.2010.vcxproj +++ /dev/null @@ -1,198 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - xmlparse - {0D108721-EAE8-4BAF-8102-D8960EC93647} - xmlparse - - - - StaticLibrary - false - MultiByte - - - StaticLibrary - false - MultiByte - - - StaticLibrary - false - MultiByte - - - StaticLibrary - false - MultiByte - - - - - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(PlatformName)\xmlparse\$(Configuration)\ - $(PlatformName)\xmlparse\$(Configuration)\ - $(PlatformName)\xmlparse\$(Configuration)\ - $(PlatformName)\xmlparse\$(Configuration)\ - - - - MaxSpeed - OnlyExplicitInline - ..\lib\expat\xmltok;..\lib\expat\xmlwf;..;..\lib\util\include;..\include;.;%(AdditionalIncludeDirectories) - NDEBUG;WIN32;_WINDOWS;XML_DTD;_LIB;%(PreprocessorDefinitions) - true - MultiThreaded - true - Level3 - true - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - - true - - - true - .\Release\xmlparse/xmlparse.bsc - - - - - X64 - - - MaxSpeed - OnlyExplicitInline - ..\lib\expat\xmltok;..\lib\expat\xmlwf;..;..\lib\util\include;..\include;.;%(AdditionalIncludeDirectories) - NDEBUG;WIN32;_WINDOWS;XML_DTD;_LIB;%(PreprocessorDefinitions) - true - MultiThreaded - true - Level3 - true - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - - true - - - true - .\Release\xmlparse/xmlparse.bsc - - - - - Disabled - ..\lib\expat\xmltok;..\lib\expat\xmlwf;..;..\lib\util\include;..\include;.;%(AdditionalIncludeDirectories) - WIN32;_WINDOWS;XML_DTD;_LIB;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebugDLL - Level3 - true - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - true - - - true - .\Debug\xmlparse/xmlparse.bsc - - - - - X64 - - - Disabled - ..\lib\expat\xmltok;..\lib\expat\xmlwf;..;..\lib\util\include;..\include;.;%(AdditionalIncludeDirectories) - WIN32;_WINDOWS;XML_DTD;_LIB;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebugDLL - Level3 - true - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - true - - - true - .\Debug\xmlparse/xmlparse.bsc - - - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - - - - - - - \ No newline at end of file diff --git a/libs/xmlrpc-c/Windows/xmlrpc-c/config.h b/libs/xmlrpc-c/Windows/xmlrpc-c/config.h deleted file mode 100644 index aabf9c2..0000000 --- a/libs/xmlrpc-c/Windows/xmlrpc-c/config.h +++ /dev/null @@ -1,38 +0,0 @@ -#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 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 . Anyone who - uses XMLRPC_SOCKET on a WIN32 system must #include - - */ - #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 - diff --git a/libs/xmlrpc-c/Windows/xmlrpc.2008.vcproj b/libs/xmlrpc-c/Windows/xmlrpc.2008.vcproj deleted file mode 100644 index 6a16191..0000000 --- a/libs/xmlrpc-c/Windows/xmlrpc.2008.vcproj +++ /dev/null @@ -1,2042 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libs/xmlrpc-c/Windows/xmlrpc.2010.vcxproj b/libs/xmlrpc-c/Windows/xmlrpc.2010.vcxproj deleted file mode 100644 index bdc988c..0000000 --- a/libs/xmlrpc-c/Windows/xmlrpc.2010.vcxproj +++ /dev/null @@ -1,620 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - xmlrpc - {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA} - xmlrpc - - - - StaticLibrary - false - MultiByte - - - StaticLibrary - false - MultiByte - - - StaticLibrary - false - MultiByte - - - StaticLibrary - false - MultiByte - - - - - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(PlatformName)\xmlrpc\$(Configuration)\ - $(PlatformName)\xmlrpc\$(Configuration)\ - $(PlatformName)\xmlrpc\$(Configuration)\ - $(PlatformName)\xmlrpc\$(Configuration)\ - - - - Disabled - ../lib;../lib/util/include;../include;..;../lib/expat/xmlparse;../lib/abyss/src;../lib/wininet_transport;.;%(AdditionalIncludeDirectories) - _DEBUG;WIN32;_LIB;ABYSS_WIN32;CURL_STATICLIB;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebugDLL - Level3 - true - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - true - - - true - .\Debug\xmlrpc/xmlrpc.bsc - - - - - X64 - - - Disabled - ../lib;../lib/util/include;../include;..;../lib/expat/xmlparse;../lib/abyss/src;../lib/wininet_transport;.;%(AdditionalIncludeDirectories) - _DEBUG;WIN32;_LIB;ABYSS_WIN32;CURL_STATICLIB;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebugDLL - Level3 - true - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - true - - - true - .\Debug\xmlrpc/xmlrpc.bsc - - - - - MaxSpeed - OnlyExplicitInline - ../lib;../lib/util/include;../include;..;../lib/expat/xmlparse;../lib/abyss/src;../lib/wininet_transport;.;%(AdditionalIncludeDirectories) - NDEBUG;WIN32;_LIB;ABYSS_WIN32;CURL_STATICLIB;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level3 - true - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - - true - - - true - .\Release\xmlrpc/xmlrpc.bsc - - - - - X64 - - - MaxSpeed - OnlyExplicitInline - ../lib;../lib/util/include;../include;..;../lib/expat/xmlparse;../lib/abyss/src;../lib/wininet_transport;.;%(AdditionalIncludeDirectories) - NDEBUG;WIN32;_LIB;ABYSS_WIN32;CURL_STATICLIB;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - Level3 - true - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - - true - - - true - .\Release\xmlrpc/xmlrpc.bsc - - - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - true - .;..\..\curl\include;%(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - .;..\..\curl\include;%(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - .;..\..\curl\include;%(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - .;..\..\curl\include;%(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - true - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/libs/xmlrpc-c/Windows/xmlrpc.2010.vcxproj.filters b/libs/xmlrpc-c/Windows/xmlrpc.2010.vcxproj.filters deleted file mode 100644 index 6886dfe..0000000 --- a/libs/xmlrpc-c/Windows/xmlrpc.2010.vcxproj.filters +++ /dev/null @@ -1,287 +0,0 @@ - - - - - {7ca2b8b9-bf59-4407-aedf-588e548fe34a} - cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;cc - - - {28891c93-973b-487f-a8f9-3fae090e14e3} - h;hpp;hxx;hm;inl - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - \ No newline at end of file diff --git a/libs/xmlrpc-c/Windows/xmlrpc.dsp b/libs/xmlrpc-c/Windows/xmlrpc.dsp index 15d20f0..a85ad1d 100644 --- a/libs/xmlrpc-c/Windows/xmlrpc.dsp +++ b/libs/xmlrpc-c/Windows/xmlrpc.dsp @@ -91,6 +91,10 @@ SOURCE=..\lib\libutil\asprintf.c # End Source File # Begin Source File +SOURCE=..\lib\libutil\base64.c +# End Source File +# Begin Source File + SOURCE=..\lib\libutil\error.c # End Source File # Begin Source File @@ -111,6 +115,10 @@ SOURCE=..\lib\util\pthreadx_win32.c # End Source File # Begin Source File +SOURCE=..\src\parse_datetime.c +# End Source File +# Begin Source File + SOURCE=..\src\parse_value.c # End Source File # Begin Source File @@ -362,6 +370,10 @@ SOURCE=..\lib\util\include\pthreadx.h # End Source File # Begin Source File +SOURCE=..\src\parse_datetime.h +# End Source File +# Begin Source File + SOURCE=..\src\parse_value.h # End Source File # Begin Source File diff --git a/libs/xmlrpc-c/Windows/xmlrpc.dsw b/libs/xmlrpc-c/Windows/xmlrpc.dsw index f7b676e..62a062e 100644 --- a/libs/xmlrpc-c/Windows/xmlrpc.dsw +++ b/libs/xmlrpc-c/Windows/xmlrpc.dsw @@ -111,6 +111,36 @@ Package=<4> ############################################################################### +Project: "xmlrpc_misc"=".\xmlrpc_misc.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "xmlrpcclient"=".\xmlrpcclient.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name xmlrpc + End Project Dependency + Begin Project Dependency + Project_Dep_Name xmlrpc_misc + End Project Dependency +}}} + +############################################################################### + Project: "xmlrpccpp"=".\xmlrpccpp.dsp" - Package Owner=<4> Package=<5> diff --git a/libs/xmlrpc-c/Windows/xmlrpc_config.h b/libs/xmlrpc-c/Windows/xmlrpc_config.h deleted file mode 100644 index 319dc2a..0000000 --- a/libs/xmlrpc-c/Windows/xmlrpc_config.h +++ /dev/null @@ -1,158 +0,0 @@ -/* 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 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. -*/ - -#ifndef XMLRPC_CONFIG_H_INCLUDED -#define XMLRPC_CONFIG_H_INCLUDED - -/* From xmlrpc_amconfig.h */ - -#define HAVE__STRICMP 1 -/* Name of package */ -#define PACKAGE "xmlrpc-c" -/*----------------------------------*/ - -#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 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 snprintf _snprintf -#define popen _popen -#define strtoll _strtoui64 -#define strtoull _strtoui64 - -#endif diff --git a/libs/xmlrpc-c/Windows/xmlrpc_win32_config.h b/libs/xmlrpc-c/Windows/xmlrpc_win32_config.h index e4e34fd..798b5b2 100644 --- a/libs/xmlrpc-c/Windows/xmlrpc_win32_config.h +++ b/libs/xmlrpc-c/Windows/xmlrpc_win32_config.h @@ -31,6 +31,8 @@ /* From xmlrpc_amconfig.h */ #define HAVE__STRICMP 1 +#define HAVE__STRTOUI64 1 + /* Name of package */ #define PACKAGE "xmlrpc-c" /*----------------------------------*/ @@ -72,6 +74,7 @@ #define HAVE_WCHAR_H 1 #define HAVE_SYS_FILIO_H 0 #define HAVE_SYS_IOCTL_H 0 +#define HAVE_SYS_SELECT_H 0 #define VA_LIST_IS_ARRAY 0 @@ -127,11 +130,41 @@ #endif #if MSVCRT + #define HAVE_WINDOWS_THREAD 1 +#else + #define HAVE_WINDOWS_THREAD 0 +#endif + +/* Some people have and use pthreads on Windows. See + http://sourceware.org/pthreads-win32 . For that case, we can set + HAVE_PTHREAD to 1. The builder prefers to use pthreads if it has + a choice. +*/ +#define HAVE_PTHREAD 0 + +/* Note that the return value of XMLRPC_VSNPRINTF is int on Windows, + ssize_t on POSIX. +*/ +#if MSVCRT #define XMLRPC_VSNPRINTF _vsnprintf #else #define XMLRPC_VSNPRINTF vsnprintf #endif +#if MSVCRT + #define HAVE_REGEX 0 +#else + #define HAVE_REGEX 1 +#endif + +#if MSVCRT + #define XMLRPC_SOCKETPAIR xmlrpc_win32_socketpair + #define XMLRPC_CLOSESOCKET closesocket +#else + #define XMLRPC_SOCKETPAIR socketpair + #define XMLRPC_CLOSESOCKET close +#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 @@ -149,10 +182,42 @@ */ #pragma warning(disable:4996) #endif +/* Warning C4090 is "different 'const' qualifiers". + + We disable this warning because MSVC erroneously issues it when there is + in fact no difference in const qualifiers: + + const char ** p; + void * q; + q = p; + + Note that both p and q are pointers to non-const. + + We have seen this in MSVC 7.1, 8, and 9 (but not 6). +*/ +#pragma warning(disable:4090) + +#if HAVE_STRTOLL + # define XMLRPC_STRTOLL strtoll +#elif HAVE_STRTOQ + # define XMLRPC_STRTOLL strtoq /* Interix */ +#elif HAVE___STRTOLL + # define XMLRPC_STRTOLL __strtoll /* HP-UX <= 11.11 */ +#elif HAVE__STRTOUI64 + #define XMLRPC_STRTOLL _strtoui64 /* Windows MSVC */ +#endif + +#if HAVE_STRTOULL + # define XMLRPC_STRTOULL strtoull +#elif HAVE_STRTOUQ + # define XMLRPC_STRTOULL strtouq /* Interix */ +#elif HAVE___STRTOULL + # define XMLRPC_STRTOULL __strtoull /* HP-UX <= 11.11 */ +#elif HAVE__STRTOUI64 + #define XMLRPC_STRTOULL _strtoui64 /* Windows MSVC */ +#endif #define snprintf _snprintf #define popen _popen -#define strtoll _strtoui64 -#define strtoull _strtoui64 #endif diff --git a/libs/xmlrpc-c/Windows/xmlrpcclient.dsp b/libs/xmlrpc-c/Windows/xmlrpcclient.dsp new file mode 100644 index 0000000..97061b0 --- /dev/null +++ b/libs/xmlrpc-c/Windows/xmlrpcclient.dsp @@ -0,0 +1,106 @@ +# Microsoft Developer Studio Project File - Name="xmlrpcclient" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=xmlrpcclient - 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 "xmlrpcclient.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 "xmlrpcclient.mak" CFG="xmlrpcclient - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "xmlrpcclient - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "xmlrpcclient - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "xmlrpcclient - 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\xmlrpcclient" +# PROP Intermediate_Dir "Release\xmlrpcclient" +# 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 ".." /I "..\lib\util\include" /I "..\tools\lib\include" /I "..\include" /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 Wininet.lib /nologo /subsystem:console /machine:I386 /out:"..\bin\xmlrpcclient.exe" + +!ELSEIF "$(CFG)" == "xmlrpcclient - 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\xmlrpcclient" +# PROP Intermediate_Dir "Debug\xmlrpcclient" +# 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 ".." /I "..\lib\util\include" /I "..\tools\lib\include" /I "..\include" /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 Wininet.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\bin\xmlrpcclientD.exe" + +!ENDIF + +# Begin Target + +# Name "xmlrpcclient - Win32 Release" +# Name "xmlrpcclient - 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=..\tools\xmlrpc\xmlrpc.c +# End Source File +# Begin Source File + +SOURCE=..\tools\lib\dumpvalue.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 diff --git a/libs/xmlrpc-c/Windows/xmlrpccpp.dsp b/libs/xmlrpc-c/Windows/xmlrpccpp.dsp index fedf4e2..34a4728 100644 --- a/libs/xmlrpc-c/Windows/xmlrpccpp.dsp +++ b/libs/xmlrpc-c/Windows/xmlrpccpp.dsp @@ -128,7 +128,6 @@ SOURCE=..\src\cpp\outcome.cpp # Begin Source File SOURCE=..\src\cpp\packetsocket.cpp -# PROP Exclude_From_Build 1 # End Source File # Begin Source File @@ -152,6 +151,10 @@ SOURCE=..\src\cpp\server_pstream.cpp # End Source File # Begin Source File +SOURCE=..\src\cpp\server_pstream_conn.cpp +# End Source File +# Begin Source File + SOURCE=..\src\cpp\value.cpp # End Source File # Begin Source File diff --git a/libs/xmlrpc-c/Windows/xmltok.2008.vcproj b/libs/xmlrpc-c/Windows/xmltok.2008.vcproj deleted file mode 100644 index 0935ede..0000000 --- a/libs/xmlrpc-c/Windows/xmltok.2008.vcproj +++ /dev/null @@ -1,455 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libs/xmlrpc-c/Windows/xmltok.2010.vcxproj b/libs/xmlrpc-c/Windows/xmltok.2010.vcxproj deleted file mode 100644 index a34b3f1..0000000 --- a/libs/xmlrpc-c/Windows/xmltok.2010.vcxproj +++ /dev/null @@ -1,213 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - xmltok - {B535402E-38D2-4D54-8360-423ACBD17192} - xmltok - - - - StaticLibrary - false - MultiByte - - - StaticLibrary - false - MultiByte - - - StaticLibrary - false - MultiByte - - - StaticLibrary - false - MultiByte - - - - - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(PlatformName)\xmltok\$(Configuration)\ - $(PlatformName)\xmltok\$(Configuration)\ - $(PlatformName)\xmltok\$(Configuration)\ - $(PlatformName)\xmltok\$(Configuration)\ - - - - Disabled - ..;.;%(AdditionalIncludeDirectories) - _DEBUG;WIN32;_WINDOWS;XML_DTD;XML_NS;_LIB;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebugDLL - Level3 - true - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - true - - - true - .\Debug\xmltok/xmltok.bsc - - - - - X64 - - - Disabled - ..;.;%(AdditionalIncludeDirectories) - _DEBUG;WIN32;_WINDOWS;XML_DTD;XML_NS;_LIB;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebugDLL - Level3 - true - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - - - true - - - true - .\Debug\xmltok/xmltok.bsc - - - - - MaxSpeed - OnlyExplicitInline - ..;.;%(AdditionalIncludeDirectories) - NDEBUG;XML_NS;WIN32;_WINDOWS;XML_DTD;_LIB;%(PreprocessorDefinitions) - true - MultiThreaded - true - Level3 - true - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - - true - - - true - .\Release\xmltok/xmltok.bsc - - - - - X64 - - - MaxSpeed - OnlyExplicitInline - ..;.;%(AdditionalIncludeDirectories) - NDEBUG;XML_NS;WIN32;_WINDOWS;XML_DTD;_LIB;%(PreprocessorDefinitions) - true - MultiThreaded - true - Level3 - true - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - - - true - - - true - .\Release\xmltok/xmltok.bsc - - - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - %(PreprocessorDefinitions) - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/libs/xmlrpc-c/Windows/xmltok.dsp b/libs/xmlrpc-c/Windows/xmltok.dsp index eaaebde..d9f88c8 100644 --- a/libs/xmlrpc-c/Windows/xmltok.dsp +++ b/libs/xmlrpc-c/Windows/xmltok.dsp @@ -41,7 +41,7 @@ RSC=rc.exe 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 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 @@ -66,7 +66,7 @@ LIB32=link.exe -lib 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 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 diff --git a/libs/xmlrpc-c/common.mk b/libs/xmlrpc-c/common.mk index 5b89fa1..a20bf42 100644 --- a/libs/xmlrpc-c/common.mk +++ b/libs/xmlrpc-c/common.mk @@ -9,7 +9,7 @@ # 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 +include $(SRCDIR)/version.mk # .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, @@ -17,13 +17,27 @@ include $(SRCDIR)/Makefile.version # fully made. .DELETE_ON_ERROR: -GCC_WARNINGS = -Wall -Wundef -Wimplicit -W -Winline -Wundef +GCC_WARNINGS = -Wall -W -Wno-uninitialized -Wundef -Wimplicit -Winline \ + -Wno-unknown-pragmas # We need -Wwrite-strings after we fix all the missing consts + # + # -Wuninitialized catches some great bugs, but it also flags a whole lot + # of perfectly good code that can't be written any better. Too bad there's + # no way to annotate particular variables as being OK, so we could turn + # on -Wuninitialized for all the others. GCC_C_WARNINGS = $(GCC_WARNINGS) \ -Wmissing-declarations -Wstrict-prototypes -Wmissing-prototypes -GCC_CXX_WARNINGS = $(GCC_WARNINGS) -Woverloaded-virtual -Wsynth +GCC_CXX_WARNINGS = $(GCC_WARNINGS) -Wsynth + +# Before 09.05.20, we had -Woverloaded-virtual, but it doesn't seem to do +# anything useful. It causes a warning that a method was hidden, but +# experiments show nothing is actually hidden. The GCC manual's description +# of what it does does not match empirical evidence. The option causes +# warnings when a derived class of xmlrpc_c::method2 overrides one of the +# execute() methods and not the other (as cpp/test/registry.cpp does), but the +# code works fine. # 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 @@ -55,12 +69,21 @@ ifeq ($(CURDIR)x,x) CURDIR := $(shell /bin/pwd) endif +# The package XmlRpc++ on Sourceforge includes a library named +# libxmlrpc++ just as Xmlrpc-c does. To use them both, you may need +# to rename one. To rename the Xmlrpc-c one, set the make variable +# LIBXMLRPCPP_NAME, e.g. on the 'make' command line. + +ifeq ($(LIBXMLRPCPP_NAME),) + LIBXMLRPCPP_NAME := xmlrpc++ +endif + ############################################################################## # STATIC LINK LIBRARY RULES # ############################################################################## -# To use this rule, the including make file must set a target_specific +# 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 @@ -81,19 +104,19 @@ $(TARGET_STATIC_LIBRARIES): ############################################################################## ifeq ($(SHARED_LIB_TYPE),unix) - include $(SRCDIR)/unix-common.make + include $(SRCDIR)/unix-common.mk endif ifeq ($(SHARED_LIB_TYPE),irix) - include $(SRCDIR)/irix-common.make + include $(SRCDIR)/irix-common.mk endif ifeq ($(SHARED_LIB_TYPE),dll) - include $(SRCDIR)/dll-common.make + include $(SRCDIR)/dll-common.mk endif ifeq ($(SHARED_LIB_TYPE),dylib) - include $(SRCDIR)/dylib-common.make + include $(SRCDIR)/dylib-common.mk endif ifeq ($(SHARED_LIB_TYPE),NONE) @@ -127,10 +150,10 @@ endif #------ the actual rules ---------------------------------------------------- $(TARGET_SHARED_LIBRARIES) dummyshlib: - $(CCLD) $(LDFLAGS_SHLIB) $(LIBDEP) -o $@ $(LIBOBJECTS) $(LADD) + $(CCLD) $(LADD) $(LDFLAGS_SHLIB) $(LIBOBJECTS) $(LIBDEP) -o $@ $(TARGET_SHARED_LIBS_PP) dummyshlibpp: - $(CXXLD) $(LDFLAGS_SHLIB) $(LIBDEP) -o $@ $(LIBOBJECTS) $(LADD) + $(CXXLD) $(LADD) $(LDFLAGS_SHLIB) $(LIBOBJECTS) $(LIBDEP) -o $@ #---------------------------------------------------------------------------- LIBXMLRPC_UTIL_DIR = $(BLDDIR)/lib/libutil @@ -186,7 +209,6 @@ 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 @@ -208,7 +230,6 @@ 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. @@ -239,31 +260,41 @@ endif # foo.o foo.osh: INCLUDES = -Iinclude -I/usr/include/foostuff # bar.o bar.osh: INCLUDES = -Iinclude -I/usr/include/barstuff # -# include Makefile.common +# include common.mk # # 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. +# CFLAGS and CXXFLAGS are designed to be picked up as environment +# variables. The user may use them to add inclusion search directories +# (-I) or control 32/64 bitness or the like. Using these is always +# iffy, because the options one might include can interact in unpredictable +# ways with what the make file is trying to do. But at least some users +# get useful results. + +CFLAGS_ALL = $(CFLAGS_COMMON) $(CFLAGS_LOCAL) $(CFLAGS) \ + $(INCLUDES) $(CFLAGS_PERSONAL) $(CADD) + +CXXFLAGS_ALL = $(CXXFLAGS_COMMON) $(CFLAGS_LOCAL) $(CXXFLAGS) \ + $(INCLUDES) $(CFLAGS_PERSONAL) $(CADD) + $(TARGET_MODS:%=%.o):%.o:%.c - $(CC) -c -o $@ $(INCLUDES) $(CFLAGS) $< + $(CC) -c -o $@ $(CFLAGS_ALL) $< $(TARGET_MODS:%=%.osh): CFLAGS_COMMON += $(CFLAGS_SHLIB) $(TARGET_MODS:%=%.osh):%.osh:%.c - $(CC) -c -o $@ $(INCLUDES) $(CFLAGS) $(CFLAGS_SHLIB) $< + $(CC) -c -o $@ $(INCLUDES) $(CFLAGS_ALL) $(CFLAGS_SHLIB) $< $(TARGET_MODS_PP:%=%.o):%.o:%.cpp - $(CXX) -c -o $@ $(INCLUDES) $(CXXFLAGS) $< + $(CXX) -c -o $@ $(INCLUDES) $(CXXFLAGS_ALL) $< $(TARGET_MODS_PP:%=%.osh): CXXFLAGS_COMMON += $(CFLAGS_SHLIB) $(TARGET_MODS_PP:%=%.osh):%.osh:%.cpp - $(CXX) -c -o $@ $(INCLUDES) $(CXXFLAGS) $< + $(CXX) -c -o $@ $(INCLUDES) $(CXXFLAGS_ALL) $< ############################################################################## @@ -278,11 +309,6 @@ $(TARGET_MODS_PP:%=%.osh):%.osh:%.cpp # 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: @@ -343,6 +369,12 @@ endif ifneq ($(OMIT_CURL_TRANSPORT_RULE),Y) $(BLDDIR)/lib/curl_transport/xmlrpc_curl_transport.o \ $(BLDDIR)/lib/curl_transport/xmlrpc_curl_transport.osh \ +$(BLDDIR)/lib/curl_transport/curltransaction.o \ +$(BLDDIR)/lib/curl_transport/curltransaction.osh \ +$(BLDDIR)/lib/curl_transport/curlmulti.o \ +$(BLDDIR)/lib/curl_transport/curlmulti.osh \ +$(BLDDIR)/lib/curl_transport/lock_pthread.o \ +$(BLDDIR)/lib/curl_transport/lock_pthread.osh \ : FORCE $(MAKE) -C $(dir $@) -f $(SRCDIR)/lib/curl_transport/Makefile \ $(notdir $@) @@ -385,6 +417,8 @@ $(LIBXMLRPC_ABYSS) $(LIBXMLRPC_ABYSS_A): FORCE $(MAKE) -C $(dir $@) -f $(SRCDIR)/lib/abyss/src/Makefile \ $(notdir $@) +ifneq ($(OMIT_CPP_LIB_RULES),Y) + $(LIBXMLRPCPP) $(LIBXMLRPCPP_A) \ $(LIBXMLRPC_PACKETSOCKET) $(LIBXMLRPC_PACKETSOCKET_A) \ $(LIBXMLRPC_CLIENTPP) $(LIBXMLRPC_CLIENTPP_A) \ @@ -394,6 +428,7 @@ $(LIBXMLRPC_SERVER_PSTREAMPP) $(LIBXMLRPC_SERVER_PSTREAMPP_A) \ $(LIBXMLRPC_CPP) $(LIBXMLRPC_CPP_A) : FORCE $(MAKE) -C $(dir $@) -f $(SRCDIR)/src/cpp/Makefile \ $(notdir $@) +endif # For the following utilities, we don't bother with a library -- we # just explicitly link the object file we need. This is to save @@ -421,12 +456,12 @@ 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 +# dependencies (depend.mk), 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 +# the top directory's make file includes common.mk, so the rules # below conflict with it. That's what OMIT_VERSION_H is for. ifneq ($(OMIT_VERSION_H),Y) @@ -471,10 +506,10 @@ $(SUBDIRS:%=$(CURDIR)/%): MKINSTALLDIRS = $(SHELL) $(SRCDIR)/mkinstalldirs -.PHONY: install-common install-ltlibraries install-headers install-bin +.PHONY: install-common install-headers install-bin install-man install-common: \ - install-ltlibraries install-static-libraries install-shared-libraries \ - install-headers install-bin + install-static-libraries install-shared-libraries \ + install-headers install-bin install-man INSTALL_LIB_CMD = $(INSTALL_DATA) $$p $(DESTDIR)$(LIBINST_DIR)/$$p RANLIB_CMD = $(RANLIB) $(DESTDIR)$(LIBINST_DIR)/$$p @@ -520,6 +555,16 @@ install-bin: $(PROGRAMS_TO_INSTALL) $(DESTDIR)$(PROGRAMINST_DIR) $(DESTDIR)$(PROGRAMINST_DIR): $(MKINSTALLDIRS) $@ +MANDESTDIR = $(DESTDIR)$(MANINST_DIR) +INSTALL_MAN_CMD = $(INSTALL_DATA) $$p $(MANDESTDIR)/$$p + +install-man: $(MAN_FILES_TO_INSTALL) + $(MKINSTALLDIRS) $(MANDESTDIR) + @list='$(MAN_FILES_TO_INSTALL)'; \ + for p in $$list; do \ + echo "$(MAN_FILES_TO_INSTALL)"; \ + $(INSTALL_MAN_CMD); \ + done ############################################################################## # MISCELLANEOUS RULES # @@ -536,29 +581,30 @@ endif .PHONY: distclean-common distclean-common: -# Makefile.depend is generated by 'make dep' and contains only dependencies +# depend.mk 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. +# besides depend.mk. # -# Because of this, a user doesn't need Makefile.depend, because he +# Because of this, a user doesn't need depend.mk, 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 +# own depend.mk, because 'make dep' creates depend.mk 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 +# So we obliterate depend.mk here. The build will automatically +# create an empty depend.mk 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 +# depend.mk, 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 depend.mk + rm -f Makefile.depend # We used to create a file by this name rm -f srcdir blddir .PHONY: distdir-common @@ -589,17 +635,17 @@ dep-common: FORCE ifneq ($(DEP_SOURCES)x,x) -$(CC) -MM -MG -I. $(INCLUDES) $(DEP_SOURCES) | \ $(DEPEND_MASSAGER) \ - >Makefile.depend + >depend.mk endif -Makefile.depend: +depend.mk: 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 +# 'distclean' target simply makes depend.mk an empty file. A +# developer may do 'make dep' to create a depend.mk full of real # dependencies. # Tell versions [3.59,3.63) of GNU make to not export all variables. diff --git a/libs/xmlrpc-c/conf/abyss_root/conf/abyss.conf b/libs/xmlrpc-c/conf/abyss_root/conf/abyss.conf deleted file mode 100644 index f9c09f2..0000000 --- a/libs/xmlrpc-c/conf/abyss_root/conf/abyss.conf +++ /dev/null @@ -1,56 +0,0 @@ -# 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 diff --git a/libs/xmlrpc-c/conf/abyss_root/conf/mime.types b/libs/xmlrpc-c/conf/abyss_root/conf/mime.types deleted file mode 100644 index d53db0f..0000000 --- a/libs/xmlrpc-c/conf/abyss_root/conf/mime.types +++ /dev/null @@ -1,276 +0,0 @@ -# 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 . - -# 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 diff --git a/libs/xmlrpc-c/conf/abyss_root/htdocs/index.htm b/libs/xmlrpc-c/conf/abyss_root/htdocs/index.htm deleted file mode 100644 index f0369a5..0000000 --- a/libs/xmlrpc-c/conf/abyss_root/htdocs/index.htm +++ /dev/null @@ -1,21 +0,0 @@ - - -ABYSS is working !!! - - -

Congratulations, ABYSS is working !!!

-
-

-ABYSS Web Server is working correctly on your system. You should now change this -page with yours. -
-Please include in your web pages (at least the first), the 'Powered by ABYSS' -banner to promote the use of ABYSS. -

-
-

-

-Copyright © 2000 Moez Mahfoudh. All rights reserved. - -

- diff --git a/libs/xmlrpc-c/config.mk.in b/libs/xmlrpc-c/config.mk.in index b583e6e..bebfa54 100644 --- a/libs/xmlrpc-c/config.mk.in +++ b/libs/xmlrpc-c/config.mk.in @@ -27,16 +27,15 @@ 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@ +BUILD_TOOLS = @BUILD_TOOLS@ +BUILD_XMLRPC_PSTREAM = @BUILD_XMLRPC_PSTREAM@ LSOCKET = @LSOCKET@ WININET_LDADD = @WININET_LDADD@ -WININET_RPATH = @WININET_RPATH@ -WININET_WL_RPATH = @WININET_WL_RPATH@ +WININET_LIBDIR = @WININET_LIBDIR@ CURL_LDADD = @CURL_LDADD@ -CURL_RPATH = @CURL_RPATH@ -CURL_WL_RPATH = @CURL_WL_RPATH@ +CURL_LIBDIR = @CURL_LIBDIR@ LIBWWW_LDADD = @LIBWWW_LDADD@ -LIBWWW_RPATH = @LIBWWW_RPATH@ -LIBWWW_WL_RPATH = @LIBWWW_WL_RPATH@ +LIBWWW_LIBDIR = @LIBWWW_LIBDIR@ FEATURE_LIST = @FEATURE_LIST@ ABS_SRCDIR = @abs_srcdir@ PREFIX = @prefix@ @@ -164,7 +163,10 @@ MUST_BUILD_SHLIBLE = N shlibfn = $(1:%=%.shlibdummy) shliblefn = $(1:%=%.shlibledummy) -ifeq ($(HOST_OS),linux-gnu) +# HOST_OS is usually has a version number suffix, e.g. "aix5.3.0.0", so +# we compare based on prefix. + +ifeq ($(patsubst linux-gnu%,linux-gnu,$(HOST_OS)),linux-gnu) # Assume linker is GNU Compiler (gcc) SHARED_LIB_TYPE = unix MUST_BUILD_SHLIB = Y @@ -177,20 +179,28 @@ ifeq ($(HOST_OS),linux-gnu) CFLAGS_SHLIB=-fPIC endif -ifeq ($(findstring solaris,$(HOST_OS)),solaris) +ifeq ($(patsubst solaris%,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)) + # We assume Sun compiler and linker here. It isn't clear what to do + # about a user who uses GNU compiler and Ld instead. For that, the + # options should be the same as "linux-gnu" platform, above, except + # with NEED_WL_RPATH. If the user uses the GNU compiler but the Sun + # linker, it's even more complicated: we need an rpath option of the + # form -Wl,-R . + # 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 + NEED_RPATH=yes endif -ifeq ($(HOST_OS),aix) +ifeq ($(patsubst aix%,aix,$(HOST_OS)),aix) SHARED_LIB_TYPE = unix MUST_BUILD_SHLIB = Y MUST_BUILD_SHLIBLE = Y @@ -200,7 +210,7 @@ ifeq ($(HOST_OS),aix) LDFLAGS_SHLIB = -qmkshrobj endif -ifeq ($(HOST_OS),hpux) +ifeq ($(patsubst hpux%,hpux,$(HOST_OS)),hpux) SHARED_LIB_TYPE = unix MUST_BUILD_SHLIB = Y MUST_BUILD_SHLIBLE = Y @@ -210,7 +220,7 @@ ifeq ($(HOST_OS),hpux) LDFLAGS_SHLIB: -shared -fPIC endif -ifeq ($(HOST_OS),osf) +ifeq ($(patsubst osf%,osf,$(HOST_OS)),osf) SHARED_LIB_TYPE = unix MUST_BUILD_SHLIB = Y MUST_BUILD_SHLIBLE = Y @@ -220,7 +230,7 @@ ifeq ($(HOST_OS),osf) LDFLAGS_SHLIB = -shared -expect_unresolved endif -ifeq ($(findstring netbsd,$(HOST_OS)),netbsd) +ifeq ($(patsubst netbsd%,netbsd,$(HOST_OS)),netbsd) SHARED_LIB_TYPE = unix SHLIB_SUFFIX = so MUST_BUILD_SHLIB = Y @@ -232,7 +242,31 @@ ifeq ($(findstring netbsd,$(HOST_OS)),netbsd) NEED_WL_RPATH=yes endif -ifeq ($(HOST_OS),dragonfly) +ifeq ($(patsubst freebsd%,freebsd,$(HOST_OS)),freebsd) + 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 ($(findstring interix,$(HOST_OS)),interix) + 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 = + LDFLAGS_SHLIB = -shared -Wl,-soname,$(SONAME) $(SHLIB_CLIB) + NEED_WL_RPATH=yes +endif + +ifeq ($(patsubst dragonfly%,dragonfly,$(HOST_OS)),dragonfly) SHARED_LIB_TYPE = unix MUST_BUILD_SHLIB = Y MUST_BUILD_SHLIBLE = Y @@ -243,7 +277,7 @@ ifeq ($(HOST_OS),dragonfly) LDFLAGS_SHLIB = -shared -Wl,-soname,$(SONAME) $(SHLIB_CLIB) endif -ifeq ($(HOST_OS),beos) +ifeq ($(patsubst beos%,beos,$(HOST_OS)),beos) SHARED_LIB_TYPE = unix MUST_BUILD_SHLIB = Y MUST_BUILD_SHLIBLE = Y @@ -253,18 +287,18 @@ ifeq ($(HOST_OS),beos) LDFLAGS_SHLIB = -nostart endif -ifeq ($(patsubst darwin%, darwin, $(HOST_OS)), darwin) - # (I once saw a system that generated 'darwin8.10.1'). +ifeq ($(patsubst darwin%,darwin,$(HOST_OS)),darwin) 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) + LDFLAGS_SHLIB = -dynamiclib -undefined suppress -single_module \ + -flat_namespace $(SHLIB_CLIB) endif -ifeq ($(HOST_OS),irix) +ifeq ($(patsubst irix%,irix,$(HOST_OS)),irix) SHARED_LIB_TYPE = irix MUST_BUILD_SHLIB = Y MUST_BUILD_SHLIBLE = Y @@ -278,13 +312,13 @@ ifeq ($(HOST_OS),irix) -set_version $(shell perl -e '$(VERSIONPERLPROG)') -lc endif -ifeq ($(HOST_OS),cygwin) +ifeq ($(patsubst cygwin%,cygwin,$(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) + shlibfn = $(1:%=%.$(SHLIB_SUFFIX)) + shliblefn = $(1:%=%.$(SHLIB_SUFFIX)) LDFLAGS_SHLIB = -shared -Wl,-soname,$(SONAME) $(SHLIB_CLIB) endif @@ -293,12 +327,12 @@ endif ############################################################################## # 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 +# will then run to build the 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. +# build the build tools for Environment B. -# The cross compiling user can update Makefile.config or override +# The cross compiling user can update config.mk or override # BUILDTOOL_CC on a make command. BUILDTOOL_CC = $(CC) @@ -316,9 +350,18 @@ INSTALL_SCRIPT = $(INSTALL) -c -m 755 # 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 +prefix = $(PREFIX) + +#datarootdir is the new Autoconf(2.60) name for datadir, which is still +#accepted, but a warning is issued if datarootdir is not also used. + +exec_prefix = @exec_prefix@ +DATAROOT_DIR = @datarootdir@ +DATAINST_DIR = @datadir@ +LIBINST_DIR = @libdir@ +HEADERINST_DIR = @includedir@ +PROGRAMINST_DIR = @bindir@ +MANINST_DIR = @mandir@/man1 # DESTDIR is designed to be overridden at make time in order to relocate # the entire install into a subdirectory. diff --git a/libs/xmlrpc-c/configure.gnu b/libs/xmlrpc-c/configure.gnu deleted file mode 100644 index dda9b7d..0000000 --- a/libs/xmlrpc-c/configure.gnu +++ /dev/null @@ -1,4 +0,0 @@ -#! /bin/sh -srcpath=$(dirname $0 2>/dev/null ) || srcpath="." -$srcpath/configure "$@" --disable-cplusplus --disable-wininet-client --disable-libwww-client --disable-shared --with-pic --disable-curl-client - diff --git a/libs/xmlrpc-c/configure.in b/libs/xmlrpc-c/configure.in index 231a1d3..8fbe80a 100644 --- a/libs/xmlrpc-c/configure.in +++ b/libs/xmlrpc-c/configure.in @@ -86,10 +86,45 @@ AC_MSG_RESULT($MUST_BUILD_LIBWWW_CLIENT) AC_SUBST(MUST_BUILD_LIBWWW_CLIENT) +AC_ARG_ENABLE(tools, + [ --enable-tools Build the tools], , +[enable_tools=no]) + +# The first AC_CHECK_LIB has to be in unconditional code because as a +# side effect, it determines what the object file suffix is on this system, +# and if it is statically present even though not actually executed, Autoconf +# later thinks it has already computed the object file suffix and uses it +# without computing it. This was with Autoconf 2.59 +AC_CHECK_LIB(ncurses, main, [have_libncurses=yes], [have_libncurses=no]) +AC_CHECK_LIB(readline, main, [have_libreadline=yes], [have_libreadline=no]) + +AC_MSG_CHECKING(whether to build tools) + +BUILD_XMLRPC_PSTREAM=no + +if test $enable_tools = yes; then + if ! test "$MUST_BUILD_WININET_CLIENT $MUST_BUILD_CURL_CLIENT $MUST_BUILD_LIBWWW_CLIENT" = "no no no"; then + if test $have_libreadline = yes && test $have_libncurses = yes; then + BUILD_XMLRPC_PSTREAM=yes + fi + BUILD_TOOLS=yes + fi +else + BUILD_TOOLS=$enable_tools +fi + +AC_MSG_RESULT($BUILD_TOOLS) +AC_SUBST(BUILD_TOOLS) + +if test $BUILD_TOOLS = yes; then + AC_MSG_CHECKING(whether to build the xmlrpc_pstream tool) + AC_MSG_RESULT($BUILD_XMLRPC_PSTREAM) + AC_SUBST(BUILD_XMLRPC_PSTREAM) +fi + + dnl Set up the appropriate Makefile substitutions. -LIBXMLRPC_CLIENT_LA=libxmlrpc_client.la -AC_SUBST(LIBXMLRPC_CLIENT_LA) CLIENTTEST=clienttest AC_SUBST(CLIENTTEST) XMLRPC_CLIENT_H=xmlrpc_client.h @@ -126,7 +161,6 @@ AC_SUBST(ENABLE_ABYSS_SERVER) dnl Set up the appropriate Makefile substitutions. ABYSS_SUBDIR= -LIBXMLRPC_ABYSS_SERVER_LA= SERVERTEST= VALIDATEE= XMLRPC_ABYSS_H= @@ -134,14 +168,12 @@ SERVER= if test x"$enable_abyss_server" != xno; then FEATURE_LIST="abyss-server $FEATURE_LIST" ABYSS_SUBDIR=abyss - LIBXMLRPC_ABYSS_SERVER_LA=libxmlrpc_abyss_server.la SERVERTEST=servertest VALIDATEE=validatee XMLRPC_ABYSS_H=xmlrpc_abyss.h SERVER=server fi AC_SUBST(ABYSS_SUBDIR) -AC_SUBST(LIBXMLRPC_ABYSS_SERVER_LA) AC_SUBST(SERVERTEST) AC_SUBST(VALIDATEE) AC_SUBST(XMLRPC_ABYSS_H) @@ -198,7 +230,9 @@ dnl Checks for programs. dnl ======================================================================= AC_PROG_CC -AC_PROG_CXX +if test x"$enable_cplusplus" != xno; then + AC_PROG_CXX +fi dnl ======================================================================= @@ -272,6 +306,14 @@ else fi AC_SUBST(HAVE_SYS_IOCTL_H_DEFINE) +AC_CHECK_HEADERS(sys/select.h) +if test x"$ac_cv_header_sys_select_h" = xyes; then + HAVE_SYS_SELECT_H_DEFINE=1 +else + HAVE_SYS_SELECT_H_DEFINE=0 +fi +AC_SUBST(HAVE_SYS_SELECT_H_DEFINE) + AC_CHECK_HEADERS(stdarg.h, , [ AC_MSG_ERROR(stdarg.h is required to build this library) @@ -329,7 +371,7 @@ AC_CHECK_FUNCS(setgroups) AC_CHECK_FUNCS(asprintf) -AC_CHECK_FUNCS(setenv) +AC_CHECK_FUNCS(setenv strtoll strtoull strtoq strtouq __strtoll __strtoull) dnl uclib doesn't have pselect AC_CHECK_FUNCS(pselect) @@ -380,22 +422,22 @@ dnl you will need to configure this way.. if test $MUST_BUILD_WININET_CLIENT = yes; then - dnl You can control which of these gets chosen by fooling around with PATH. + dnl You can control which of these gets chosen by controlling PATH. AC_PATH_PROGS(WININET_CONFIG, wininet-xmlrpc-config wininet-config, no) if test "x$WININET_CONFIG" = "xno"; then - AC_MSG_ERROR(wininet lib not found; see './configure --help') + AC_MSG_ERROR(Configure INTERNAL ERROR - first wininet-config found, then not found) fi dnl Get our wininet version. dnl Adapted from a macro which called gtk-config. AC_MSG_CHECKING(for wininet version >= 1.0.0) - W3VER=`$WININET_CONFIG --version` + W3VER=$($WININET_CONFIG --version) WININET_MAJOR=\ -`echo $W3VER|sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` +$(echo $W3VER|sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/') WININET_MINOR=\ -`echo $W3VER|sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` +$(echo $W3VER|sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/') WININET_MICRO=\ -`echo $W3VER|sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'` +$(echo $W3VER|sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/') AC_MSG_RESULT($WININET_MAJOR.$WININET_MINOR.$WININET_MICRO) dnl Check to make sure our version is OK. @@ -417,61 +459,44 @@ if test $MUST_BUILD_WININET_CLIENT = yes; then fi dnl Get the necessary CFLAGS, and merge them into our master list. - WININET_CFLAGS="`$WININET_CONFIG --cflags`" + WININET_CFLAGS=$($WININET_CONFIG --cflags) AC_SUBST(WININET_CFLAGS) CFLAGS="$CFLAGS $WININET_CFLAGS" dnl Get the huge list of libraries we need to link against. - WININET_LDADD="`$WININET_CONFIG --libs`" + WININET_LDADD=$($WININET_CONFIG --libs) AC_SUBST(WININET_LDADD) - dnl Oh, such massive brain damage! Because there may be another copy - dnl of libwww in the default dynamic loader search path, we need to - dnl adjust the search patch manually. Just gag me with a backquote, OK? AC_MSG_CHECKING(for wininet library directory) - if $WININET_CONFIG --rpath-dir > /dev/null 2>&1; then - dnl Yay! We're using our smart version of wininet. - WININET_LIBDIR="`$WININET_CONFIG --rpath-dir`" - else - dnl Yawn. We're using the regular boring version. - WININET_LIBDIR="`$WININET_CONFIG --prefix`/lib" - fi + WININET_LIBDIR="$($WININET_CONFIG --prefix)/lib" AC_MSG_RESULT($WININET_LIBDIR) AC_SUBST(WININET_LIBDIR) - WININET_RPATH="-rpath $WININET_LIBDIR" - AC_SUBST(WININET_RPATH) - WININET_WL_RPATH="-Wl,--rpath -Wl,$WININET_LIBDIR" - AC_SUBST(WININET_WL_RPATH) fi # MUST_BUILD_WININET_CLIENT dnl ======================================================================= 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 function -dnl for keeping track of libwww's rpath, although this is no longer really -dnl necessary. if test $MUST_BUILD_LIBWWW_CLIENT = yes; then - dnl First of all, locate the semi-broken libwww config program. - dnl You can control which of these gets chosen by fooling around with PATH. + dnl First of all, locate the libwww config program. + dnl You can control which of these gets chosen by controlling PATH. AC_PATH_PROGS(LIBWWW_CONFIG, libwww-xmlrpc-config libwww-config, no) if test "x$LIBWWW_CONFIG" = "xno"; then - AC_MSG_ERROR(w3c-libwww not found; see './configure --help') + AC_MSG_ERROR(Configure INTERNAL ERROR - first libwww-config found, then not found) fi dnl Get our libwww version. dnl Adapted from a macro which called gtk-config. AC_MSG_CHECKING(for w3c-libwww version >= 5.2.8) - W3VER=`$LIBWWW_CONFIG --version` + W3VER=$($LIBWWW_CONFIG --version) LIBWWW_MAJOR=\ -`echo $W3VER|sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` +$(echo $W3VER|sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/') LIBWWW_MINOR=\ -`echo $W3VER|sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` +$(echo $W3VER|sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/') LIBWWW_MICRO=\ -`echo $W3VER|sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'` +$(echo $W3VER|sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/') AC_MSG_RESULT($LIBWWW_MAJOR.$LIBWWW_MINOR.$LIBWWW_MICRO) dnl Check to make sure our version is OK. @@ -493,78 +518,46 @@ if test $MUST_BUILD_LIBWWW_CLIENT = yes; then fi dnl Get the huge list of libraries we need to link against. - LIBWWW_LDADD="`$LIBWWW_CONFIG --libs`" + LIBWWW_LDADD=$(LIBWWW_CONFIG --libs) AC_SUBST(LIBWWW_LDADD) - dnl Oh, such massive brain damage! Because there may be another copy - dnl of libwww in the default dynamic loader search path, we need to - dnl adjust the search patch manually. Just gag me with a backquote, OK? AC_MSG_CHECKING(for libwww library directory) - if $LIBWWW_CONFIG --rpath-dir > /dev/null 2>&1; then - dnl Yay! We're using our smart version of libwww. - LIBWWW_LIBDIR="`$LIBWWW_CONFIG --rpath-dir`" - else - dnl Yawn. We're using the regular boring version. - LIBWWW_LIBDIR="`$LIBWWW_CONFIG --prefix`/lib" - fi + LIBWWW_LIBDIR="$(LIBWWW_CONFIG --prefix)/lib" AC_MSG_RESULT($LIBWWW_LIBDIR) AC_SUBST(LIBWWW_LIBDIR) - # Some ancient rpath stuff, now disabled. I turned this off because it - # breaks Debian (and Mandrake?) policy, and we don't use it anymore. - # If you have multiple copies of w3c-libwww lying around, you can turn - # it back on. - #LIBWWW_RPATH="-rpath $LIBWWW_LIBDIR" - LIBWWW_RPATH="" - AC_SUBST(LIBWWW_RPATH) - #LIBWWW_WL_RPATH="-Wl,--rpath -Wl,$LIBWWW_LIBDIR" - LIBWWW_WL_RPATH="" - AC_SUBST(LIBWWW_WL_RPATH) - fi # MUST_BUILD_LIBWWW_CLIENT dnl ======================================================================= -dnl Finding cURL +dnl Finding Curl dnl ======================================================================= if test $MUST_BUILD_CURL_CLIENT = yes; then - dnl First of all, locate the curl config program. - dnl You can control which of these gets chosen by fooling around with PATH. + dnl First of all, locate the Curl config program. + dnl You can control which of these gets chosen by controlling PATH. AC_PATH_PROGS(CURL_CONFIG, curl-xmlrpc-config curl-config, no) if test "x$CURL_CONFIG" = "xno"; then - AC_MSG_ERROR(cURL not found; see './configure --help') + AC_MSG_ERROR(Configure INTERNAL ERROR - first curl-config found, then not found) fi dnl There used to be code here to check the Curl version and make sure dnl it is at least 7.8. But there were bugs both in the code and in - dnl curl (curl-config --vernum, at least in older versios of Curl, + dnl curl (curl-config --vernum, at least in older versions of Curl, dnl omits the leading zero). So it didn't work. Plus, checking version dnl numbers isn't a good idea. Better to check for feature presence. dnl So we don't do any check now. If we find out there's a problem with dnl older Curls, we will revisit that. - dnl Get the huge list of libraries we need to link against. - dnl MRB-20010516-For some reason, curl-config - dnl does not list itself '-lcurl'. 2004.12.12. It seems to do so - dnl now. - CURL_LDADD=`$CURL_CONFIG --libs` + CURL_LDADD=$($CURL_CONFIG --libs) AC_SUBST(CURL_LDADD) - 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 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" + AC_MSG_CHECKING(for Curl library directory) + CURL_LIBDIR="$($CURL_CONFIG --prefix)/lib" AC_MSG_RESULT($CURL_LIBDIR) AC_SUBST(CURL_LIBDIR) - CURL_RPATH="-rpath $CURL_LIBDIR" - AC_SUBST(CURL_RPATH) - CURL_WL_RPATH="-Wl,--rpath -Wl,$CURL_LIBDIR" - AC_SUBST(CURL_WL_RPATH) fi # MUST_BUILD_CURL_CLIENT @@ -620,7 +613,7 @@ CPP_WARN_FLAGS= AC_SUBST(CPP_WARN_FLAGS) -BUILDDIR=`pwd` +BUILDDIR=$(pwd) AC_SUBST(BUILDDIR) @@ -632,7 +625,7 @@ dnl Note that AM_CONFIG_HEADER at the top of this file outputs another dnl result: xmlrpc_amconfig.h . AC_OUTPUT( \ - Makefile.srcdir \ + srcdir.mk \ config.mk \ xmlrpc_config.h \ ) @@ -647,7 +640,9 @@ fi 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.]) + AC_MSG_NOTICE([==>]) + AC_MSG_NOTICE([==>We are not building any client XML transport (see earlier messages explaining why), therefore WE WILL NOT BUILD THE CLIENT LIBRARY.]) + AC_MSG_NOTICE([==>]) fi diff --git a/libs/xmlrpc-c/debian/README.Debian b/libs/xmlrpc-c/debian/README.Debian deleted file mode 100644 index 830df77..0000000 --- a/libs/xmlrpc-c/debian/README.Debian +++ /dev/null @@ -1,7 +0,0 @@ -xmlrpc-c for Debian -------------------- - -This is my first attempt at porting my RPM packages to Debian. User -beware! - - -- Eric Kidd , Tue, 26 Jun 2001 12:39:39 -0400 diff --git a/libs/xmlrpc-c/debian/changelog b/libs/xmlrpc-c/debian/changelog deleted file mode 100644 index 848fac8..0000000 --- a/libs/xmlrpc-c/debian/changelog +++ /dev/null @@ -1,22 +0,0 @@ -xmlrpc-c (0.9.10-1) unstable; urgency=low - - * Updated from new upstream release. - - -- Eric Kidd Sun, 1 Jul 2001 10:45:51 -0400 - -xmlrpc-c (0.9.9-2) unstable; urgency=low - - * Added man pages. - * Improved depends for xmlrpc-c-dev. - - -- Eric Kidd Wed, 27 Jun 2001 12:25:52 -0400 - -xmlrpc-c (0.9.9-1) unstable; urgency=low - - * Initial Release. - - -- Eric Kidd Tue, 26 Jun 2001 12:39:39 -0400 - -Local variables: -mode: debian-changelog -End: diff --git a/libs/xmlrpc-c/debian/control b/libs/xmlrpc-c/debian/control deleted file mode 100644 index 45bd020..0000000 --- a/libs/xmlrpc-c/debian/control +++ /dev/null @@ -1,30 +0,0 @@ -Source: xmlrpc-c -Section: devel -Priority: optional -Maintainer: Eric Kidd -Build-Depends: debhelper (>> 3.0.0), libwww0 (>= 5.3.2), libwww-dev (>= 5.3.2) -Standards-Version: 3.5.2 - -Package: xmlrpc-c0 -Architecture: any -Depends: ${shlibs:Depends} -Description: A library implementing XML-based remote procedure calls - XML-RPC is a lightweight RPC protocol based on XML and HTTP. This package - is used by XML-RPC clients and servers written in C and C++. - -Package: xmlrpc-c-dev -Architecture: any -Depends: xmlrpc-c0 (= ${Source-Version}), libc6-dev, libstdc++-dev, libfrontier-rpc-perl -Description: Libraries and header files for developing XML-RPC applications - Static libraries and header files for writing XML-RPC applications in C and - C++. - -Package: xmlrpc-c-apps -Architecture: any -Depends: xmlrpc-c0 (= ${Source-Version}), ${shlibs:Depends} -Description: Sample XML-RPC applications - Some handy XML-RPC demo applications based on the Meerkat Open Wire Service - (found at http://www.oreillynet.com/meerkat/). You can use 'query-meerkat' to - perform a regex search on recent news items, or 'meerkat-app-list' to get - a list of recent Linux software releases. - diff --git a/libs/xmlrpc-c/debian/copyright b/libs/xmlrpc-c/debian/copyright deleted file mode 100644 index 8873b9d..0000000 --- a/libs/xmlrpc-c/debian/copyright +++ /dev/null @@ -1,128 +0,0 @@ -This software package is covered by the XML-RPC C Library License. -Additionally, certain parts of this library are derived from pre-existing -code, which may carry its own license. - -In particular, the Expat Licence applies to the contents of the directory -lib/expat, the ABYSS Web Server License applies to the contents of the -directory lib/abyss and parts of the file src/xmlrpc_abyss.c, and the -Python 1.5.2 license applies to parts of the file src/xmlrpc_base64.c. - -And as for the tools/ directory, you'll have to examine the licenses on -your own. - - - XML-RPC C Library License - ------------------------- - -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. - - - Expat License - ------------- - -Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - - ABYSS Web Server License - ------------------------ - -Copyright (C) 2000 by Moez Mahfoudh . 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. - - - - Python 1.5.2 License - -------------------- - -Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum, -Amsterdam, The Netherlands. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the names of Stichting Mathematisch -Centrum or CWI or Corporation for National Research Initiatives or -CNRI not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -While CWI is the initial source for this software, a modified version -is made available by the Corporation for National Research Initiatives -(CNRI) at the Internet address ftp://ftp.python.org. - -STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH -CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL -DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR -PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THIS SOFTWARE. diff --git a/libs/xmlrpc-c/debian/postinst b/libs/xmlrpc-c/debian/postinst deleted file mode 100644 index a7b0408..0000000 --- a/libs/xmlrpc-c/debian/postinst +++ /dev/null @@ -1,47 +0,0 @@ -#! /bin/sh -# postinst script for xmlrpc-c -# -# see: dh_installdeb(1) - -set -e - -# summary of how this script can be called: -# * `configure' -# * `abort-upgrade' -# * `abort-remove' `in-favour' -# -# * `abort-deconfigure' `in-favour' -# `removing' -# -# for details, see /usr/share/doc/packaging-manual/ -# -# quoting from the policy: -# Any necessary prompting should almost always be confined to the -# post-installation script, and should be protected with a conditional -# so that unnecessary prompting doesn't happen if a package's -# installation fails and the `postinst' is called with `abort-upgrade', -# `abort-remove' or `abort-deconfigure'. - -case "$1" in - configure) - ldconfig - ;; - - abort-upgrade|abort-remove|abort-deconfigure) - - ;; - - *) - echo "postinst called with unknown argument \`$1'" >&2 - exit 0 - ;; -esac - -# dh_installdeb will replace this with shell code automatically -# generated by other debhelper scripts. - -#DEBHELPER# - -exit 0 - - diff --git a/libs/xmlrpc-c/debian/postrm b/libs/xmlrpc-c/debian/postrm deleted file mode 100644 index 3294e0a..0000000 --- a/libs/xmlrpc-c/debian/postrm +++ /dev/null @@ -1,39 +0,0 @@ -#! /bin/sh -# postrm script for xmlrpc-c -# -# see: dh_installdeb(1) - -set -e - -# summary of how this script can be called: -# * `remove' -# * `purge' -# * `upgrade' -# * `failed-upgrade' -# * `abort-install' -# * `abort-install' -# * `abort-upgrade' -# * `disappear' overwrit>r> -# for details, see /usr/share/doc/packaging-manual/ - -case "$1" in - remove) - ldconfig - ;; - - purge|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) - - ;; - - *) - echo "postrm called with unknown argument \`$1'" >&2 - exit 0 - -esac - -# dh_installdeb will replace this with shell code automatically -# generated by other debhelper scripts. - -#DEBHELPER# - - diff --git a/libs/xmlrpc-c/debian/rules b/libs/xmlrpc-c/debian/rules deleted file mode 100644 index c7c728c..0000000 --- a/libs/xmlrpc-c/debian/rules +++ /dev/null @@ -1,97 +0,0 @@ -#!/usr/bin/make -f -# Sample debian/rules that uses debhelper. -# GNU copyright 1997 to 1999 by Joey Hess. - -# Uncomment this to turn on verbose mode. -#export DH_VERBOSE=1 - -# This is the debhelper compatability version to use. -export DH_COMPAT=3 - -# shared library versions, option 1 -#version=2.0.5 -#major=2 -# option 2, assuming the library is created as src/.libs/libfoo.so.2.0.5 or so -version=`ls src/.libs/lib*.so.* | \ - awk '{if (match($$0,/[0-9]+\.[0-9]+\.[0-9]+$$/)) print substr($$0,RSTART)}'` -major=`ls src/.libs/lib*.so.* | \ - awk '{if (match($$0,/\.so\.[0-9]+$$/)) print substr($$0,RSTART+4)}'` - -configure: configure-stamp -configure-stamp: - dh_testdir - # Add here commands to configure the package. - ./configure --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info - - touch configure-stamp - -build: configure-stamp build-stamp -build-stamp: - dh_testdir - - # Add here commands to compile the package. - $(MAKE) - $(MAKE) check - - touch build-stamp - -clean: - dh_testdir - dh_testroot - rm -f build-stamp configure-stamp - - # Add here commands to clean up after the build process. - -$(MAKE) distclean - - dh_clean - -install: build - dh_testdir - dh_testroot - dh_clean -k - dh_installdirs - - # Add here commands to install the package into debian/tmp - $(MAKE) DESTDIR=$(CURDIR)/debian/tmp install - - -# Build architecture-independent files here. -binary-indep: build install -# We have nothing to do by default. - -# Build architecture-dependent files here. -binary-arch: build install - dh_testdir - dh_testroot - dh_movefiles - -# dh_installdebconf - dh_installdocs - dh_installexamples - dh_installmenu -# dh_installlogrotate -# dh_installemacsen -# dh_installpam -# dh_installmime -# dh_installinit - dh_installcron -# dh_installman debian/xmlrpc-c.7 -# dh_installman -p xmlrpc-c-dev debian/xml-rpc-api2cpp.1 debian/xml-rpc-api2txt.1 debian/xmlrpc-c-config.1 -# dh_installman -p xmlrpc-c-apps debian/meerkat-app-list.1 debian/query-meerkat.1 - dh_installinfo -# dh_undocumented - dh_installchangelogs - dh_link - dh_strip - dh_compress - dh_fixperms - dh_makeshlibs - dh_installdeb -# dh_perl - dh_shlibdeps -l"$(CURDIR)/debian/xmlrpc-c0/usr/lib/:$$LD_LIBRARY_PATH" - dh_gencontrol - dh_md5sums - dh_builddeb - -binary: binary-indep binary-arch -.PHONY: build clean binary-indep binary-arch binary install configure diff --git a/libs/xmlrpc-c/debian/xmlrpc-c-apps.files b/libs/xmlrpc-c/debian/xmlrpc-c-apps.files deleted file mode 100644 index 3f005c6..0000000 --- a/libs/xmlrpc-c/debian/xmlrpc-c-apps.files +++ /dev/null @@ -1,4 +0,0 @@ -usr/bin/query-meerkat -usr/bin/meerkat-app-list -usr/share/man/man1/query-meerkat.1 -usr/share/man/man1/meerkat-app-list.1 diff --git a/libs/xmlrpc-c/debian/xmlrpc-c-dev.files b/libs/xmlrpc-c/debian/xmlrpc-c-dev.files deleted file mode 100644 index f1cc55d..0000000 --- a/libs/xmlrpc-c/debian/xmlrpc-c-dev.files +++ /dev/null @@ -1,10 +0,0 @@ -usr/bin/xmlrpc-c-config -usr/bin/xml-rpc-api2txt -usr/bin/xml-rpc-api2cpp -usr/include/* -usr/lib/lib*.a -usr/lib/lib*.la -usr/lib/lib*.so -usr/share/man/man1/xmlrpc-c-config.1 -usr/share/man/man1/xml-rpc-api2txt.1 -usr/share/man/man1/xml-rpc-api2cpp.1 diff --git a/libs/xmlrpc-c/debian/xmlrpc-c0.docs b/libs/xmlrpc-c/debian/xmlrpc-c0.docs deleted file mode 100644 index 6df52b9..0000000 --- a/libs/xmlrpc-c/debian/xmlrpc-c0.docs +++ /dev/null @@ -1,6 +0,0 @@ -BUGS -NEWS -README -CREDITS -SECURITY -doc/*.txt diff --git a/libs/xmlrpc-c/debian/xmlrpc-c0.examples b/libs/xmlrpc-c/debian/xmlrpc-c0.examples deleted file mode 100644 index d510cc5..0000000 --- a/libs/xmlrpc-c/debian/xmlrpc-c0.examples +++ /dev/null @@ -1,3 +0,0 @@ -examples/*.c -examples/*.cc -conf diff --git a/libs/xmlrpc-c/debian/xmlrpc-c0.files b/libs/xmlrpc-c/debian/xmlrpc-c0.files deleted file mode 100644 index 6f82592..0000000 --- a/libs/xmlrpc-c/debian/xmlrpc-c0.files +++ /dev/null @@ -1,2 +0,0 @@ -usr/lib/lib*.so.* -usr/share/man/man7/xmlrpc-c.7 diff --git a/libs/xmlrpc-c/dll-common.make b/libs/xmlrpc-c/dll-common.make deleted file mode 100644 index 0d53c17..0000000 --- a/libs/xmlrpc-c/dll-common.make +++ /dev/null @@ -1,22 +0,0 @@ -# -*-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)/$< diff --git a/libs/xmlrpc-c/dll-common.mk b/libs/xmlrpc-c/dll-common.mk new file mode 100644 index 0000000..9840709 --- /dev/null +++ b/libs/xmlrpc-c/dll-common.mk @@ -0,0 +1,22 @@ +# -*-makefile-*- <-- an Emacs control + +# See unix-common.mk for an explanation of this file. This file is +# analogous to unix-common.mk, 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):%/install:%.$(SHLIB_SUFFIX) +# $< is a library file name, e.g. libfoo.dll . + $(INSTALL_SHLIB) $< $(DESTDIR)$(LIBINST_DIR)/$< diff --git a/libs/xmlrpc-c/doc/INSTALL b/libs/xmlrpc-c/doc/INSTALL index 76881fa..2790010 100644 --- a/libs/xmlrpc-c/doc/INSTALL +++ b/libs/xmlrpc-c/doc/INSTALL @@ -82,6 +82,48 @@ you have to have a -f option and set SRCDIR and BLDDIR on your 'make' command. +CROSS-COMPILING +--------------- + +Cross compiling is building code on one machine to be run on another, +particularly when the two machines are different enough that it matters, +e.g. one executes x86 instructions and the other executes PowerPC +instructions. + +The machine that will run the code is called the target machine. The one +that will build the code is the build machine. + +To cross-compile, you set up nearly all of the build environment for the +target machine (that includes such things as the default include file search +path for the compiler and library search path for the linker). On your +'configure' command, you use a --host option to identify the kind of target +machine (rather than let it default to the kind of machine on which +'configure' is running). It's a nontrivial task, and beyond the scope of +this document as it is not specific to Xmlrpc-c. + +There is one area that requires special attention and is specific to Xmlrpc-c: +The Xmlrpc-c build does part of its job by compiling a program from C source +code and running that program as part of the build. That compile, unlike all +the regular ones, must be done for the build machine, not the target +machine. + +To facilitate that, there are the BUILDTOOL_CC and BUILDTOOL_CCLD make +variables. BUILDTOOL_CC is the command name for the appropriate compiler +which which to build a build tool, i.e. a compiler that generates code to run +on the build system. BUILDTOOL_CCLD is similarly for the linker, and should +be the kind of linker command that invokes a combined compiler/linker, +e.g. "gcc" instead of "ld". + +You can set these make variables on the Make command line, or if you prefer, +by modifying the file 'config.mk' after 'configure' creates it. The default +value of these variables (as set in 'config.mk') is the same compile and link +commands as for building target code. + +(There is probably a way to do this with GNU Autoconf facilities and avoid the +BUILDTOOL_CC complication. If you know how (without using Automake), tell the +Xmlrpc-c maintainer and he will change the build system to use it). + + COMMON PROBLEMS --------------- @@ -135,7 +177,7 @@ 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 +build directory. And they do that because curl-config erroneously says that you need a -L /usr/lib link option to find the Curl library. diff --git a/libs/xmlrpc-c/dylib-common.make b/libs/xmlrpc-c/dylib-common.make deleted file mode 100644 index a72d416..0000000 --- a/libs/xmlrpc-c/dylib-common.make +++ /dev/null @@ -1,37 +0,0 @@ -# -*-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)) diff --git a/libs/xmlrpc-c/dylib-common.mk b/libs/xmlrpc-c/dylib-common.mk new file mode 100644 index 0000000..c9ac6c5 --- /dev/null +++ b/libs/xmlrpc-c/dylib-common.mk @@ -0,0 +1,37 @@ +# -*-makefile-*- <-- an Emacs control + +# See unix-common.mk for an explanation of this file. This file is +# analogous to unix-common.mk, but is for an Irix system. + +SONAME = $(@:%.$(MIN)=%) + +SHLIB_CMD = $(CCLD) $(LADD) $(LDFLAGS_SHLIB) -o $@ $^ + +SHLIBPP_CMD = $(CXXLD) $(LADD) $(LDFLAGS_SHLIB) -o $@ $^ + +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)) diff --git a/libs/xmlrpc-c/examples/.cvsignore b/libs/xmlrpc-c/examples/.cvsignore deleted file mode 100644 index 792265c..0000000 --- a/libs/xmlrpc-c/examples/.cvsignore +++ /dev/null @@ -1,11 +0,0 @@ -gen_sample_add_xml -meerkat-app-list -query-meerkat -synch_client -xmlrpc_asynch_client -auth_client -xmlrpc_loop_server -xmlrpc_sample_add_client -xmlrpc_sample_add_server -xmlrpc_server_validatee -*.cgi diff --git a/libs/xmlrpc-c/examples/Makefile b/libs/xmlrpc-c/examples/Makefile index 5a9fd19..c441c9f 100644 --- a/libs/xmlrpc-c/examples/Makefile +++ b/libs/xmlrpc-c/examples/Makefile @@ -1,8 +1,8 @@ -# Since the programs in this directories are examples for the user, this -# make file should be as ordinary as possible. It should not rely heavily -# on included make files or configuration parameters. It should not use -# libtool. Also, we don't try to build or rebuild the libraries on which -# these programs depend. +# Since the programs in this directory are examples for the user, this make +# file should be as ordinary as possible. It should not rely heavily on +# included make files or configuration parameters. Also, we don't try to +# build or rebuild the libraries on which these programs depend or even +# recognize that they've changed on their own. ifeq ($(SRCDIR),) @@ -15,8 +15,8 @@ include $(BLDDIR)/config.mk default: all -CFLAGS = $(CFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD) -LDFLAGS = $(LADD) +CFLAGS = $(CFLAGS_PERSONAL) $(CADD) +LDFLAGS += $(LADD) # 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 @@ -25,6 +25,7 @@ XMLRPC_C_CONFIG = $(BLDDIR)/xmlrpc-c-config.test CLIENTPROGS = \ auth_client \ + compound_value_client \ synch_client \ xmlrpc_sample_add_client \ xmlrpc_asynch_client \ @@ -37,6 +38,7 @@ SERVERPROGS_CGI = \ xmlrpc_sample_add_server.cgi SERVERPROGS_ABYSS = \ + compound_value_server \ interrupted_server \ xmlrpc_inetd_server \ xmlrpc_socket_server \ @@ -44,15 +46,19 @@ SERVERPROGS_ABYSS = \ xmlrpc_sample_add_server \ xmlrpc_server_validatee \ +BASIC_PROGS = \ + json \ + gen_sample_add_xml \ + # Build up PROGS: PROGS = +PROGS += $(BASIC_PROGS) + ifeq ($(ENABLE_ABYSS_SERVER),yes) PROGS += $(SERVERPROGS_ABYSS) endif -PROGS += gen_sample_add_xml - ifeq ($(MUST_BUILD_CLIENT),yes) PROGS += $(CLIENTPROGS) endif @@ -63,17 +69,17 @@ endif INCLUDES = -I. $(shell $(XMLRPC_C_CONFIG) client abyss-server --cflags) -LDADD_CLIENT = \ - $(shell $(XMLRPC_C_CONFIG) client --ldadd) +LIBS_CLIENT = \ + $(shell $(XMLRPC_C_CONFIG) client --libs) -LDADD_SERVER_ABYSS = \ - $(shell $(XMLRPC_C_CONFIG) abyss-server --ldadd) +LIBS_SERVER_ABYSS = \ + $(shell $(XMLRPC_C_CONFIG) abyss-server --libs) -LDADD_SERVER_CGI = \ - $(shell $(XMLRPC_C_CONFIG) cgi-server --ldadd) +LIBS_SERVER_CGI = \ + $(shell $(XMLRPC_C_CONFIG) cgi-server --libs) -LDADD_BASE = \ - $(shell $(XMLRPC_C_CONFIG) --ldadd) +LIBS_BASE = \ + $(shell $(XMLRPC_C_CONFIG) --libs) all: $(PROGS) @@ -90,16 +96,17 @@ $(BLDDIR)/examples/cpp: mkdir $@ $(CLIENTPROGS):%:%.o - $(CCLD) -o $@ $(LDFLAGS) $^ $(LDADD_CLIENT) + $(CCLD) -o $@ $^ $(LIBS_CLIENT) $(LDFLAGS) $(SERVERPROGS_CGI):%.cgi:%_cgi.o - $(CCLD) -o $@ $(LDFLAGS) $^ $(LDADD_SERVER_CGI) + $(CCLD) -o $@ $^ $(LIBS_SERVER_CGI) $(LDFLAGS) $(SERVERPROGS_ABYSS):%:%.o - $(CCLD) -o $@ $(LDFLAGS) $^ $(LDADD_SERVER_ABYSS) + $(CCLD) -o $@ $^ $(LIBS_SERVER_ABYSS) $(LDFLAGS) + +$(BASIC_PROGS):%:%.o + $(CCLD) -o $@ $^ $(LIBS_BASE) $(LDFLAGS) -gen_sample_add_xml:%:%.o - $(CCLD) -o $@ $(LDFLAGS) $^ $(LDADD_BASE) OBJECTS = $(patsubst %,%.o,$(patsubst %.cgi,%_cgi,$(PROGS))) @@ -119,11 +126,9 @@ config.h: xmlrpc_amconfig.h: $(LN_S) $(BLDDIR)/$@ . -include $(SRCDIR)/common.mk - .PHONY: clean -clean: clean-common - rm -f $(PROGS) config.h xmlrpc_amconfig.h +clean: + rm -f $(PROGS) *.o config.h xmlrpc_amconfig.h $(MAKE) -C cpp clean .PHONY: distclean diff --git a/libs/xmlrpc-c/examples/README b/libs/xmlrpc-c/examples/README index 46b02b4..6691f8a 100644 --- a/libs/xmlrpc-c/examples/README +++ b/libs/xmlrpc-c/examples/README @@ -1,15 +1,12 @@ This directory contains working examples of uses of XML-RPC-c. There are XML-RPC servers and XML-RPC clients that use the Xmlrpc-c libraries. -The simplest example is the 'query-meerkat' program, which contacts an -XML-RPC server that O'Reilly operates on the Internet called Meerkat. -Meerkat provides an RPC that returns a list of new articles that match -a specified search pattern. Run 'query-meerkat' like this example: - - $ ./query-meerkat Linux - -This responds with a list of new articles that contain the work "Linux", -according to O'reilly's Meerkat service. +The make file is a combination of an example of how to build programs +that use Xmlrpc-c libraries and something that actually does build the +programs in this directory. As such, it isn't perfect for either of +those purposes. To build the examples, you must first build the +libraries (make dependencies will not take care of that for you). Then +you can issue a simple 'make' in this directory. The simplest server program is 'xmlrpc_sample_add_server'. This diff --git a/libs/xmlrpc-c/examples/auth_client.c b/libs/xmlrpc-c/examples/auth_client.c index 50047f4..fbbd0a9 100644 --- a/libs/xmlrpc-c/examples/auth_client.c +++ b/libs/xmlrpc-c/examples/auth_client.c @@ -35,7 +35,7 @@ die_if_fault_occurred(xmlrpc_env * const envP) { int main(int const argc, - const char ** const argv ATTR_UNUSED) { + const char ** const argv) { xmlrpc_env env; xmlrpc_server_info * serverP; diff --git a/libs/xmlrpc-c/examples/compound_value_client.c b/libs/xmlrpc-c/examples/compound_value_client.c new file mode 100644 index 0000000..92baad1 --- /dev/null +++ b/libs/xmlrpc-c/examples/compound_value_client.c @@ -0,0 +1,161 @@ +/* An XML-RPC client program written in C, as an example of using + compound XML-RPC values. + + For a simple client program that just deals with integer values, + see xmlrpc_sample_add_client.c. This example focuses just on the + compound XML-RPC values and not the client functions. + + This client invokes the example.divide XML-RPC method that the example + server program compound_value_server.c provides. That method takes a + list of pairs of numbers and returns the list of their quotients. + + Compound XML-RPC values are arrays and structures. We call them compound + because they are made up of other XML-RPC values (e.g. an array of XML-RPC + integers). + + The arguments to the example.divide method are specified as follows: + + There are two arguments: + + Argument 0: Integer. Version number of this argument protocol. Must + be 1. + + + Argument 1: Array. One element for each pair of numbers you want the + server to divide. Each element is structure, with these + members: + + KEY: "dividend" + VALUE: floating point number. The dividend. + + KEY: "divisor" + VALUE: floating point number. The divisor. + + The result of the method is an array. It has one member for each pair of + numbers in the arguments (So it is the same size as Argument 1). That + member is a floating point number. It is the quotient of the numbers + in the corresponding element of Argument 1. + + The client sends the RPC to the server running on the local system + ("localhost"), HTTP Port 8080. +*/ + +#include +#include + +#include +#include + +#include "config.h" /* information about this build environment */ + +#define NAME "Xmlrpc-c Test Client" +#define VERSION "1.0" + +static void +dieIfFaultOccurred (xmlrpc_env * const envP) { + if (envP->fault_occurred) { + fprintf(stderr, "ERROR: %s (%d)\n", + envP->fault_string, envP->fault_code); + exit(1); + } +} + + + +struct ratio { + double dividend; + double divisor; +}; + + + +int +main(int const argc, + const char ** const argv) { + + const char * const serverUrl = "http://localhost:8080/RPC2"; + const char * const methodName = "example.divide"; + unsigned int const argVersion = 1; + struct ratio const data[] = {{1,2},{12,3},{10,3},{89,3000}}; + xmlrpc_env env; + xmlrpc_value * resultP; + unsigned int i; + xmlrpc_value * ratioArrayP; + unsigned int quotientCt; + + if (argc-1 > 0) { + fprintf(stderr, "This program has no arguments\n"); + exit(1); + } + + xmlrpc_env_init(&env); + + xmlrpc_client_init2(&env, XMLRPC_CLIENT_NO_FLAGS, NAME, VERSION, NULL, 0); + dieIfFaultOccurred(&env); + + /* Build the 2nd method argument: the array of ratios */ + + ratioArrayP = xmlrpc_array_new(&env); + dieIfFaultOccurred(&env); + + for (i = 0; i < 4; ++i) { + xmlrpc_value * dividendP; + xmlrpc_value * divisorP; + xmlrpc_value * ratioP; + + dividendP = xmlrpc_double_new(&env, data[i].dividend); + dieIfFaultOccurred(&env); + divisorP = xmlrpc_double_new(&env, data[i].divisor); + dieIfFaultOccurred(&env); + + ratioP = xmlrpc_struct_new(&env); + dieIfFaultOccurred(&env); + + xmlrpc_struct_set_value(&env, ratioP, "DIVIDEND", dividendP); + dieIfFaultOccurred(&env); + xmlrpc_struct_set_value(&env, ratioP, "DIVISOR", divisorP); + dieIfFaultOccurred(&env); + + xmlrpc_array_append_item(&env, ratioArrayP, ratioP); + dieIfFaultOccurred(&env); + + xmlrpc_DECREF(ratioP); + xmlrpc_DECREF(divisorP); + xmlrpc_DECREF(dividendP); + } + + /* Make the call */ + + resultP = xmlrpc_client_call(&env, serverUrl, methodName, "(iA)", + (xmlrpc_int32) argVersion, ratioArrayP); + dieIfFaultOccurred(&env); + + /* Print out the quotients returned */ + + quotientCt = xmlrpc_array_size(&env, resultP); + dieIfFaultOccurred(&env); + + for (i = 0; i < quotientCt; ++i) { + xmlrpc_value * quotientP; + xmlrpc_double quotient; + + xmlrpc_array_read_item(&env, resultP, i, "ientP); + dieIfFaultOccurred(&env); + + xmlrpc_read_double(&env, quotientP, "ient); + dieIfFaultOccurred(&env); + + printf("Server says quotient %u is %f\n", i, quotient); + + xmlrpc_DECREF(quotientP); + } + + xmlrpc_DECREF(resultP); + + xmlrpc_env_clean(&env); + + xmlrpc_client_cleanup(); + + return 0; +} + diff --git a/libs/xmlrpc-c/examples/compound_value_server.c b/libs/xmlrpc-c/examples/compound_value_server.c new file mode 100644 index 0000000..99d1127 --- /dev/null +++ b/libs/xmlrpc-c/examples/compound_value_server.c @@ -0,0 +1,199 @@ +/* An XML-RPC server program written in C, as an example of using + compound XML-RPC values. + + For a simple server program that just deals with integer values, + see xmlrpc_sample_add_server.c. This example focuses just on the + compound XML-RPC values and not the server functions. + + This server provides the example.divide XML-RPC method that the example + client program compound_value_client.c invokes. See that program for + details on what the method does. + + The program takes one argument: the HTTP port number on which the server + is to accept connections, in decimal. + + Example: + + $ ./compound_value_server 8080& + $ ./compound_value_client +*/ + +#include +#include + +#include +#include +#include + +#include "config.h" /* information about this build environment */ + + + +static void +computeQuotient(xmlrpc_env * const envP, + xmlrpc_value * const ratioP, + xmlrpc_double * const quotientP) { + + xmlrpc_value * dividendP; + + xmlrpc_struct_find_value(envP, ratioP, "DIVIDEND", ÷ndP); + + if (!envP->fault_occurred) { + if (!dividendP) + xmlrpc_env_set_fault( + envP, 0, "Structure is missing 'DIVIDEND' member"); + else { + xmlrpc_value * divisorP; + + xmlrpc_struct_find_value(envP, ratioP, "DIVISOR", &divisorP); + + if (!envP->fault_occurred) { + if (!divisorP) + xmlrpc_env_set_fault( + envP, 0, "Structure is missing 'DIVISOR' member"); + else { + xmlrpc_double dividend; + + xmlrpc_read_double(envP, dividendP, ÷nd); + + if (!envP->fault_occurred) { + xmlrpc_double divisor; + + xmlrpc_read_double(envP, divisorP, &divisor); + + if (!envP->fault_occurred) + *quotientP = dividend / divisor; + } + xmlrpc_DECREF(divisorP); + } + } + xmlrpc_DECREF(dividendP); + } + } +} + + + +static void +computeQuotients(xmlrpc_env * const envP, + xmlrpc_value * const ratioArrayP, + xmlrpc_value ** const quotientArrayPP) { + + xmlrpc_value * quotientArrayP; + + quotientArrayP = xmlrpc_array_new(envP); + if (!envP->fault_occurred) { + + unsigned int const ratioCt = xmlrpc_array_size(envP, ratioArrayP); + + unsigned int i; + + for (i = 0; i < ratioCt && !envP->fault_occurred; ++i) { + xmlrpc_value * ratioP; + + xmlrpc_array_read_item(envP, ratioArrayP, i, &ratioP); + + if (!envP->fault_occurred) { + xmlrpc_double quotient; + + computeQuotient(envP, ratioP, "ient); + + if (!envP->fault_occurred) { + xmlrpc_value * quotientP; + + quotientP = xmlrpc_double_new(envP, quotient); + + if (!envP->fault_occurred) { + xmlrpc_array_append_item(envP, quotientArrayP, + quotientP); + + xmlrpc_DECREF(quotientP); + } + } + xmlrpc_DECREF(ratioP); + } + } + if (envP->fault_occurred) + xmlrpc_DECREF(quotientArrayP); + else + *quotientArrayPP = quotientArrayP; + } +} + + + +static xmlrpc_value * +example_divide(xmlrpc_env * const envP, + xmlrpc_value * const paramArrayP, + void * const serverInfo, + void * const channelInfo) { + + xmlrpc_value * retvalP; + xmlrpc_int32 argVersion; + xmlrpc_value * ratioArrayP; + + xmlrpc_decompose_value(envP, paramArrayP, "(iA)", + &argVersion, &ratioArrayP); + if (envP->fault_occurred) + return NULL; + + if (argVersion != 1) { + xmlrpc_env_set_fault(envP, 0, "Parameter list version must be 1"); + return NULL; + } + + computeQuotients(envP, ratioArrayP, &retvalP); + + xmlrpc_DECREF(ratioArrayP); + + if (envP->fault_occurred) + return NULL; + + return retvalP; +} + + + +int +main(int const argc, + const char ** const argv) { + + struct xmlrpc_method_info3 const methodInfo = { + /* .methodName = */ "example.divide", + /* .methodFunction = */ &example_divide, + }; + xmlrpc_server_abyss_parms serverparm; + xmlrpc_registry * registryP; + xmlrpc_env env; + + if (argc-1 != 1) { + fprintf(stderr, "You must specify 1 argument: The TCP port " + "number on which the server will accept connections " + "for RPCs (8080 is a common choice). " + "You specified %d arguments.\n", argc-1); + exit(1); + } + + xmlrpc_env_init(&env); + + registryP = xmlrpc_registry_new(&env); + + xmlrpc_registry_add_method3(&env, registryP, &methodInfo); + + /* 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"; + + printf("Running XML-RPC server...\n"); + + xmlrpc_server_abyss(&env, &serverparm, XMLRPC_APSIZE(log_file_name)); + + /* xmlrpc_server_abyss() never returns */ + + return 0; +} diff --git a/libs/xmlrpc-c/examples/cpp/.cvsignore b/libs/xmlrpc-c/examples/cpp/.cvsignore deleted file mode 100644 index fedad6b..0000000 --- a/libs/xmlrpc-c/examples/cpp/.cvsignore +++ /dev/null @@ -1,4 +0,0 @@ -meerkat-app-list -xmlrpc_sample_add_server -xmlrpc_sample_add_client -sample_add_client_complex diff --git a/libs/xmlrpc-c/examples/cpp/Makefile b/libs/xmlrpc-c/examples/cpp/Makefile index 1c8b930..18798cb 100644 --- a/libs/xmlrpc-c/examples/cpp/Makefile +++ b/libs/xmlrpc-c/examples/cpp/Makefile @@ -15,8 +15,8 @@ include $(BLDDIR)/config.mk default: all -CXXFLAGS = $(CXXFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD) -LDFLAGS = $(LADD) +CXXFLAGS = $(CFLAGS_PERSONAL) $(CADD) +LDFLAGS += $(LADD) # 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 @@ -24,10 +24,14 @@ LDFLAGS = $(LADD) XMLRPC_C_CONFIG = $(BLDDIR)/xmlrpc-c-config.test +SERVERPROGS_CGI = \ + xmlrpc_sample_add_server.cgi + SERVERPROGS_ABYSS = \ xmlrpc_inetd_server \ xmlrpc_loop_server \ xmlrpc_sample_add_server \ + callinfo_abyss_server \ CLIENTPROGS = \ xmlrpc_sample_add_client \ @@ -45,7 +49,11 @@ ifeq ($(MUST_BUILD_CLIENT),yes) PROGS += $(CLIENTPROGS) endif -PROGS += pstream_inetd_server +ifeq ($(ENABLE_CGI_SERVER),yes) + PROGS += $(SERVERPROGS_CGI) +endif + +PROGS += pstream_inetd_server pstream_serial_server ifeq ($(MUST_BUILD_CLIENT),yes) PROGS += pstream_client @@ -53,37 +61,43 @@ 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) +LIBS_SERVER_ABYSS = \ + $(shell $(XMLRPC_C_CONFIG) c++2 abyss-server --libs) -LDADD_CLIENT = \ - $(shell $(XMLRPC_C_CONFIG) c++2 client --ldadd) +LIBS_SERVER_CGI = \ + $(shell $(XMLRPC_C_CONFIG) c++2 cgi-server --libs) -LDADD_BASE = \ - $(shell $(XMLRPC_C_CONFIG) c++2 --ldadd) +LIBS_CLIENT = \ + $(shell $(XMLRPC_C_CONFIG) c++2 client --libs) + +LIBS_BASE = \ + $(shell $(XMLRPC_C_CONFIG) c++2 --libs) all: $(PROGS) +$(SERVERPROGS_CGI):%.cgi:%_cgi.o + $(CXXLD) -o $@ $^ $(LIBS_SERVER_CGI) $(LDFLAGS) + $(SERVERPROGS_ABYSS):%:%.o - $(CXXLD) -o $@ $(LDFLAGS) $^ $(LDADD_SERVER_ABYSS) + $(CXXLD) -o $@ $^ $(LIBS_SERVER_ABYSS) $(LDFLAGS) $(CLIENTPROGS):%:%.o - $(CXXLD) -o $@ $(LDFLAGS) $^ $(LDADD_CLIENT) + $(CXXLD) -o $@ $^ $(LIBS_CLIENT) $(LDFLAGS) -LDADD_PSTREAM_CLIENT = \ - $(shell $(XMLRPC_C_CONFIG) c++2 client --ldadd) +LIBS_PSTREAM_CLIENT = \ + $(shell $(XMLRPC_C_CONFIG) c++2 client --libs) pstream_client:%:%.o - $(CXXLD) -o $@ $(LDFLAGS) $^ $(LDADD_PSTREAM_CLIENT) + $(CXXLD) -o $@ $^ $(LIBS_PSTREAM_CLIENT) $(LDFLAGS) -LDADD_PSTREAM_SERVER = \ - $(shell $(XMLRPC_C_CONFIG) c++2 pstream-server --ldadd) +LIBS_PSTREAM_SERVER = \ + $(shell $(XMLRPC_C_CONFIG) c++2 pstream-server --libs) -pstream_inetd_server:%:%.o - $(CXXLD) -o $@ $(LDFLAGS) $^ $(LDADD_PSTREAM_SERVER) +pstream_inetd_server pstream_serial_server:%:%.o + $(CXXLD) -o $@ $^ $(LIBS_PSTREAM_SERVER) $(LDFLAGS) -OBJECTS = $(PROGS:%=%.o) +OBJECTS = $(patsubst %,%.o,$(patsubst %.cgi,%_cgi,$(PROGS))) $(OBJECTS):%.o:%.cpp $(CXX) -c $(INCLUDES) $(CXXFLAGS) $< @@ -97,11 +111,9 @@ config.h: xmlrpc_amconfig.h: $(LN_S) $(BLDDIR)/$@ . -include $(SRCDIR)/common.mk - .PHONY: clean -clean: clean-common - rm -f $(PROGS) config.h xmlrpc_amconfig.h +clean: + rm -f $(PROGS) *.o config.h xmlrpc_amconfig.h .PHONY: distclean distclean: clean diff --git a/libs/xmlrpc-c/examples/cpp/callinfo_abyss_server.cpp b/libs/xmlrpc-c/examples/cpp/callinfo_abyss_server.cpp new file mode 100644 index 0000000..a297b8e --- /dev/null +++ b/libs/xmlrpc-c/examples/cpp/callinfo_abyss_server.cpp @@ -0,0 +1,133 @@ +// A simple standalone XML-RPC server written in C++. +// +// This server returns to the caller his IP address and port number, +// as a demonstration of how to access such information. +// +// This works only on Unix (to wit, something that uses Abyss's +// ChanSwitchUnix channel switch to accept TCP connections from clients). +// +// See xmlrpc_sample_add_server.cpp for a more basic example. +// +// To run this: +// +// $ ./callinfo_abyss_server & +// $ xmlrpc localhost:8080 getCallInfo + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +using namespace std; + + +struct tcpPortAddr { + unsigned char ipAddr[4]; + unsigned short portNumber; +}; + + +static struct tcpPortAddr +tcpAddrFromSockAddr(struct sockaddr const sockAddr) { + + const struct sockaddr_in * const sockAddrInP( + static_cast((void *)&sockAddr)); + + const unsigned char * const ipAddr( + static_cast( + (const void *)&sockAddrInP->sin_addr.s_addr) + ); // 4 byte array + + assert(sockAddrInP->sin_family == AF_INET); + + struct tcpPortAddr retval; + + retval.ipAddr[0] = ipAddr[0]; + retval.ipAddr[1] = ipAddr[1]; + retval.ipAddr[2] = ipAddr[2]; + retval.ipAddr[3] = ipAddr[3]; + retval.portNumber = ntohs(sockAddrInP->sin_port); + + return retval; +} + + + +static std::string +rpcIpAddrMsg(xmlrpc_c::callInfo_serverAbyss const& callInfo) { + + void * chanInfoPtr; + SessionGetChannelInfo(callInfo.abyssSessionP, &chanInfoPtr); + + struct abyss_unix_chaninfo * const chanInfoP( + static_cast(chanInfoPtr)); + + struct tcpPortAddr const tcpAddr(tcpAddrFromSockAddr(chanInfoP->peerAddr)); + + char msg[128]; + + sprintf(msg, "RPC is from IP address %u.%u.%u.%u, Port %hu", + tcpAddr.ipAddr[0], + tcpAddr.ipAddr[1], + tcpAddr.ipAddr[2], + tcpAddr.ipAddr[3], + tcpAddr.portNumber); + + return std::string(msg); +} + + + +class getCallInfoMethod : public xmlrpc_c::method2 { +public: + void + execute(xmlrpc_c::paramList const& paramList, + const xmlrpc_c::callInfo * const callInfoPtr, + xmlrpc_c::value * const retvalP) { + + const xmlrpc_c::callInfo_serverAbyss * const callInfoP( + dynamic_cast(callInfoPtr)); + + paramList.verifyEnd(0); + + // Because this gets called via a xmlrpc_c::serverAbyss: + assert(callInfoP != NULL); + + *retvalP = xmlrpc_c::value_string(rpcIpAddrMsg(*callInfoP)); + } +}; + + + +int +main(int const, + const char ** const) { + + try { + xmlrpc_c::registry myRegistry; + + xmlrpc_c::methodPtr const getCallInfoMethodP(new getCallInfoMethod); + + myRegistry.addMethod("getCallInfo", getCallInfoMethodP); + + xmlrpc_c::serverAbyss myAbyssServer(xmlrpc_c::serverAbyss::constrOpt() + .registryP(&myRegistry) + .portNumber(8080) + ); + + myAbyssServer.run(); + // xmlrpc_c::serverAbyss.run() never returns + assert(false); + } catch (exception const& e) { + cerr << "Something failed. " << e.what() << endl; + } + return 0; +} diff --git a/libs/xmlrpc-c/examples/cpp/meerkat-app-list.cpp b/libs/xmlrpc-c/examples/cpp/meerkat-app-list.cpp deleted file mode 100644 index c2bd1e3..0000000 --- a/libs/xmlrpc-c/examples/cpp/meerkat-app-list.cpp +++ /dev/null @@ -1,108 +0,0 @@ -// List recently-released Linux applications. (Written in C++.) -// For more details about O'Reilly's excellent Meerkat news service, see: -// http://www.oreillynet.com/pub/a/rss/2000/11/14/meerkat_xmlrpc.html */ - -#include -#include -#include - -using namespace std; - -#include - -#define NAME "XML-RPC C++ Meerkat Query Demo" -#define VERSION "0.1" -#define MEERKAT_URL "http://www.oreillynet.com/meerkat/xml-rpc/server.php" -#define SOFTWARE_LINUX (6) - -static void list_apps (int hours) { - - // Build our time_period parameter. - ostringstream time_period_stream; - time_period_stream << hours << "HOUR"; - string time_period = time_period_stream.str(); - - // Assemble our meerkat query recipe. - XmlRpcValue recipe = XmlRpcValue::makeStruct(); - recipe.structSetValue("category", XmlRpcValue::makeInt(SOFTWARE_LINUX)); - recipe.structSetValue("time_period", XmlRpcValue::makeString(time_period)); - recipe.structSetValue("descriptions", XmlRpcValue::makeInt(76)); - - // Build our parameter array. - XmlRpcValue param_array = XmlRpcValue::makeArray(); - param_array.arrayAppendItem(recipe); - - // Create a client pointing to Meerkat. - XmlRpcClient meerkat (MEERKAT_URL); - - // Perform the query. - XmlRpcValue apps = meerkat.call("meerkat.getItems", param_array); - - // Print our results. - int first = 1; - size_t app_count = apps.arraySize(); - for (size_t i = 0; i < app_count; i++) { - XmlRpcValue app = apps.arrayGetItem(i); - - // Get some information about our application. - string title = app.structGetValue("title").getString(); - string link = app.structGetValue("link").getString(); - string description = app.structGetValue("description").getString(); - - // Print a separator line if necessary. - if (first) - first = 0; - else - cout << endl; - - // Print this application entry. - if (description.size() > 0) { - cout << title << endl << description << endl << link << endl; - } else { - cout << title << endl << description << endl << link << endl; - } - } -} - -// Print out a usage message. -static void usage (void) -{ - cerr << "Usage: meekat-app-list [hours]" << endl; - cerr << "Data from ." << endl; - exit(1); -} - -int main (int argc, char **argv) { - int status = 0; - int hours = 25; - - // Parse our command-line arguments. - if (argc == 1) { - // Use default value for hours. - } else if (argc == 2) { - hours = atoi(argv[1]); - } - if (hours == 0) - usage(); - if (hours > 49) { - cerr << "It's not nice to ask for > 49 hours at once." << endl; - exit(1); - } - - // Start up our client library. - XmlRpcClient::Initialize(NAME, VERSION); - - // Call our implementation, and watch out for faults. - try { - list_apps(hours); - } catch (XmlRpcFault& fault) { - cerr << argv[0] << ": XML-RPC fault #" << fault.getFaultCode() - << ": " << fault.getFaultString() << endl; - status = 1; - } - - // Shut down our client library. - XmlRpcClient::Terminate(); - - return status; -} diff --git a/libs/xmlrpc-c/examples/cpp/pstream_client.cpp b/libs/xmlrpc-c/examples/cpp/pstream_client.cpp index 7a8f322..738e8ba 100644 --- a/libs/xmlrpc-c/examples/cpp/pstream_client.cpp +++ b/libs/xmlrpc-c/examples/cpp/pstream_client.cpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/libs/xmlrpc-c/examples/cpp/pstream_inetd_server.cpp b/libs/xmlrpc-c/examples/cpp/pstream_inetd_server.cpp index 65f1aa5..00d930c 100644 --- a/libs/xmlrpc-c/examples/cpp/pstream_inetd_server.cpp +++ b/libs/xmlrpc-c/examples/cpp/pstream_inetd_server.cpp @@ -22,7 +22,7 @@ #endif #include #include -#include +#include #include #include @@ -76,12 +76,7 @@ main(int const, .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. + server.run(); } catch (exception const& e) { cerr << "Something threw an error: " << e.what() << endl; diff --git a/libs/xmlrpc-c/examples/cpp/pstream_serial_server.cpp b/libs/xmlrpc-c/examples/cpp/pstream_serial_server.cpp new file mode 100644 index 0000000..aba2fbe --- /dev/null +++ b/libs/xmlrpc-c/examples/cpp/pstream_serial_server.cpp @@ -0,0 +1,84 @@ +/* A simple standalone RPC server based on an Xmlrpc-c packet socket. + + This program expects the invoker to provide a socket in listen mode + as Standard Input. + + 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 -listen -local_port=8080 ./pstream_serial_server +*/ + +#ifndef WIN32 +#include +#endif +#include +#include +#include + +#include +#include +#include + +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::serverPstream server( + xmlrpc_c::serverPstream::constrOpt() + .socketFd(STDIN_FILENO) + .registryP(&myRegistry)); + + server.runSerial(); + + } catch (exception const& e) { + cerr << "Something threw an error: " << e.what() << endl; + } + return 0; +} diff --git a/libs/xmlrpc-c/examples/cpp/xmlrpc_inetd_server.cpp b/libs/xmlrpc-c/examples/cpp/xmlrpc_inetd_server.cpp index 0dd902a..3bfe186 100644 --- a/libs/xmlrpc-c/examples/cpp/xmlrpc_inetd_server.cpp +++ b/libs/xmlrpc-c/examples/cpp/xmlrpc_inetd_server.cpp @@ -1,6 +1,25 @@ /* 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. + + A typical example of where this would be useful is with an Inetd + "super server." + + xmlrpc_sample_add_server.cpp is a server that does the same thing, + but you give it a TCP port number and it listens for TCP connections + 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 listens 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. */ #ifndef WIN32 @@ -49,10 +68,8 @@ main(int const, myRegistry.addMethod("sample.add", sampleAddMethodP); xmlrpc_c::serverAbyss myAbyssServer( - myRegistry, - 8080, // TCP port on which to listen - "/tmp/xmlrpc_log" // Log file - ); + xmlrpc_c::serverAbyss::constrOpt() + .registryP(&myRegistry)); myAbyssServer.runConn(STDIN_FILENO); /* This reads the HTTP POST request from Standard Input and diff --git a/libs/xmlrpc-c/examples/cpp/xmlrpc_sample_add_server.cpp b/libs/xmlrpc-c/examples/cpp/xmlrpc_sample_add_server.cpp index ff96ae2..f499e5a 100644 --- a/libs/xmlrpc-c/examples/cpp/xmlrpc_sample_add_server.cpp +++ b/libs/xmlrpc-c/examples/cpp/xmlrpc_sample_add_server.cpp @@ -62,10 +62,9 @@ main(int const, myRegistry.addMethod("sample.add", sampleAddMethodP); xmlrpc_c::serverAbyss myAbyssServer( - myRegistry, - 8080, // TCP port on which to listen - "/tmp/xmlrpc_log" // Log file - ); + xmlrpc_c::serverAbyss::constrOpt() + .registryP(&myRegistry) + .portNumber(8080)); myAbyssServer.run(); // xmlrpc_c::serverAbyss.run() never returns diff --git a/libs/xmlrpc-c/examples/cpp/xmlrpc_sample_add_server_cgi.cpp b/libs/xmlrpc-c/examples/cpp/xmlrpc_sample_add_server_cgi.cpp new file mode 100644 index 0000000..9b80603 --- /dev/null +++ b/libs/xmlrpc-c/examples/cpp/xmlrpc_sample_add_server_cgi.cpp @@ -0,0 +1,62 @@ +/* A CGI script that effects a simple XML-RPC server, written in C++. + + See the identically named C program source code for hints on running + this example. + +*/ + +#include +#include + +#include +#include +#include + +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::serverCgi myServer( + xmlrpc_c::serverCgi::constrOpt() + .registryP(&myRegistry)); + + myServer.processCall(); + + } catch (exception const& e) { + cerr << "Something failed. " << e.what() << endl; + } + return 0; +} diff --git a/libs/xmlrpc-c/examples/gen_sample_add_xml.c b/libs/xmlrpc-c/examples/gen_sample_add_xml.c index 736d822..dd65699 100644 --- a/libs/xmlrpc-c/examples/gen_sample_add_xml.c +++ b/libs/xmlrpc-c/examples/gen_sample_add_xml.c @@ -28,7 +28,7 @@ die_if_fault_occurred(xmlrpc_env * const envP) { int main(int const argc, - const char ** const argv ATTR_UNUSED) { + const char ** const argv) { char * const methodName = "sample.add"; diff --git a/libs/xmlrpc-c/examples/interrupted_client.c b/libs/xmlrpc-c/examples/interrupted_client.c index 89cd4e8..1652be2 100644 --- a/libs/xmlrpc-c/examples/interrupted_client.c +++ b/libs/xmlrpc-c/examples/interrupted_client.c @@ -2,6 +2,7 @@ both by timeout and by control-C. */ +#define _XOPEN_SOURCE 600 #include #include #include @@ -110,7 +111,7 @@ addInterruptibly(xmlrpc_client * const clientP, int main(int const argc, - const char ** const argv ATTR_UNUSED) { + const char ** const argv) { const char * const serverUrl = "http://localhost:8080/RPC2"; diff --git a/libs/xmlrpc-c/examples/interrupted_server.c b/libs/xmlrpc-c/examples/interrupted_server.c index 9d5c593..56bac81 100644 --- a/libs/xmlrpc-c/examples/interrupted_server.c +++ b/libs/xmlrpc-c/examples/interrupted_server.c @@ -1,4 +1,4 @@ -/* A simple standalone XML-RPC server based on Abyss. +/* A simple standalone XML-RPC server program based on Abyss. You can terminate this server in controlled fashion with a SIGTERM signal. @@ -7,6 +7,7 @@ simpler code, but it is not interruptible with SIGTERM. */ +#define _XOPEN_SOURCE 600 #include #include #include @@ -36,7 +37,7 @@ dieIfFailed(const char * const description, static xmlrpc_server_abyss_t * serverToTerminateP; static void -sigtermHandler(int const signalClass ATTR_UNUSED) { +sigtermHandler(int const signalClass) { xmlrpc_env env; @@ -82,8 +83,8 @@ restoreSigtermHandler(void){ static xmlrpc_value * sample_add(xmlrpc_env * const envP, xmlrpc_value * const paramArrayP, - void * const serverInfo ATTR_UNUSED, - void * const channelInfo ATTR_UNUSED) { + void * const serverInfo, + void * const channelInfo) { xmlrpc_int x, y, z; @@ -105,6 +106,11 @@ int main(int const argc, const char ** const argv) { + struct xmlrpc_method_info3 const methodInfo = { + .methodName = "sample.add", + .methodFunction = &sample_add, + .serverInfo = NULL + }; xmlrpc_server_abyss_parms serverparm; xmlrpc_server_abyss_t * serverP; xmlrpc_registry * registryP; @@ -126,8 +132,7 @@ main(int const argc, registryP = xmlrpc_registry_new(&env); dieIfFailed("xmlrpc_registry_new", env); - xmlrpc_registry_add_method2( - &env, registryP, "sample.add", &sample_add, NULL, NULL, NULL); + xmlrpc_registry_add_method3(&env, registryP, &methodInfo); dieIfFailed("xmlrpc_registry_add_method2", env); serverparm.config_file_name = NULL; diff --git a/libs/xmlrpc-c/examples/json.c b/libs/xmlrpc-c/examples/json.c new file mode 100644 index 0000000..89fe82b --- /dev/null +++ b/libs/xmlrpc-c/examples/json.c @@ -0,0 +1,115 @@ +/* + This example program demonstrates the JSON parsing and generating + capabilities of Xmlrpc-c. + + The program reads JSON text from Standard Input and displays its value as + XML-RPC XML text. It then re-generates JSON from the intermediate + parsed information and displays that. +*/ +#include +#include + +#include + + + +static void +dieIfFaultOccurred(xmlrpc_env * const envP) { + if (envP->fault_occurred) { + fprintf(stderr, "ERROR: %s (%d)\n", + envP->fault_string, envP->fault_code); + exit(1); + } +} + + + +void +printAsXml(xmlrpc_value * const valP) { + + xmlrpc_env env; + xmlrpc_mem_block out; + + xmlrpc_env_init(&env); + + XMLRPC_MEMBLOCK_INIT(char, &env, &out, 0); + + dieIfFaultOccurred(&env); + + xmlrpc_serialize_value(&env, &out, valP); + + printf("XML-RPC XML:\n"); + + printf("%.*s\n", + XMLRPC_MEMBLOCK_SIZE(char, &out), + XMLRPC_MEMBLOCK_CONTENTS(char, &out)); + + XMLRPC_MEMBLOCK_CLEAN(char, &out); + xmlrpc_env_clean(&env); +} + + + +void +printAsJson(xmlrpc_value * const valP) { + + xmlrpc_env env; + xmlrpc_mem_block out; + xmlrpc_value * val2P; + + xmlrpc_env_init(&env); + + XMLRPC_MEMBLOCK_INIT(char, &env, &out, 0); + + dieIfFaultOccurred(&env); + + xmlrpc_serialize_json(&env, valP, &out); + + dieIfFaultOccurred(&env); + + printf("JSON:\n"); + + printf("%.*s\n", + XMLRPC_MEMBLOCK_SIZE(char, &out), + XMLRPC_MEMBLOCK_CONTENTS(char, &out)); + + XMLRPC_MEMBLOCK_CLEAN(char, &out); + xmlrpc_env_clean(&env); +} + + + +int +main(int argc, const char *argv[]) { + + xmlrpc_env env; + char buf[1024]; + xmlrpc_value * valP; + size_t bytesRead; + + xmlrpc_env_init(&env); + + if (argc-1 > 0) { + fprintf(stderr, "This program has no arguments. " + "JSON input is from Standard Input\n"); + exit(1); + } + + bytesRead = fread(buf, 1, sizeof(buf), stdin); + buf[bytesRead] = '\0'; + + valP = xmlrpc_parse_json(&env, buf); + + dieIfFaultOccurred(&env); + + printAsXml(valP); + + printAsJson(valP); + + xmlrpc_DECREF(valP); + xmlrpc_env_clean(&env); + + return 0; +} + + diff --git a/libs/xmlrpc-c/examples/query-meerkat.c b/libs/xmlrpc-c/examples/query-meerkat.c deleted file mode 100644 index e566654..0000000 --- a/libs/xmlrpc-c/examples/query-meerkat.c +++ /dev/null @@ -1,156 +0,0 @@ -/* A simple news-searcher, written in C to demonstrate how to use the - xmplrpc-c client library. - - This program connects to an XMLRPC server that O'Reilly runs on the - Internet, gets some information, and displays it on Standard Output. - - Note that that server is not in any way designed specifically for xmlrpc-c. - It simply implements the XMLRPC protocol, and works with any client that - implements XMLRPC. - - The service that the aforementioned server provides is that it gives you - a list of news articles that match a certain regular expression. You give - that regular expression an argument to this client program. - - For more details about O'Reilly's excellent Meerkat news service, see: - http://www.oreillynet.com/pub/a/rss/2000/11/14/meerkat_xmlrpc.html -*/ - -#include -#include -#include - -#include -#include - -#include "config.h" /* information about this build environment */ - -#define NAME "XML-RPC C Meerkat Query Demo" -#define VERSION "1.0" -#define MEERKAT_URL "http://www.oreillynet.com/meerkat/xml-rpc/server.php" - -struct cmdline { - const char * searchArg; - int hours; -}; - - -static void -parseCommandLine(int const argc, - const char ** const argv, - struct cmdline * const cmdlineP) { - - if (argc-1 < 1) { - fprintf(stderr, "Need at least one argument: " - "A mysql regular expression " - "search pattern. Try 'query-meerkat Linux'\n"); - exit(1); - } else { - cmdlineP->searchArg = argv[1]; - - if (argc-1 < 2) { - cmdlineP->hours = 24; - } else { - cmdlineP->hours = atoi(argv[2]); - if (cmdlineP->hours > 49) { - fprintf(stderr, "It's not nice to ask for > 49 hours " - "at once.\n"); - exit(1); - } - if (argc-1 > 2) { - fprintf(stderr, "There are at most 2 arguments: " - "search pattern " - "and number of hours."); - exit(1); - } - } - } -} - - - -static void -die_if_fault_occurred(xmlrpc_env * const env) { - /* We're a command-line utility, so we abort if an error occurs. */ - if (env->fault_occurred) { - fprintf(stderr, "XML-RPC Fault #%d: %s\n", - env->fault_code, env->fault_string); - exit(1); - } -} - - - -/* Hey! We fit in one function. */ -int -main(int const argc, - const char** const argv) { - - struct cmdline cmdline; - char time_period[16]; - xmlrpc_env env; - xmlrpc_value *stories, *story; - size_t size, i; - int first; - - parseCommandLine(argc, argv, &cmdline); - - snprintf(time_period, sizeof(time_period), "%dHOUR", cmdline.hours); - - xmlrpc_env_init(&env); - - /* Set up our client. */ - xmlrpc_client_init2(&env, XMLRPC_CLIENT_NO_FLAGS, NAME, VERSION, NULL, 0); - - die_if_fault_occurred(&env); - - /* Ask Meerkat to look for matching stories. */ - stories = xmlrpc_client_call(&env, MEERKAT_URL, - "meerkat.getItems", "({s:s,s:i,s:s})", - "search", cmdline.searchArg, - "descriptions", (xmlrpc_int32) 76, - "time_period", time_period); - die_if_fault_occurred(&env); - - /* Loop over the stories. */ - size = xmlrpc_array_size(&env, stories); - die_if_fault_occurred(&env); - first = 1; - for (i = 0; i < size; i++) { - const char * title; - const char * link; - const char * description; - - /* Extract the useful information from our story. */ - story = xmlrpc_array_get_item(&env, stories, i); - die_if_fault_occurred(&env); - xmlrpc_decompose_value(&env, story, "{s:s,s:s,s:s,*}", - "title", &title, - "link", &link, - "description", &description); - die_if_fault_occurred(&env); - - /* Print a separator line if necessary. */ - if (first) - first = 0; - else - printf("\n"); - - /* Print the story. */ - if (strlen(description) > 0) { - printf("%s\n%s\n%s\n", title, description, link); - } else { - printf("%s\n%s\n", title, link); - } - free((char*)title); - free((char*)link); - free((char*)description); - } - - /* Shut down our client. */ - xmlrpc_DECREF(stories); - xmlrpc_env_clean(&env); - xmlrpc_client_cleanup(); - - return 0; -} diff --git a/libs/xmlrpc-c/examples/synch_client.c b/libs/xmlrpc-c/examples/synch_client.c index 589aa7b..b9b62a2 100644 --- a/libs/xmlrpc-c/examples/synch_client.c +++ b/libs/xmlrpc-c/examples/synch_client.c @@ -1,4 +1,4 @@ -/* A simple synchronous XML-RPC client written in C. */ +/* A simple synchronous XML-RPC client program written in C. */ #include #include @@ -24,7 +24,7 @@ die_if_fault_occurred(xmlrpc_env * const envP) { int main(int const argc, - const char ** const argv ATTR_UNUSED) { + const char ** const argv) { xmlrpc_env env; xmlrpc_value * resultP; diff --git a/libs/xmlrpc-c/examples/xmlrpc_asynch_client.c b/libs/xmlrpc-c/examples/xmlrpc_asynch_client.c index ec3bd31..ff56dfd 100644 --- a/libs/xmlrpc-c/examples/xmlrpc_asynch_client.c +++ b/libs/xmlrpc-c/examples/xmlrpc_asynch_client.c @@ -1,4 +1,4 @@ -/* A simple asynchronous XML-RPC client written in C, as an example of +/* A simple asynchronous XML-RPC client program written in C, as an example of Xmlrpc-c asynchronous RPC facilities. This is the same as the simpler synchronous client xmlprc_sample_add_client.c, except that it adds 3 different pairs of numbers with the summation RPCs going on @@ -35,7 +35,7 @@ static void handle_sample_add_response(const char * const serverUrl, const char * const methodName, xmlrpc_value * const paramArrayP, - void * const user_data ATTR_UNUSED, + void * const user_data, xmlrpc_env * const faultP, xmlrpc_value * const resultP) { @@ -70,7 +70,7 @@ handle_sample_add_response(const char * const serverUrl, int main(int const argc, - const char ** const argv ATTR_UNUSED) { + const char ** const argv) { const char * const serverUrl = "http://localhost:8080/RPC2"; const char * const methodName = "sample.add"; diff --git a/libs/xmlrpc-c/examples/xmlrpc_inetd_server.c b/libs/xmlrpc-c/examples/xmlrpc_inetd_server.c index 196b42a..8b1bb48 100644 --- a/libs/xmlrpc-c/examples/xmlrpc_inetd_server.c +++ b/libs/xmlrpc-c/examples/xmlrpc_inetd_server.c @@ -1,4 +1,4 @@ -/* A simple standalone XML-RPC server based on Abyss that processes a +/* A simple standalone XML-RPC server program 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 @@ -21,6 +21,7 @@ respond to the client, then exit. */ +#define _XOPEN_SOURCE 600 #include #include #include @@ -63,8 +64,8 @@ setupSignalHandlers(void) { static xmlrpc_value * sample_add(xmlrpc_env * const envP, xmlrpc_value * const paramArrayP, - void * const serverInfo ATTR_UNUSED, - void * const channelInfo ATTR_UNUSED) { + void * const serverInfo, + void * const channelInfo) { xmlrpc_int x, y, z; @@ -86,6 +87,11 @@ int main(int const argc, const char ** const argv) { + struct xmlrpc_method_info3 const methodInfo = { + .methodName = "sample.add", + .methodFunction = &sample_add, + .serverInfo = NULL + }; TServer abyssServer; xmlrpc_registry * registryP; xmlrpc_env env; @@ -101,8 +107,7 @@ main(int const argc, registryP = xmlrpc_registry_new(&env); - xmlrpc_registry_add_method2( - &env, registryP, "sample.add", &sample_add, NULL, NULL, NULL); + xmlrpc_registry_add_method3(&env, registryP, &methodInfo); ServerCreateNoAccept(&abyssServer, "XmlRpcServer", NULL, NULL); diff --git a/libs/xmlrpc-c/examples/xmlrpc_loop_server.c b/libs/xmlrpc-c/examples/xmlrpc_loop_server.c index 2553ea6..af0c750 100644 --- a/libs/xmlrpc-c/examples/xmlrpc_loop_server.c +++ b/libs/xmlrpc-c/examples/xmlrpc_loop_server.c @@ -1,11 +1,14 @@ -/* A simple standalone XML-RPC server based on Abyss that contains a +/* A simple standalone XML-RPC server program based on Abyss that contains a simple one-thread request processing loop. + This uses the "provide your own Abyss server" mode of operation. + xmlrpc_sample_add_server.c 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. */ +#define _XOPEN_SOURCE 600 #include #include #include @@ -66,7 +69,7 @@ printPeerIpAddr(TSession * const abyssSessionP) { static xmlrpc_value * sample_add(xmlrpc_env * const envP, xmlrpc_value * const paramArrayP, - void * const serverInfo ATTR_UNUSED, + void * const serverInfo, void * const channelInfo) { xmlrpc_int x, y, z; @@ -117,6 +120,11 @@ int main(int const argc, const char ** const argv) { + struct xmlrpc_method_info3 const methodInfo = { + .methodName = "sample.add", + .methodFunction = &sample_add, + .serverInfo = NULL + }; TServer abyssServer; xmlrpc_registry * registryP; xmlrpc_env env; @@ -136,8 +144,7 @@ main(int const argc, registryP = xmlrpc_registry_new(&env); - xmlrpc_registry_add_method2( - &env, registryP, "sample.add", &sample_add, NULL, NULL, NULL); + xmlrpc_registry_add_method3(&env, registryP, &methodInfo); xmlrpc_registry_set_shutdown(registryP, &requestShutdown, &terminationRequested); diff --git a/libs/xmlrpc-c/examples/xmlrpc_sample_add_client.c b/libs/xmlrpc-c/examples/xmlrpc_sample_add_client.c index f675a92..3a219dd 100644 --- a/libs/xmlrpc-c/examples/xmlrpc_sample_add_client.c +++ b/libs/xmlrpc-c/examples/xmlrpc_sample_add_client.c @@ -1,7 +1,10 @@ -/* A simple synchronous XML-RPC client written in C, as an example of +/* A simple synchronous XML-RPC client program written in C, as an example of an Xmlrpc-c client. This invokes the sample.add procedure that the - Xmlrpc-c example server.c server provides. I.e. it adds to numbers - together, the hard way. + Xmlrpc-c example xmlrpc_sample_add_server.c server provides. I.e. it adds + two numbers together, the hard way. + + This sends the RPC to the server running on the local system ("localhost"), + HTTP Port 8080. */ #include @@ -16,9 +19,9 @@ #define VERSION "1.0" static void -die_if_fault_occurred (xmlrpc_env * const envP) { +dieIfFaultOccurred (xmlrpc_env * const envP) { if (envP->fault_occurred) { - fprintf(stderr, "XML-RPC Fault: %s (%d)\n", + fprintf(stderr, "ERROR: %s (%d)\n", envP->fault_string, envP->fault_code); exit(1); } @@ -28,7 +31,7 @@ die_if_fault_occurred (xmlrpc_env * const envP) { int main(int const argc, - const char ** const argv ATTR_UNUSED) { + const char ** const argv) { xmlrpc_env env; xmlrpc_value * resultP; @@ -46,7 +49,7 @@ main(int const argc, /* Start up our XML-RPC client library. */ xmlrpc_client_init2(&env, XMLRPC_CLIENT_NO_FLAGS, NAME, VERSION, NULL, 0); - die_if_fault_occurred(&env); + dieIfFaultOccurred(&env); printf("Making XMLRPC call to server url '%s' method '%s' " "to request the sum " @@ -55,11 +58,11 @@ main(int const argc, /* Make the remote procedure call */ resultP = xmlrpc_client_call(&env, serverUrl, methodName, "(ii)", (xmlrpc_int32) 5, (xmlrpc_int32) 7); - die_if_fault_occurred(&env); + dieIfFaultOccurred(&env); /* Get our sum and print it out. */ xmlrpc_read_int(&env, resultP, &sum); - die_if_fault_occurred(&env); + dieIfFaultOccurred(&env); printf("The sum is %d\n", sum); /* Dispose of our result value. */ diff --git a/libs/xmlrpc-c/examples/xmlrpc_sample_add_server.c b/libs/xmlrpc-c/examples/xmlrpc_sample_add_server.c index dbd2861..a4a4370 100644 --- a/libs/xmlrpc-c/examples/xmlrpc_sample_add_server.c +++ b/libs/xmlrpc-c/examples/xmlrpc_sample_add_server.c @@ -1,4 +1,24 @@ -/* A simple standalone XML-RPC server written in C. */ +/* A simple standalone XML-RPC server program written in C. */ + +/* This server knows one RPC class (besides the system classes): + "sample.add". + + The program takes one argument: the HTTP port number on which the server + is to accept connections, in decimal. + + You can use the example program 'xmlrpc_sample_add_client' to send an RPC + to this server. + + Example: + + $ ./xmlrpc_sample_add_server 8080& + $ ./xmlrpc_sample_add_client + + For more fun, run client and server in separate terminals and turn on + tracing for each: + + $ export XMLRPC_TRACE_XML=1 +*/ #include #include @@ -25,8 +45,8 @@ static xmlrpc_value * sample_add(xmlrpc_env * const envP, xmlrpc_value * const paramArrayP, - void * const serverInfo ATTR_UNUSED, - void * const channelInfo ATTR_UNUSED) { + void * const serverInfo, + void * const channelInfo) { xmlrpc_int32 x, y, z; @@ -54,6 +74,10 @@ int main(int const argc, const char ** const argv) { + struct xmlrpc_method_info3 const methodInfo = { + /* .methodName = */ "sample.add", + /* .methodFunction = */ &sample_add, + }; xmlrpc_server_abyss_parms serverparm; xmlrpc_registry * registryP; xmlrpc_env env; @@ -70,8 +94,7 @@ main(int const argc, registryP = xmlrpc_registry_new(&env); - xmlrpc_registry_add_method2( - &env, registryP, "sample.add", &sample_add, NULL, NULL, NULL); + xmlrpc_registry_add_method3(&env, registryP, &methodInfo); /* In the modern form of the Abyss API, we supply parameters in memory like a normal API. We select the modern form by setting diff --git a/libs/xmlrpc-c/examples/xmlrpc_sample_add_server_cgi.c b/libs/xmlrpc-c/examples/xmlrpc_sample_add_server_cgi.c index fa476a7..e34c4d7 100644 --- a/libs/xmlrpc-c/examples/xmlrpc_sample_add_server_cgi.c +++ b/libs/xmlrpc-c/examples/xmlrpc_sample_add_server_cgi.c @@ -1,4 +1,22 @@ -/* A simple standalone XML-RPC server written in C. */ +/* A CGI script written in C to effect a simple XML-RPC server. + + Example of use: + + - Compile this as the executable 'xmlrpc_sample_add_server.cgi' + + - Place the .cgi file in web server www.example.com's /cgi-bin + directory. + + - Configure the web server to permit CGI scripts in /cgi-bin + (Apache ExecCgi directory option). + + - Configure the web server to recognize this .cgi file as a CGI + script (Apache "AddHandler cgi-script ..." or ScriptAlias). + + - $ xmlrpc http://www.example.com/cgi-bin/xmlrpc_sample_add_server.cgi \ + sample.add i/5 i/7 +*/ + #include #include @@ -12,7 +30,7 @@ static xmlrpc_value * sample_add(xmlrpc_env * const envP, xmlrpc_value * const paramArrayP, - void * const user_data ATTR_UNUSED) { + void * const user_data) { xmlrpc_int32 x, y, z; diff --git a/libs/xmlrpc-c/examples/xmlrpc_server_validatee.c b/libs/xmlrpc-c/examples/xmlrpc_server_validatee.c index 927da8a..ad613a8 100644 --- a/libs/xmlrpc-c/examples/xmlrpc_server_validatee.c +++ b/libs/xmlrpc-c/examples/xmlrpc_server_validatee.c @@ -66,7 +66,7 @@ static xmlrpc_value * array_of_structs(xmlrpc_env * const envP, xmlrpc_value * const paramArrayP, - void * const user_data ATTR_UNUSED) { + void * const user_data) { xmlrpc_value * arrayP; xmlrpc_value * retval; @@ -114,7 +114,7 @@ array_of_structs(xmlrpc_env * const envP, static xmlrpc_value * count_entities(xmlrpc_env * const envP, xmlrpc_value * const paramArrayP, - void * const user_data ATTR_UNUSED) { + void * const user_data) { const char * str; size_t len, i; @@ -154,7 +154,7 @@ count_entities(xmlrpc_env * const envP, static xmlrpc_value * easy_struct(xmlrpc_env * const envP, xmlrpc_value * const paramArrayP, - void * const user_data ATTR_UNUSED) { + void * const user_data) { xmlrpc_int32 larry, moe, curly; @@ -179,7 +179,7 @@ easy_struct(xmlrpc_env * const envP, static xmlrpc_value * echo_struct(xmlrpc_env * const envP, xmlrpc_value * const paramArrayP, - void * const user_data ATTR_UNUSED) { + void * const user_data) { xmlrpc_value * sP; @@ -198,9 +198,9 @@ echo_struct(xmlrpc_env * const envP, */ static xmlrpc_value * -many_types(xmlrpc_env * const env ATTR_UNUSED, +many_types(xmlrpc_env * const env, xmlrpc_value * const param_array, - void * const user_data ATTR_UNUSED) { + void * const user_data) { /* Create another reference to our argument array and return it as is. */ xmlrpc_INCREF(param_array); @@ -244,7 +244,7 @@ concatenate(xmlrpc_env * const envP, static xmlrpc_value * moderate_array(xmlrpc_env * const envP, xmlrpc_value * const paramArrayP, - void * const user_data ATTR_UNUSED) { + void * const user_data) { xmlrpc_value * retval; xmlrpc_value * arrayP; @@ -295,7 +295,7 @@ moderate_array(xmlrpc_env * const envP, static xmlrpc_value * nested_struct(xmlrpc_env * const envP, xmlrpc_value * const paramArrayP, - void * const user_data ATTR_UNUSED) { + void * const user_data) { xmlrpc_value * yearsP; xmlrpc_value * retval; @@ -333,7 +333,7 @@ nested_struct(xmlrpc_env * const envP, static xmlrpc_value * struct_return(xmlrpc_env * const envP, xmlrpc_value * const paramArrayP, - void * const user_data ATTR_UNUSED) { + void * const user_data) { xmlrpc_int32 i; diff --git a/libs/xmlrpc-c/examples/xmlrpc_socket_server.c b/libs/xmlrpc-c/examples/xmlrpc_socket_server.c index 2e2cd8b..9cbc5aa 100644 --- a/libs/xmlrpc-c/examples/xmlrpc_socket_server.c +++ b/libs/xmlrpc-c/examples/xmlrpc_socket_server.c @@ -1,5 +1,5 @@ -/* A simple standalone XML-RPC server written in C as an example of use of - the Xmlrpc-c libraries. +/* A simple standalone XML-RPC server program 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, @@ -7,7 +7,11 @@ 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. - */ + + Example: + + $ socketexec -local_port=8080 ./xmlrpc_socket_server +*/ #include #include @@ -33,7 +37,8 @@ static xmlrpc_value * sample_add(xmlrpc_env * const envP, xmlrpc_value * const paramArrayP, - void * const user_data ATTR_UNUSED) { + void * const serverInfo, + void * const channelInfo) { xmlrpc_int32 x, y, z; @@ -61,6 +66,11 @@ int main(int const argc, const char ** const argv) { + struct xmlrpc_method_info3 const methodInfo = { + .methodName = "sample.add", + .methodFunction = &sample_add, + .serverInfo = NULL + }; xmlrpc_server_abyss_parms serverparm; xmlrpc_registry * registryP; xmlrpc_env env; @@ -77,8 +87,7 @@ main(int const argc, registryP = xmlrpc_registry_new(&env); - xmlrpc_registry_add_method( - &env, registryP, NULL, "sample.add", &sample_add, NULL); + xmlrpc_registry_add_method3(&env, registryP, &methodInfo); /* In the modern form of the Abyss API, we supply parameters in memory like a normal API. We select the modern form by setting diff --git a/libs/xmlrpc-c/include/Makefile b/libs/xmlrpc-c/include/Makefile index d396ca7..28fd00b 100644 --- a/libs/xmlrpc-c/include/Makefile +++ b/libs/xmlrpc-c/include/Makefile @@ -36,18 +36,22 @@ xmlrpc-c/config.h: $(BLDDIR)/$(SUBDIR)/xmlrpc-c @echo ' #define XMLRPC_SOCKET SOCKET' >>$@ @echo ' #define XMLRPC_HAVE_TIMEVAL 0' >>$@ @echo ' #define XMLRPC_HAVE_TIMESPEC 0' >>$@ + @echo ' #define XMLRPC_HAVE_PTHREAD 0' >>$@ @echo '#else' >>$@ @echo ' #define XMLRPC_SOCKET int' >>$@ @echo ' #define XMLRPC_HAVE_TIMEVAL 1' >>$@ @echo ' #define XMLRPC_HAVE_TIMESPEC 1' >>$@ + @echo ' #define XMLRPC_HAVE_PTHREAD 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_PRId64 "I64"' >>$@ @echo ' #define XMLRPC_INT32 __int32' >>$@ @echo '#else' >>$@ @echo ' #define XMLRPC_INT64 long long' >>$@ + @echo ' #define XMLRPC_PRId64 "lld"' >>$@ @echo ' #define XMLRPC_INT32 int' >>$@ @echo '#endif' >>$@ @echo '#endif' >>$@ @@ -58,7 +62,7 @@ $(BLDDIR)/$(SUBDIR)/xmlrpc-c: 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_abyss.h xmlrpc_abyss.h; \ $(LN_S) xmlrpc-c/server_w32httpsys.h xmlrpc_server_w32httpsys.h; \ HEADERS_TO_INSTALL = \ @@ -67,6 +71,7 @@ HEADERS_TO_INSTALL = \ xmlrpc-c/c_util.h \ xmlrpc-c/util.h \ xmlrpc-c/base.h \ + xmlrpc-c/json.h \ xmlrpc-c/abyss.h \ xmlrpc-c/abyss_unixsock.h \ xmlrpc-c/abyss_winsock.h \ @@ -119,22 +124,25 @@ default: all all: .PHONY: install-compat-hdr -install-compat-hdr: +install-compat-hdr: install-headers # 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 \ + xmlrpc_server_abyss.h xmlrpc_abyss.h \ + xmlrpc_server_w32httpsys.h \ XmlRpcCpp.h; \ $(COMPAT_LINK_CMDS) .PHONY: install install: install-common install-compat-hdr -.PHONY: clean distclean dep +.PHONY: clean clean: -distclean: rm -f xmlrpc-c/config.h +.PHONY: distclean +distclean: clean + .PHONY: check check: diff --git a/libs/xmlrpc-c/include/xmlrpc-c/abyss.h b/libs/xmlrpc-c/include/xmlrpc-c/abyss.h index e044008..627e872 100644 --- a/libs/xmlrpc-c/include/xmlrpc-c/abyss.h +++ b/libs/xmlrpc-c/include/xmlrpc-c/abyss.h @@ -21,6 +21,7 @@ extern "C" { #include +#include #include /**************************************************************************** @@ -33,9 +34,11 @@ typedef int abyss_bool; GLOBAL (STATIC) PROGRAM STUFF ****************************************************************************/ +XMLRPC_DLLEXPORT void AbyssInit(const char ** const errorP); +XMLRPC_DLLEXPORT void AbyssTerm(void); @@ -45,23 +48,29 @@ AbyssTerm(void); typedef struct MIMEType MIMEType; +XMLRPC_DLLEXPORT MIMEType * MIMETypeCreate(void); +XMLRPC_DLLEXPORT void MIMETypeDestroy(MIMEType * const MIMETypeP); +XMLRPC_DLLEXPORT void MIMETypeInit(void); +XMLRPC_DLLEXPORT void MIMETypeTerm(void); +XMLRPC_DLLEXPORT abyss_bool MIMETypeAdd2(MIMEType * const MIMETypeP, const char * const type, const char * const ext); +XMLRPC_DLLEXPORT abyss_bool MIMETypeAdd(const char * const type, const char * const ext); @@ -81,9 +90,11 @@ typedef struct _TSocket TSocket; #include #endif +XMLRPC_DLLEXPORT void ChanSwitchInit(const char ** const errorP); +XMLRPC_DLLEXPORT void ChanSwitchTerm(void); @@ -92,18 +103,23 @@ ChanSwitchTerm(void); in abyss_unixsock.h, etc. */ +XMLRPC_DLLEXPORT void ChanSwitchDestroy(TChanSwitch * const chanSwitchP); +XMLRPC_DLLEXPORT void ChannelInit(const char ** const errorP); +XMLRPC_DLLEXPORT void ChannelTerm(void); +XMLRPC_DLLEXPORT void ChannelDestroy(TChannel * const channelP); +XMLRPC_DLLEXPORT void SocketDestroy(TSocket * const socketP); @@ -120,6 +136,7 @@ typedef struct { typedef struct _TSession TSession; +XMLRPC_DLLEXPORT abyss_bool ServerCreate(TServer * const serverP, const char * const name, @@ -127,11 +144,13 @@ ServerCreate(TServer * const serverP, const char * const filespath, const char * const logfilename); +XMLRPC_DLLEXPORT void ServerCreateSwitch(TServer * const serverP, TChanSwitch * const chanSwitchP, const char ** const errorP); +XMLRPC_DLLEXPORT abyss_bool ServerCreateSocket(TServer * const serverP, const char * const name, @@ -140,71 +159,87 @@ ServerCreateSocket(TServer * const serverP, const char * const logfilename); #define HAVE_SERVER_CREATE_SOCKET_2 +XMLRPC_DLLEXPORT void ServerCreateSocket2(TServer * const serverP, TSocket * const socketP, const char ** const errorP); +XMLRPC_DLLEXPORT abyss_bool ServerCreateNoAccept(TServer * const serverP, const char * const name, const char * const filespath, const char * const logfilename); +XMLRPC_DLLEXPORT void ServerFree(TServer * const serverP); +XMLRPC_DLLEXPORT void ServerSetName(TServer * const serverP, const char * const name); +XMLRPC_DLLEXPORT void ServerSetFilesPath(TServer * const serverP, const char * const filesPath); +XMLRPC_DLLEXPORT void ServerSetLogFileName(TServer * const serverP, const char * const logFileName); #define HAVE_SERVER_SET_KEEPALIVE_TIMEOUT 1 +XMLRPC_DLLEXPORT void ServerSetKeepaliveTimeout(TServer * const serverP, xmlrpc_uint32_t const keepaliveTimeout); #define HAVE_SERVER_SET_KEEPALIVE_MAX_CONN 1 +XMLRPC_DLLEXPORT void ServerSetKeepaliveMaxConn(TServer * const serverP, xmlrpc_uint32_t const keepaliveMaxConn); #define HAVE_SERVER_SET_TIMEOUT 1 +XMLRPC_DLLEXPORT void ServerSetTimeout(TServer * const serverP, xmlrpc_uint32_t const timeout); #define HAVE_SERVER_SET_ADVERTISE 1 +XMLRPC_DLLEXPORT void ServerSetAdvertise(TServer * const serverP, abyss_bool const advertise); #define HAVE_SERVER_SET_MIME_TYPE 1 +XMLRPC_DLLEXPORT void ServerSetMimeType(TServer * const serverP, MIMEType * const MIMETypeP); +XMLRPC_DLLEXPORT int ServerInit(TServer * const serverP); +XMLRPC_DLLEXPORT void ServerRun(TServer * const serverP); +XMLRPC_DLLEXPORT void ServerRunOnce(TServer * const serverP); /* ServerRunOnce2() is obsolete. See user's guide. */ +XMLRPC_DLLEXPORT void ServerRunOnce2(TServer * const serverP, enum abyss_foreback const foregroundBackground); +XMLRPC_DLLEXPORT void ServerRunChannel(TServer * const serverP, TChannel * const channelP, @@ -212,24 +247,30 @@ ServerRunChannel(TServer * const serverP, const char ** const errorP); #define HAVE_SERVER_RUN_CONN_2 +XMLRPC_DLLEXPORT void ServerRunConn2(TServer * const serverP, TSocket * const connectedSocketP, const char ** const errorP); +XMLRPC_DLLEXPORT void ServerRunConn(TServer * const serverP, TOsSocket const connectedSocket); +XMLRPC_DLLEXPORT void ServerDaemonize(TServer * const serverP); +XMLRPC_DLLEXPORT void ServerTerminate(TServer * const serverP); +XMLRPC_DLLEXPORT void ServerResetTerminate(TServer * const serverP); +XMLRPC_DLLEXPORT void ServerUseSigchld(TServer * const serverP); @@ -242,15 +283,31 @@ typedef abyss_bool (*URIHandler) (TSession *); /* deprecated */ struct URIHandler2; -typedef void (*initHandlerFn)(struct URIHandler2 *, - abyss_bool *); +typedef void (*initHandlerFn)(struct URIHandler2 *, abyss_bool *); typedef void (*termHandlerFn)(void *); +typedef void (*handleReq3Fn)(void *, + TSession *, + abyss_bool *); + typedef void (*handleReq2Fn)(struct URIHandler2 *, TSession *, abyss_bool *); +struct ServerReqHandler3 { + termHandlerFn term; + handleReq3Fn handleReq; + void * userdata; + size_t handleReqStackSize; /* zero = default */ +}; + +XMLRPC_DLLEXPORT +void +ServerAddHandler3(TServer * const serverP, + const struct ServerReqHandler3 * const handlerP, + abyss_bool * const successP); + typedef struct URIHandler2 { initHandlerFn init; termHandlerFn term; @@ -259,11 +316,13 @@ typedef struct URIHandler2 { void * userdata; } URIHandler2; +XMLRPC_DLLEXPORT void ServerAddHandler2(TServer * const srvP, URIHandler2 * const handlerP, abyss_bool * const successP); +XMLRPC_DLLEXPORT abyss_bool ServerAddHandler(TServer * const srvP, URIHandler const handler); @@ -274,6 +333,7 @@ typedef abyss_bool (*THandlerDflt) (TSession *); for the same type */ +XMLRPC_DLLEXPORT void ServerDefaultHandler(TServer * const srvP, THandlerDflt const handler); @@ -283,10 +343,12 @@ ServerDefaultHandler(TServer * const srvP, inappropriate for an API. */ +XMLRPC_DLLEXPORT abyss_bool ConfReadServerFile(const char * const filename, TServer * const srvP); +XMLRPC_DLLEXPORT void LogWrite(TServer * const srvP, const char * const c); @@ -309,7 +371,7 @@ typedef struct { 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 + /* NOT the value of the host: header field. 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. @@ -319,7 +381,7 @@ typedef struct { const char * referer; const char * requestline; const char * user; - /* Requesting user (from authorization: header). NULL if + /* Requesting user (from authorization: header field). NULL if request doesn't specify or handler has not authenticated it. */ xmlrpc_uint16_t port; @@ -329,98 +391,157 @@ typedef struct { abyss_bool keepalive; } TRequestInfo; +XMLRPC_DLLEXPORT abyss_bool SessionRefillBuffer(TSession * const sessionP); +XMLRPC_DLLEXPORT size_t SessionReadDataAvail(TSession * const sessionP); +XMLRPC_DLLEXPORT void SessionGetReadData(TSession * const sessionP, size_t const max, const char ** const outStartP, size_t * const outLenP); +XMLRPC_DLLEXPORT void SessionGetRequestInfo(TSession * const sessionP, const TRequestInfo ** const requestInfoPP); +XMLRPC_DLLEXPORT void SessionGetChannelInfo(TSession * const sessionP, void ** const channelInfoPP); +XMLRPC_DLLEXPORT void * SessionGetDefaultHandlerCtx(TSession * const sessionP); +XMLRPC_DLLEXPORT char * RequestHeaderValue(TSession * const sessionP, const char * const name); +XMLRPC_DLLEXPORT abyss_bool ResponseAddField(TSession * const sessionP, const char * const name, const char * const value); -void +XMLRPC_DLLEXPORT +abyss_bool ResponseWriteStart(TSession * const sessionP); /* For backward compatibility: */ #define ResponseWrite ResponseWriteStart +XMLRPC_DLLEXPORT abyss_bool ResponseWriteBody(TSession * const sessionP, const char * const data, xmlrpc_uint32_t const len); +XMLRPC_DLLEXPORT abyss_bool ResponseWriteEnd(TSession * const sessionP); +XMLRPC_DLLEXPORT abyss_bool ResponseChunked(TSession * const sessionP); +XMLRPC_DLLEXPORT xmlrpc_uint16_t ResponseStatusFromErrno(int const errnoArg); +XMLRPC_DLLEXPORT void ResponseStatus(TSession * const sessionP, xmlrpc_uint16_t const code); +XMLRPC_DLLEXPORT void ResponseStatusErrno(TSession * const sessionP); +XMLRPC_DLLEXPORT abyss_bool ResponseContentType(TSession * const serverP, const char * const type); +XMLRPC_DLLEXPORT abyss_bool ResponseContentLength(TSession * const sessionP, xmlrpc_uint64_t const len); +typedef struct { +/*---------------------------------------------------------------------------- + These are parameters to control the HTTP "Access Control functions. That's + where the client asks whether it is OK to send a request that some other + server asked the client to send (e.g. a person web browses a page at + a.example.com, and it sends a script that executes on the user's computer + and tries to perform an XML-RPC RPC on b.example.com. The user's browser + first asks b.example.com if it is OK to do an RPC that is really initiated + by a.example.com. +-----------------------------------------------------------------------------*/ + const char * allowOrigin; + /* This tells what original servers (a.example.com in the example + above) are allowed to submit RPCs indirectly to us. The value is a + verbatim value for an HTTP Access-Control-Allow-Origin header field + (just the value part of the field, not the whole field). "*" + therefore means everyone is allowed. "" means no one. + + NULL means not to say anything about access control to the client. + */ + abyss_bool expires; + /* The permissions herein expire after a certain period from now. + 'maxAge' is that period. + */ + unsigned int maxAge; + /* Meaningful only when 'expires' is true. The expiration period + in seconds. Zero is valid. + */ +} ResponseAccessCtl; + +XMLRPC_DLLEXPORT +void +ResponseAccessControl(TSession * const abyssSessionP, + ResponseAccessCtl const accessControl); + +XMLRPC_DLLEXPORT void ResponseError2(TSession * const sessionP, const char * const explanation); +XMLRPC_DLLEXPORT void ResponseError(TSession * const sessionP); +XMLRPC_DLLEXPORT const char * MIMETypeFromExt(const char * const ext); +XMLRPC_DLLEXPORT const char * MIMETypeFromExt2(MIMEType * const MIMETypeP, const char * const ext); +XMLRPC_DLLEXPORT const char * MIMETypeFromFileName2(MIMEType * const MIMETypeP, const char * const fileName); +XMLRPC_DLLEXPORT const char * MIMETypeFromFileName(const char * const fileName); +XMLRPC_DLLEXPORT const char * MIMETypeGuessFromFile2(MIMEType * const MIMETypeP, const char * const fileName); +XMLRPC_DLLEXPORT const char * MIMETypeGuessFromFile(const char * const filename); @@ -460,7 +581,7 @@ MIMETypeGuessFromFile(const char * const filename); ** Maximum number of simultaneous connections *********************************************************************/ -#define MAX_CONN 100000 +#define MAX_CONN 16 /********************************************************************* ** General purpose definitions @@ -482,26 +603,21 @@ MIMETypeGuessFromFile(const char * const filename); ** Range *********************************************************************/ +XMLRPC_DLLEXPORT abyss_bool RangeDecode(char * const str, xmlrpc_uint64_t const filesize, xmlrpc_uint64_t * const start, xmlrpc_uint64_t * const end); +XMLRPC_DLLEXPORT abyss_bool DateInit(void); /********************************************************************* -** Base64 -*********************************************************************/ - -void -Base64Encode(const char * const chars, - char * const base64); - -/********************************************************************* ** Session *********************************************************************/ +XMLRPC_DLLEXPORT abyss_bool SessionLog(TSession * const s); diff --git a/libs/xmlrpc-c/include/xmlrpc-c/abyss_winsock.h b/libs/xmlrpc-c/include/xmlrpc-c/abyss_winsock.h index f376446..8aeb782 100644 --- a/libs/xmlrpc-c/include/xmlrpc-c/abyss_winsock.h +++ b/libs/xmlrpc-c/include/xmlrpc-c/abyss_winsock.h @@ -7,17 +7,19 @@ struct abyss_win_chaninfo { struct sockaddr peerAddr; }; - +XMLRPC_DLLEXPORT void ChanSwitchWinCreate(unsigned short const portNumber, TChanSwitch ** const chanSwitchPP, const char ** const errorP); +XMLRPC_DLLEXPORT void ChanSwitchWinCreateWinsock(SOCKET const winsock, TChanSwitch ** const chanSwitchPP, const char ** const errorP); +XMLRPC_DLLEXPORT void ChannelWinCreateWinsock(SOCKET const fd, TChannel ** const channelPP, diff --git a/libs/xmlrpc-c/include/xmlrpc-c/base.h b/libs/xmlrpc-c/include/xmlrpc-c/base.h index a68a4f1..cdc9161 100644 --- a/libs/xmlrpc-c/include/xmlrpc-c/base.h +++ b/libs/xmlrpc-c/include/xmlrpc-c/base.h @@ -6,26 +6,40 @@ #include #include #include +#include #include #include - /* Defines XMLRPC_HAVE_WCHAR, XMLRPC_INT64 */ + /* Defines XMLRPC_HAVE_WCHAR, XMLRPC_INT64, XMLRPC_HAVE_TIMEVAL */ #if XMLRPC_HAVE_WCHAR #include #endif +#if XMLRPC_HAVE_TIMEVAL +#include +#endif + #ifdef __cplusplus extern "C" { #endif - /*========================================================================= ** Version of libxmlrpc **=======================================================================*/ + +/* These are for backward compatibility -- they can't be exported from a + Windows DLL. xmlrpc_server_version() is preferred. +*/ extern unsigned int const xmlrpc_version_major; extern unsigned int const xmlrpc_version_minor; extern unsigned int const xmlrpc_version_point; +XMLRPC_DLLEXPORT +void +xmlrpc_version(unsigned int * const majorP, + unsigned int * const minorP, + unsigned int * const pointP); + /*========================================================================= ** C types equivalent to XML-RPC types **=======================================================================*/ @@ -50,6 +64,19 @@ typedef double xmlrpc_double; so it's probably clearer just to use that. This typedef is here for mathematical completeness. */ +typedef struct { + /* A datetime of the type defined by XML-RPC with + a few extensions. I.e. in the range 1-9999 AD with microsecond + resolution. + */ + unsigned int Y; /* 1-? */ + unsigned int M; /* 1-12 */ + unsigned int D; /* 1-31 */ + unsigned int h; /* 0-23 */ + unsigned int m; /* 0-59 */ + unsigned int s; /* 0-59 */ + unsigned int u; /* 0-999999 */ +} xmlrpc_datetime; /* 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 @@ -89,12 +116,13 @@ typedef enum { #define XMLRPC_HAVE_I8 1 -/* These are *always* allocated on the heap. No exceptions. */ typedef struct _xmlrpc_value xmlrpc_value; +XMLRPC_DLLEXPORT const char * xmlrpc_type_name(xmlrpc_type const type); +XMLRPC_DLLEXPORT void xmlrpc_abort_if_array_bad(xmlrpc_value * const arrayP); @@ -102,109 +130,193 @@ xmlrpc_abort_if_array_bad(xmlrpc_value * const arrayP); xmlrpc_abort_if_array_bad(val) /* Increment the reference count of an xmlrpc_value. */ -extern void xmlrpc_INCREF (xmlrpc_value* const value); +XMLRPC_DLLEXPORT +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* const value); +XMLRPC_DLLEXPORT +extern void xmlrpc_DECREF(xmlrpc_value* const value); /* Get the type of an XML-RPC value. */ +XMLRPC_DLLEXPORT extern xmlrpc_type xmlrpc_value_type (xmlrpc_value* const value); +XMLRPC_DLLEXPORT xmlrpc_value * xmlrpc_int_new(xmlrpc_env * const envP, int const intValue); +XMLRPC_DLLEXPORT +void +xmlrpc_read_int(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + int * const intValueP); + +XMLRPC_DLLEXPORT xmlrpc_value * xmlrpc_i8_new(xmlrpc_env * const envP, xmlrpc_int64 const value); +XMLRPC_DLLEXPORT void -xmlrpc_read_int(xmlrpc_env * const envP, - const xmlrpc_value * const valueP, - int * const intValueP); +xmlrpc_read_i8(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + xmlrpc_int64 * const intValueP); +XMLRPC_DLLEXPORT xmlrpc_value * xmlrpc_bool_new(xmlrpc_env * const envP, xmlrpc_bool const boolValue); +XMLRPC_DLLEXPORT void xmlrpc_read_bool(xmlrpc_env * const envP, const xmlrpc_value * const valueP, xmlrpc_bool * const boolValueP); +XMLRPC_DLLEXPORT xmlrpc_value * xmlrpc_double_new(xmlrpc_env * const envP, double const doubleValue); +XMLRPC_DLLEXPORT void xmlrpc_read_double(xmlrpc_env * const envP, const xmlrpc_value * const valueP, xmlrpc_double * const doubleValueP); +XMLRPC_DLLEXPORT +xmlrpc_value * +xmlrpc_datetime_new(xmlrpc_env * const envP, + xmlrpc_datetime const dt); + +XMLRPC_DLLEXPORT xmlrpc_value * xmlrpc_datetime_new_str(xmlrpc_env * const envP, const char * const value); +XMLRPC_DLLEXPORT xmlrpc_value * xmlrpc_datetime_new_sec(xmlrpc_env * const envP, time_t const value); +XMLRPC_DLLEXPORT +xmlrpc_value* +xmlrpc_datetime_new_usec(xmlrpc_env * const envP, + time_t const secs, + unsigned int const usecs); + +#if XMLRPC_HAVE_TIMEVAL +XMLRPC_DLLEXPORT +xmlrpc_value * +xmlrpc_datetime_new_timeval(xmlrpc_env * const envP, + struct timeval const value); +#endif + +#if XMLRPC_HAVE_TIMESPEC +XMLRPC_DLLEXPORT +xmlrpc_value * +xmlrpc_datetime_new_timespec(xmlrpc_env * const envP, + struct timespec const value); +#endif + +void +XMLRPC_DLLEXPORT +xmlrpc_read_datetime(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + xmlrpc_datetime * const dtP); + +XMLRPC_DLLEXPORT void xmlrpc_read_datetime_str(xmlrpc_env * const envP, const xmlrpc_value * const valueP, const char ** const stringValueP); +XMLRPC_DLLEXPORT void xmlrpc_read_datetime_sec(xmlrpc_env * const envP, const xmlrpc_value * const valueP, time_t * const timeValueP); +XMLRPC_DLLEXPORT +void +xmlrpc_read_datetime_usec(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + time_t * const secsP, + unsigned int * const usecsP); + +#if XMLRPC_HAVE_TIMEVAL +XMLRPC_DLLEXPORT +void +xmlrpc_read_datetime_timeval(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + struct timeval * const timeValueP); +#endif + +#if XMLRPC_HAVE_TIMESPEC +XMLRPC_DLLEXPORT +void +xmlrpc_read_datetime_timespec(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + struct timespec * const timeValueP); +#endif + +XMLRPC_DLLEXPORT xmlrpc_value * xmlrpc_string_new(xmlrpc_env * const envP, const char * const stringValue); +XMLRPC_DLLEXPORT xmlrpc_value * xmlrpc_string_new_lp(xmlrpc_env * const envP, size_t const length, const char * const stringValue); +XMLRPC_DLLEXPORT xmlrpc_value * xmlrpc_string_new_va(xmlrpc_env * const envP, const char * const format, va_list args); +XMLRPC_DLLEXPORT xmlrpc_value * xmlrpc_string_new_f(xmlrpc_env * const envP, const char * const format, ...); +XMLRPC_DLLEXPORT xmlrpc_value * xmlrpc_string_new_lp_cr(xmlrpc_env * const envP, size_t const length, const char * const value); +XMLRPC_DLLEXPORT xmlrpc_value * xmlrpc_string_new_cr(xmlrpc_env * const envP, const char * const value); +XMLRPC_DLLEXPORT void xmlrpc_read_string(xmlrpc_env * const envP, const xmlrpc_value * const valueP, const char ** const stringValueP); +XMLRPC_DLLEXPORT void xmlrpc_read_string_crlf(xmlrpc_env * const envP, const xmlrpc_value * const valueP, const char ** const stringValueP); +XMLRPC_DLLEXPORT void xmlrpc_read_string_lp_crlf(xmlrpc_env * const envP, const xmlrpc_value * const valueP, size_t * const lengthP, const char ** const stringValueP); +XMLRPC_DLLEXPORT void xmlrpc_read_string_lp(xmlrpc_env * const envP, const xmlrpc_value * const valueP, @@ -212,80 +324,93 @@ xmlrpc_read_string_lp(xmlrpc_env * const envP, const char ** const stringValueP); #if XMLRPC_HAVE_WCHAR +XMLRPC_DLLEXPORT xmlrpc_value * xmlrpc_string_w_new(xmlrpc_env * const envP, const wchar_t * const stringValue); +XMLRPC_DLLEXPORT xmlrpc_value * xmlrpc_string_w_new_lp(xmlrpc_env * const envP, size_t const length, const wchar_t * const stringValue); +XMLRPC_DLLEXPORT void xmlrpc_read_string_w(xmlrpc_env * const envP, xmlrpc_value * const valueP, const wchar_t ** const stringValueP); +XMLRPC_DLLEXPORT void xmlrpc_read_string_w_crlf(xmlrpc_env * const envP, xmlrpc_value * const valueP, const wchar_t ** const stringValueP); +XMLRPC_DLLEXPORT void xmlrpc_read_string_w_lp(xmlrpc_env * const envP, xmlrpc_value * const valueP, size_t * const lengthP, const wchar_t ** const stringValueP); +XMLRPC_DLLEXPORT 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_DLLEXPORT xmlrpc_value * xmlrpc_string_w_new_lp_cr(xmlrpc_env * const envP, size_t const length, const wchar_t * const value); +XMLRPC_DLLEXPORT xmlrpc_value * xmlrpc_string_w_new_cr(xmlrpc_env * const envP, const wchar_t * const value); #endif /* XMLRPC_HAVE_WCHAR */ +XMLRPC_DLLEXPORT xmlrpc_value * xmlrpc_base64_new(xmlrpc_env * const envP, size_t const length, const unsigned char * const value); +XMLRPC_DLLEXPORT void xmlrpc_read_base64(xmlrpc_env * const envP, const xmlrpc_value * const valueP, size_t * const lengthP, const unsigned char ** const bytestringValueP); +XMLRPC_DLLEXPORT void xmlrpc_read_base64_size(xmlrpc_env * const envP, const xmlrpc_value * const valueP, size_t * const lengthP); +XMLRPC_DLLEXPORT xmlrpc_value * xmlrpc_array_new(xmlrpc_env * const envP); /* Return the number of elements in an XML-RPC array. ** Sets XMLRPC_TYPE_ERROR if 'array' is not an array. */ +XMLRPC_DLLEXPORT int xmlrpc_array_size(xmlrpc_env * const env, const xmlrpc_value * const array); -/* 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 * const envP, - xmlrpc_value * const arrayP, - xmlrpc_value * const valueP); +XMLRPC_DLLEXPORT +void +xmlrpc_array_append_item(xmlrpc_env * const envP, + xmlrpc_value * const arrayP, + xmlrpc_value * const valueP); +XMLRPC_DLLEXPORT void xmlrpc_array_read_item(xmlrpc_env * const envP, const xmlrpc_value * const arrayP, @@ -299,30 +424,35 @@ xmlrpc_array_read_item(xmlrpc_env * const envP, Sets XMLRPC_TYPE_ERROR if 'array' is not an array. Sets XMLRPC_INDEX_ERROR if 'index' is out of bounds. */ +XMLRPC_DLLEXPORT xmlrpc_value * xmlrpc_array_get_item(xmlrpc_env * const envP, const xmlrpc_value * const arrayP, int const index); /* Not implemented--we don't need it yet. -extern -int xmlrpc_array_set_item (xmlrpc_env* env, -xmlrpc_value* array, -int index, - xmlrpc_value* value); +XMLRPC_DLLEXPORT +int +xmlrpc_array_set_item(xmlrpc_env * const envP, + xmlrpc_value * const arrayP, + unsigned int const index, + xmlrpc_value * const valueP); */ +XMLRPC_DLLEXPORT xmlrpc_value * 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. */ +XMLRPC_DLLEXPORT int -xmlrpc_struct_size (xmlrpc_env * env, - xmlrpc_value * strct); +xmlrpc_struct_size (xmlrpc_env * const env, + xmlrpc_value * const strct); /* Returns true iff 'strct' contains 'key'. ** Sets XMLRPC_TYPE_ERROR if 'strct' is not a struct. */ +XMLRPC_DLLEXPORT int xmlrpc_struct_has_key(xmlrpc_env * const envP, xmlrpc_value * const strctP, @@ -332,6 +462,7 @@ xmlrpc_struct_has_key(xmlrpc_env * const envP, Deprecated. xmlrpc_struct_get_value_v() is more general, and this case is not common enough to warrant a shortcut. */ +XMLRPC_DLLEXPORT int xmlrpc_struct_has_key_n(xmlrpc_env * const envP, xmlrpc_value * const strctP, @@ -340,6 +471,7 @@ xmlrpc_struct_has_key_n(xmlrpc_env * const envP, #if 0 /* Not implemented yet, but needed for completeness. */ +XMLRPC_DLLEXPORT int xmlrpc_struct_has_key_v(xmlrpc_env * env, xmlrpc_value * strct, @@ -347,6 +479,7 @@ xmlrpc_struct_has_key_v(xmlrpc_env * env, #endif +XMLRPC_DLLEXPORT void xmlrpc_struct_find_value(xmlrpc_env * const envP, xmlrpc_value * const structP, @@ -354,18 +487,21 @@ xmlrpc_struct_find_value(xmlrpc_env * const envP, xmlrpc_value ** const valuePP); +XMLRPC_DLLEXPORT void xmlrpc_struct_find_value_v(xmlrpc_env * const envP, xmlrpc_value * const structP, xmlrpc_value * const keyP, xmlrpc_value ** const valuePP); +XMLRPC_DLLEXPORT void xmlrpc_struct_read_value(xmlrpc_env * const envP, xmlrpc_value * const structP, const char * const key, xmlrpc_value ** const valuePP); +XMLRPC_DLLEXPORT void xmlrpc_struct_read_value_v(xmlrpc_env * const envP, xmlrpc_value * const structP, @@ -375,6 +511,7 @@ xmlrpc_struct_read_value_v(xmlrpc_env * const envP, /* The "get_value" functions are deprecated. Use the "find_value" and "read_value" functions instead. */ +XMLRPC_DLLEXPORT xmlrpc_value * xmlrpc_struct_get_value(xmlrpc_env * const envP, xmlrpc_value * const strctP, @@ -384,6 +521,7 @@ xmlrpc_struct_get_value(xmlrpc_env * const envP, Deprecated. xmlrpc_struct_get_value_v() is more general, and this case is not common enough to warrant a shortcut. */ +XMLRPC_DLLEXPORT xmlrpc_value * xmlrpc_struct_get_value_n(xmlrpc_env * const envP, xmlrpc_value * const strctP, @@ -393,6 +531,7 @@ xmlrpc_struct_get_value_n(xmlrpc_env * const envP, /* Set the value associated with 'key' in 'strct' to 'value'. Sets XMLRPC_TYPE_ERROR if 'strct' is not a struct. */ +XMLRPC_DLLEXPORT void xmlrpc_struct_set_value(xmlrpc_env * const env, xmlrpc_value * const strct, @@ -403,6 +542,7 @@ xmlrpc_struct_set_value(xmlrpc_env * const env, The general way to set a structure value is xmlrpc_struct_set_value_v(), and this case is not common enough to deserve a shortcut. */ +XMLRPC_DLLEXPORT void xmlrpc_struct_set_value_n(xmlrpc_env * const env, xmlrpc_value * const strct, @@ -412,6 +552,7 @@ xmlrpc_struct_set_value_n(xmlrpc_env * const env, /* The same as above, but the key must be an XML-RPC string. ** Fails with XMLRPC_TYPE_ERROR if 'keyval' is not a string. */ +XMLRPC_DLLEXPORT void xmlrpc_struct_set_value_v(xmlrpc_env * const env, xmlrpc_value * const strct, @@ -423,6 +564,7 @@ xmlrpc_struct_set_value_v(xmlrpc_env * const env, ** Fails with XMLRPC_TYPE_ERROR if 'struct' is not a struct. ** Fails with XMLRPC_INDEX_ERROR if 'index' is out of bounds. */ +XMLRPC_DLLEXPORT void xmlrpc_struct_read_member(xmlrpc_env * const envP, xmlrpc_value * const structP, @@ -436,6 +578,7 @@ xmlrpc_struct_read_member(xmlrpc_env * const envP, Deprecated. Use xmlrpc_struct_read_member() instead. */ +XMLRPC_DLLEXPORT void xmlrpc_struct_get_key_and_value(xmlrpc_env * const env, xmlrpc_value * const strct, @@ -443,38 +586,55 @@ xmlrpc_struct_get_key_and_value(xmlrpc_env * const env, xmlrpc_value ** const out_keyval, xmlrpc_value ** const out_value); +/* The "C pointer" type has no relation to XML-RPC. It is here for the + convenience of programs that use xmlrpc_value for XML-RPC purposes + and can benefit from using it for non-XML-RPC purposes as well. + + Also, some people use libxmlrpc for xmlrpc_value alone, because sometimes + you need to work with basic data types in richer ways than the C types + (int, time_t, etc) allow. +*/ + +XMLRPC_DLLEXPORT +xmlrpc_value * +xmlrpc_cptr_new(xmlrpc_env * const envP, + void * const value); + +typedef void (*xmlrpc_cptr_dtor_fn)(void *, void *); + +XMLRPC_DLLEXPORT +xmlrpc_value * +xmlrpc_cptr_new_dtor(xmlrpc_env * const envP, + void * const value, + xmlrpc_cptr_dtor_fn const dtor, + void * const dtorContext); + +XMLRPC_DLLEXPORT void xmlrpc_read_cptr(xmlrpc_env * const envP, const xmlrpc_value * const valueP, void ** const ptrValueP); +XMLRPC_DLLEXPORT 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, - void * const value); - +XMLRPC_DLLEXPORT xmlrpc_value * xmlrpc_nil_new(xmlrpc_env * const envP); /* Build an xmlrpc_value from a format string. */ +XMLRPC_DLLEXPORT xmlrpc_value * xmlrpc_build_value(xmlrpc_env * const env, const char * const format, ...); /* The same as the above, but using a va_list and more general */ +XMLRPC_DLLEXPORT void xmlrpc_build_value_va(xmlrpc_env * const env, const char * const format, @@ -482,12 +642,14 @@ xmlrpc_build_value_va(xmlrpc_env * const env, xmlrpc_value ** const valPP, const char ** const tailP); +XMLRPC_DLLEXPORT void xmlrpc_decompose_value(xmlrpc_env * const envP, xmlrpc_value * const value, const char * const format, ...); +XMLRPC_DLLEXPORT void xmlrpc_decompose_value_va(xmlrpc_env * const envP, xmlrpc_value * const value, @@ -501,6 +663,7 @@ xmlrpc_decompose_value_va(xmlrpc_env * const envP, These are deprecated. Use xmlrpc_decompose_value... instead. */ +XMLRPC_DLLEXPORT void xmlrpc_parse_value(xmlrpc_env * const envP, xmlrpc_value * const value, @@ -508,6 +671,7 @@ xmlrpc_parse_value(xmlrpc_env * const envP, ...); /* The same as the above, but using a va_list. */ +XMLRPC_DLLEXPORT void xmlrpc_parse_value_va(xmlrpc_env * const envP, xmlrpc_value * const value, @@ -523,28 +687,33 @@ typedef enum xmlrpc_dialect { xmlrpc_dialect_apache } xmlrpc_dialect; +XMLRPC_DLLEXPORT void xmlrpc_serialize_value2(xmlrpc_env * const envP, xmlrpc_mem_block * const outputP, xmlrpc_value * const valueP, xmlrpc_dialect const dialect); +XMLRPC_DLLEXPORT void xmlrpc_serialize_value(xmlrpc_env * const envP, xmlrpc_mem_block * const outputP, xmlrpc_value * const valueP); +XMLRPC_DLLEXPORT void xmlrpc_serialize_params2(xmlrpc_env * const envP, xmlrpc_mem_block * const outputP, xmlrpc_value * const paramArrayP, xmlrpc_dialect const dialect); +XMLRPC_DLLEXPORT void xmlrpc_serialize_params(xmlrpc_env * const envP, xmlrpc_mem_block * const outputP, xmlrpc_value * const paramArrayP); +XMLRPC_DLLEXPORT void xmlrpc_serialize_call2(xmlrpc_env * const envP, xmlrpc_mem_block * const outputP, @@ -552,23 +721,27 @@ xmlrpc_serialize_call2(xmlrpc_env * const envP, xmlrpc_value * const paramArrayP, xmlrpc_dialect const dialect); +XMLRPC_DLLEXPORT void xmlrpc_serialize_call(xmlrpc_env * const envP, xmlrpc_mem_block * const outputP, const char * const methodName, xmlrpc_value * const paramArrayP); +XMLRPC_DLLEXPORT void xmlrpc_serialize_response2(xmlrpc_env * const envP, xmlrpc_mem_block * const outputP, xmlrpc_value * const valueP, xmlrpc_dialect const dialect); +XMLRPC_DLLEXPORT void xmlrpc_serialize_response(xmlrpc_env * const envP, xmlrpc_mem_block * const outputP, xmlrpc_value * const valueP); +XMLRPC_DLLEXPORT void xmlrpc_serialize_fault(xmlrpc_env * const envP, xmlrpc_mem_block * const outputP, @@ -579,17 +752,22 @@ xmlrpc_serialize_fault(xmlrpc_env * const envP, ** Decoding XML **=======================================================================*/ -/* Parse an XML-RPC call. If an error occurs, set a fault and set -** the output variables to NULL. -** The caller is responsible for calling free(*out_method_name) and -** xmlrpc_DECREF(*out_param_array). */ +XMLRPC_DLLEXPORT +void +xmlrpc_parse_value_xml(xmlrpc_env * const envP, + const char * const xmlData, + size_t const xmlDataLen, + xmlrpc_value ** const valuePP); + +XMLRPC_DLLEXPORT void xmlrpc_parse_call(xmlrpc_env * const envP, - const char * const xml_data, - size_t const xml_len, - const char ** const out_method_name, - xmlrpc_value ** const out_param_array); + const char * const xmlData, + size_t const xmlDataLen, + const char ** const methodNameP, + xmlrpc_value ** const paramArrayP); +XMLRPC_DLLEXPORT void xmlrpc_parse_response2(xmlrpc_env * const envP, const char * const xmlData, @@ -601,6 +779,7 @@ xmlrpc_parse_response2(xmlrpc_env * const envP, /* xmlrpc_parse_response() is for backward compatibility */ +XMLRPC_DLLEXPORT xmlrpc_value * xmlrpc_parse_response(xmlrpc_env * const envP, const char * const xmlData, @@ -616,23 +795,26 @@ xmlrpc_parse_response(xmlrpc_env * const envP, /* This routine inserts newlines every 76 characters, as required by the ** Base64 specification. */ +XMLRPC_DLLEXPORT xmlrpc_mem_block * -xmlrpc_base64_encode(xmlrpc_env * env, - unsigned char * bin_data, - size_t bin_len); +xmlrpc_base64_encode(xmlrpc_env * const envP, + const unsigned char * const binData, + size_t const binLen); /* This routine encodes everything in one line. This is needed for HTTP ** authentication and similar tasks. */ +XMLRPC_DLLEXPORT xmlrpc_mem_block * -xmlrpc_base64_encode_without_newlines(xmlrpc_env * env, - unsigned char * bin_data, - size_t bin_len); +xmlrpc_base64_encode_without_newlines(xmlrpc_env * const envP, + const unsigned char * const binData, + size_t const binLen); /* This decodes Base64 data with or without newlines. */ +XMLRPC_DLLEXPORT extern xmlrpc_mem_block * xmlrpc_base64_decode(xmlrpc_env * const envP, - const char * const ascii_data, - size_t const ascii_len); + const char * const asciiData, + size_t const asciiLen); /*========================================================================= @@ -645,10 +827,12 @@ xmlrpc_base64_decode(xmlrpc_env * const envP, ** a cookie replacement of basic authentication.) **/ +XMLRPC_DLLEXPORT extern void xmlrpc_authcookie_set(xmlrpc_env * const env, const char * const username, const char * const password); +XMLRPC_DLLEXPORT char *xmlrpc_authcookie(void); /*========================================================================= @@ -677,9 +861,11 @@ char *xmlrpc_authcookie(void); #define XMLRPC_XML_SIZE_LIMIT_DEFAULT (512*1024) /* Set a specific limit to the specified value. */ +XMLRPC_DLLEXPORT extern void xmlrpc_limit_set (int const limit_id, size_t const value); /* Get the value of a specified limit. */ +XMLRPC_DLLEXPORT extern size_t xmlrpc_limit_get (int const limit_id); diff --git a/libs/xmlrpc-c/include/xmlrpc-c/base.hpp b/libs/xmlrpc-c/include/xmlrpc-c/base.hpp index ab6fe3e..6f93e38 100644 --- a/libs/xmlrpc-c/include/xmlrpc-c/base.hpp +++ b/libs/xmlrpc-c/include/xmlrpc-c/base.hpp @@ -1,19 +1,24 @@ #ifndef XMLRPC_BASE_HPP_INCLUDED #define XMLRPC_BASE_HPP_INCLUDED +#include + #include #include #include #include #include #include +#if XMLRPC_HAVE_TIMEVAL +#include +#endif +#include #include namespace xmlrpc_c { - -class value { +class XMLRPC_DLLEXPORT value { // This is a handle. You don't want to create a pointer to this; // it is in fact a pointer itself. public: @@ -26,6 +31,8 @@ public: ~value(); enum type_t { + // These are designed to be identical to the values for + // enum xmlrpc_type in the C library. TYPE_INT = 0, TYPE_BOOLEAN = 1, TYPE_DOUBLE = 2, @@ -62,6 +69,8 @@ public: xmlrpc_value * cValue() const; + // Not to be confused with public 'cvalue' method that all the derived + // classes have. value(xmlrpc_value * const valueP); @@ -72,33 +81,42 @@ public: xmlrpc_value * cValueP; // NULL means this is merely a placeholder object. + +protected: + void + validateInstantiated() const; }; +std::ostream& operator<<(std::ostream& out, + xmlrpc_c::value::type_t const& type); + -class value_int : public value { +class XMLRPC_DLLEXPORT value_int : public value { public: value_int(int const cvalue); value_int(xmlrpc_c::value const baseValue); operator int() const; -}; + int cvalue() const; +}; -class value_boolean : public value { +class XMLRPC_DLLEXPORT value_boolean : public value { public: value_boolean(bool const cvalue); value_boolean(xmlrpc_c::value const baseValue); operator bool() const; -}; + bool cvalue() const; +}; -class value_string : public value { +class XMLRPC_DLLEXPORT value_string : public value { public: enum nlCode {nlCode_all, nlCode_lf}; @@ -113,103 +131,274 @@ public: crlfValue() const; operator std::string() const; -}; + std::string cvalue() const; +}; -class value_double : public value { +class XMLRPC_DLLEXPORT value_double : public value { public: value_double(double const cvalue); value_double(xmlrpc_c::value const baseValue); operator double() const; -}; + double cvalue() const; +}; -class value_datetime : public value { +class XMLRPC_DLLEXPORT value_datetime : public value { public: value_datetime(std::string const cvalue); value_datetime(time_t const cvalue); #if XMLRPC_HAVE_TIMEVAL value_datetime(struct timeval const& cvalue); + operator timeval() const; #endif #if XMLRPC_HAVE_TIMESPEC value_datetime(struct timespec const& cvalue); + operator timespec() const; #endif value_datetime(xmlrpc_c::value const baseValue); operator time_t() const; + + time_t cvalue() const; }; +typedef std::vector cbytestring; -class value_bytestring : public value { +class XMLRPC_DLLEXPORT value_bytestring : public value { public: - value_bytestring(std::vector const& cvalue); + value_bytestring(cbytestring const& cvalue); value_bytestring(xmlrpc_c::value const baseValue); // You can't cast to a vector because the compiler can't tell which // constructor to use (complains about ambiguity). So we have this: - std::vector + cbytestring vectorUcharValue() const; + cbytestring cvalue() const; + size_t length() const; }; -class value_struct : public value { +typedef std::map cstruct; + +class XMLRPC_DLLEXPORT value_struct : public value { public: - value_struct(std::map const& cvalue); + value_struct(cstruct const& cvalue); value_struct(xmlrpc_c::value const baseValue); - operator std::map() const; + operator cstruct() const; + + cstruct cvalue() const; }; -class value_array : public value { +typedef std::vector carray; + +class XMLRPC_DLLEXPORT value_array : public value { public: - value_array(std::vector const& cvalue); + value_array(carray const& cvalue); value_array(xmlrpc_c::value const baseValue); - std::vector + // You can't cast to a vector because the compiler can't tell which + // constructor to use (complains about ambiguity). So we have this: + carray vectorValueValue() const; + carray cvalue() const; + size_t size() const; }; -class value_nil : public value { +template xmlrpc_c::value_array +arrayValueSlice(InputIterator begin, + InputIterator end) { +/*---------------------------------------------------------------------------- + convert C++ iterator pair to XML-RPC array +-----------------------------------------------------------------------------*/ + carray ret; + for (InputIterator p = begin; p != end; ++p) { + ret.push_back(toValue(*p)); + } + return xmlrpc_c::value_array(ret); +} + +template inline xmlrpc_c::value_array +arrayValueArray(const MemberClass * const in, + size_t const size) { +/*---------------------------------------------------------------------------- + convert C++ array to XML-RPC array +-----------------------------------------------------------------------------*/ + return arrayValueSlice(in, in + size); +} + +class XMLRPC_DLLEXPORT value_nil : public value { public: value_nil(); value_nil(xmlrpc_c::value const baseValue); -}; + void * cvalue() const; +}; -class value_i8 : public value { +class XMLRPC_DLLEXPORT value_i8 : public value { public: value_i8(xmlrpc_int64 const cvalue); value_i8(xmlrpc_c::value const baseValue); operator xmlrpc_int64() const; + + xmlrpc_int64 cvalue() const; }; +inline xmlrpc_c::value_string +toValue(const char * const x) { + return xmlrpc_c::value_string(x); +} + +inline xmlrpc_c::value_string +toValue(std::string const& x) { + return xmlrpc_c::value_string(x); +} + +inline xmlrpc_c::value_int +toValue(int const x) { + return xmlrpc_c::value_int(x); +} + +inline xmlrpc_c::value_boolean +toValue(bool const x) { + return xmlrpc_c::value_boolean(x); +} + +inline xmlrpc_c::value_double +toValue(double const x) { + return xmlrpc_c::value_double(x); +} + +inline xmlrpc_c::value_bytestring + toValue(cbytestring const& x) { + return xmlrpc_c::value_bytestring(x); +} + +inline const xmlrpc_c::value & +toValue(xmlrpc_c::value const& v) { +/*---------------------------------------------------------------------------- + This does a null conversion; you use it to catch all the XML-RPC types that + have no usable C++ equivalent, so you can do a toValue() of any XML-RPC + type at all. In particular: 'value_datetime', 'value_nil'. +-----------------------------------------------------------------------------*/ + return v; +} -class fault { +template xmlrpc_c::value_struct +toValue(std::map const& in) { +/*---------------------------------------------------------------------------- + convert C++ map to XML-RPC structure +-----------------------------------------------------------------------------*/ + cstruct ret; + for (typename std::map::const_iterator p = in.begin(); + p != in.end(); + ++p) { + ret[p->first] = toValue(p->second); + } + return xmlrpc_c::value_struct(ret); +} + +template inline xmlrpc_c::value_array +toValue(std::vector const& in) { +/*---------------------------------------------------------------------------- + convert C++ vector to XML-RPC array +-----------------------------------------------------------------------------*/ + return arrayValueSlice(in.begin(), in.end()); +} + +// fromValue() returns via reference argument instead of by return value +// so the compiler can tell which version of it to invoke based on the +// desired output type. + +inline void +fromValue(std::string & y, xmlrpc_c::value const& x) { + y = xmlrpc_c::value_string(x); +} + +inline void +fromValue(int & y, xmlrpc_c::value const& x) { + y = xmlrpc_c::value_int(x); +} + +inline void +fromValue(bool & y, xmlrpc_c::value const& x) { + y = xmlrpc_c::value_boolean(x); +} + +inline void +fromValue(double & y, xmlrpc_c::value const& x) { + y = xmlrpc_c::value_double(x); +} + +inline void +fromValue(cbytestring & y, xmlrpc_c::value const& x) { + y = xmlrpc_c::value_bytestring(x).vectorUcharValue(); +} + +inline void +fromValue(xmlrpc_c::value & y, xmlrpc_c::value const& x) { +/*---------------------------------------------------------------------------- + This does a null conversion; it's so you can use fromValue() with + an XML-RPC value or C++ value without having to know which it is. + One reason you would have an XML-RPC value lying around with C++ values + is that some XML-RPC values don't have a common C++ equivalent. +-----------------------------------------------------------------------------*/ + y = x; +} + +template inline void +fromValue(std::map & y, xmlrpc_c::value const& x) { +/*---------------------------------------------------------------------------- + Convert XML-RPC structure to C++ map. +-----------------------------------------------------------------------------*/ + cstruct m = xmlrpc_c::value_struct(x); + y.clear(); + for (std::map::const_iterator p = m.begin(); + p != m.end(); + ++p) { + fromValue(y[p->first], p->second); + } +} + +template inline void +fromValue(std::vector & y, xmlrpc_c::value const& x) { +/*---------------------------------------------------------------------------- + Convert XML-RPC array to C++ vector. +-----------------------------------------------------------------------------*/ + carray v = xmlrpc_c::value_array(x).vectorValueValue(); + y.resize(v.size()); + for (unsigned int i = 0; i < v.size(); ++i) { + fromValue(y[i], v[i]); + } +} + +class XMLRPC_DLLEXPORT fault { /*---------------------------------------------------------------------------- This is an XML-RPC fault. @@ -253,7 +442,7 @@ private: std::string description; }; -class rpcOutcome { +class XMLRPC_DLLEXPORT rpcOutcome { /*---------------------------------------------------------------------------- The outcome of a validly executed RPC -- either an XML-RPC fault or an XML-RPC value of the result. @@ -275,7 +464,7 @@ private: xmlrpc_c::fault fault; // valid if not 'succeeded' }; -class paramList { +class XMLRPC_DLLEXPORT paramList { /*---------------------------------------------------------------------------- A parameter list of an XML-RPC call. -----------------------------------------------------------------------------*/ @@ -288,6 +477,11 @@ public: paramList& addx(xmlrpc_c::value const param); + template paramList& addc(const T & x) { + xmlrpc_c::paramList::add(toValue(x)); + return *this; + } + unsigned int size() const; @@ -316,15 +510,15 @@ public: std::string getString(unsigned int const paramNumber) const; - std::vector + cbytestring getBytestring(unsigned int const paramNumber) const; - std::vector + carray getArray(unsigned int const paramNumber, unsigned int const minSize = 0, unsigned int const maxSize = UINT_MAX) const; - std::map + cstruct getStruct(unsigned int const paramNumber) const; void diff --git a/libs/xmlrpc-c/include/xmlrpc-c/base64.hpp b/libs/xmlrpc-c/include/xmlrpc-c/base64.hpp index a884225..4ef06aa 100644 --- a/libs/xmlrpc-c/include/xmlrpc-c/base64.hpp +++ b/libs/xmlrpc-c/include/xmlrpc-c/base64.hpp @@ -4,18 +4,21 @@ #include #include +#include + namespace xmlrpc_c { enum newlineCtl {NEWLINE_NO, NEWLINE_YES}; +XMLRPC_DLLEXPORT std::string base64FromBytes( std::vector const& bytes, xmlrpc_c::newlineCtl const newlineCtl = xmlrpc_c::NEWLINE_YES); - +XMLRPC_DLLEXPORT std::vector bytesFromBase64(std::string const& base64); diff --git a/libs/xmlrpc-c/include/xmlrpc-c/base64_int.h b/libs/xmlrpc-c/include/xmlrpc-c/base64_int.h new file mode 100644 index 0000000..1d1414d --- /dev/null +++ b/libs/xmlrpc-c/include/xmlrpc-c/base64_int.h @@ -0,0 +1,11 @@ +#ifndef BASE64_INT_H_INCLUDED +#define BASE64_INT_H_INCLUDED + +#include "xmlrpc-c/c_util.h" + +XMLRPC_DLLEXPORT +void +xmlrpc_base64Encode(const char * const chars, + char * const base64); + +#endif diff --git a/libs/xmlrpc-c/include/xmlrpc-c/base_int.h b/libs/xmlrpc-c/include/xmlrpc-c/base_int.h index be45cfd..cff8773 100644 --- a/libs/xmlrpc-c/include/xmlrpc-c/base_int.h +++ b/libs/xmlrpc-c/include/xmlrpc-c/base_int.h @@ -18,14 +18,14 @@ #include "bool.h" #include "int.h" -#include +#include #include +#include #ifdef __cplusplus extern "C" { #endif - struct _xmlrpc_value { xmlrpc_type _type; int _refcount; @@ -36,8 +36,13 @@ struct _xmlrpc_value { xmlrpc_int64 i8; xmlrpc_bool b; double d; - /* time_t t */ - void * c_ptr; + xmlrpc_datetime dt; + /* NOTE: may be invalid! e.g. February 30 */ + struct { + void * objectP; + xmlrpc_cptr_dtor_fn dtor; // NULL if none + void * dtorContext; + } cptr; } _value; /* Other data types use a memory block. @@ -77,6 +82,15 @@ struct _xmlrpc_value { This member is always NULL on a system that does not have Unicode wchar functions. */ + void * _cache; + /* This is a hack to support the old style memory management in which + one gets a pointer into memory that belongs to the xmlrpc_value + object; i.e. the caller of xmlrpc_read_datetime_str_old() doesn't + get memory that he is responsible for freeing. + + This is essentially a cached value of the result of a + xmlrpc_read_datetime_str_old(). NULL means nothing cached. + */ }; #define XMLRPC_ASSERT_VALUE_OK(val) \ @@ -97,24 +111,34 @@ typedef struct { } _struct_member; +XMLRPC_DLLEXPORT void xmlrpc_createXmlrpcValue(xmlrpc_env * const envP, xmlrpc_value ** const valPP); +XMLRPC_DLLEXPORT const char * xmlrpc_typeName(xmlrpc_type const type); +XMLRPC_DLLEXPORT void xmlrpc_traceXml(const char * const label, const char * const xml, - unsigned int const xmlLength); + size_t const xmlLength); +XMLRPC_DLLEXPORT void xmlrpc_destroyString(xmlrpc_value * const stringP); +XMLRPC_DLLEXPORT +void +xmlrpc_destroyDatetime(xmlrpc_value * const datetimeP); + +XMLRPC_DLLEXPORT void xmlrpc_destroyStruct(xmlrpc_value * const structP); +XMLRPC_DLLEXPORT void xmlrpc_destroyArrayContents(xmlrpc_value * const arrayP); @@ -130,16 +154,19 @@ xmlrpc_destroyArrayContents(xmlrpc_value * const arrayP); new memory for them. -----------------------------------------------------------------------------*/ +XMLRPC_DLLEXPORT void xmlrpc_read_datetime_str_old(xmlrpc_env * const envP, const xmlrpc_value * const valueP, const char ** const stringValueP); +XMLRPC_DLLEXPORT void xmlrpc_read_string_old(xmlrpc_env * const envP, const xmlrpc_value * const valueP, const char ** const stringValueP); +XMLRPC_DLLEXPORT void xmlrpc_read_string_lp_old(xmlrpc_env * const envP, const xmlrpc_value * const valueP, @@ -147,11 +174,13 @@ xmlrpc_read_string_lp_old(xmlrpc_env * const envP, const char ** const stringValueP); #if XMLRPC_HAVE_WCHAR +XMLRPC_DLLEXPORT void xmlrpc_read_string_w_old(xmlrpc_env * const envP, xmlrpc_value * const valueP, const wchar_t ** const stringValueP); +XMLRPC_DLLEXPORT void xmlrpc_read_string_w_lp_old(xmlrpc_env * const envP, xmlrpc_value * const valueP, @@ -159,6 +188,7 @@ xmlrpc_read_string_w_lp_old(xmlrpc_env * const envP, const wchar_t ** const stringValueP); #endif +XMLRPC_DLLEXPORT void xmlrpc_read_base64_old(xmlrpc_env * const envP, const xmlrpc_value * const valueP, diff --git a/libs/xmlrpc-c/include/xmlrpc-c/c_util.h b/libs/xmlrpc-c/include/xmlrpc-c/c_util.h index 8cc72e9..b8635e6 100644 --- a/libs/xmlrpc-c/include/xmlrpc-c/c_util.h +++ b/libs/xmlrpc-c/include/xmlrpc-c/c_util.h @@ -1,14 +1,31 @@ #ifndef XMLRPC_C_C_UTIL_H_INCLUDED #define XMLRPC_C_C_UTIL_H_INCLUDED -/* GNU_PRINTF_ATTR lets the GNU compiler check printf-type +/* C language stuff. Doesn't involve any libraries that aren't part of + the compiler. +*/ + +#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) + +/* XMLRPC_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))) +#define XMLRPC_PRINTF_ATTR(a,b) __attribute__ ((format (printf, a, b))) +#define XMLRPC_NORETURN_ATTR __attribute__((noreturn)) +#else +#define XMLRPC_PRINTF_ATTR(a,b) +#define XMLRPC_NORETURN_ATTR +#endif + +/* XMLRPC_DLLEXPORT is an attribute of an external symbols that says it + is to be exported from a library that contains it. +*/ +#if defined(_DLL) && defined(_MSC_VER) && _MSC_VER >= 1500 +#define XMLRPC_DLLEXPORT __declspec(dllexport) #else -#define GNU_PRINTF_ATTR(a,b) +#define XMLRPC_DLLEXPORT #endif #endif diff --git a/libs/xmlrpc-c/include/xmlrpc-c/client.h b/libs/xmlrpc-c/include/xmlrpc-c/client.h index c2e2e61..f4166e3 100644 --- a/libs/xmlrpc-c/include/xmlrpc-c/client.h +++ b/libs/xmlrpc-c/include/xmlrpc-c/client.h @@ -10,6 +10,8 @@ #ifndef XMLRPC_CLIENT_H_INCLUDED #define XMLRPC_CLIENT_H_INCLUDED +#include +#include #include #ifdef __cplusplus @@ -39,8 +41,11 @@ typedef struct xmlrpc_client_transport_ops xmlrpc_client_transport_ops; so now we just use void * as a base class pointer. */ +XMLRPC_DLLEXPORT extern struct xmlrpc_client_transport_ops xmlrpc_libwww_transport_ops; +XMLRPC_DLLEXPORT extern struct xmlrpc_client_transport_ops xmlrpc_wininet_transport_ops; +XMLRPC_DLLEXPORT extern struct xmlrpc_client_transport_ops xmlrpc_curl_transport_ops; enum xmlrpc_sslversion { @@ -50,6 +55,29 @@ enum xmlrpc_sslversion { XMLRPC_SSLVERSION_SSLv3 }; + +enum xmlrpc_httpauthtype { + /* These are just constants. They can be or'ed as integers to create + a set. + */ + XMLRPC_HTTPAUTH_BASIC = (1<<0), + XMLRPC_HTTPAUTH_DIGEST = (1<<1), + XMLRPC_HTTPAUTH_GSSNEGOTIATE = (1<<2), + XMLRPC_HTTPAUTH_NTLM = (1<<3), +}; + +/* The following are useful combinations of the HTTP authentication types + above. +*/ +#define XMLRPC_HTTPAUTH_NONE 0 +#define XMLRPC_HTTPAUTH_ANY ~0 +#define XMLRPC_HTTPAUTH_ANYSAFE (~XMLRPC_HTTPAUTH_BASIC) + +enum xmlrpc_httpproxytype { + XMLRPC_HTTPPROXY_HTTP = 0, + XMLRPC_HTTPPROXY_SOCKS5 = 5 +}; + struct xmlrpc_curl_xportparms { /* This is designed so that zero values are always the defaults. */ const char * network_interface; @@ -71,6 +99,15 @@ struct xmlrpc_curl_xportparms { const char * egdsocket; const char * ssl_cipher_list; unsigned int timeout; + xmlrpc_bool dont_advertise; + const char * proxy; + unsigned int proxy_port; + enum xmlrpc_httpproxytype proxy_type; + unsigned int proxy_auth; + /* A set of authentication schemes -- an OR of + enum xmlrpc_httpproxyauth values + */ + const char * proxy_userpwd; }; @@ -88,6 +125,19 @@ struct xmlrpc_wininet_xportparms { /* XMLRPC_WXPSIZE(xyz) is analogous to XMLRPC_CPSIZE, below */ +struct xmlrpc_transfer_progress { + double total; + double now; +}; + +struct xmlrpc_progress_data { + struct xmlrpc_transfer_progress call; + struct xmlrpc_transfer_progress response; +}; + +typedef void xmlrpc_progress_fn(void * const, + struct xmlrpc_progress_data const); + struct xmlrpc_clientparms { /* (transport, transportparmsP, transportparm_size) and (transportOpsP, transportP) are mutually exclusive. @@ -100,6 +150,7 @@ struct xmlrpc_clientparms { const struct xmlrpc_client_transport_ops * transportOpsP; xmlrpc_client_transport * transportP; xmlrpc_dialect dialect; + xmlrpc_progress_fn * progressFn; }; #define XMLRPC_CPSIZE(mbrname) \ @@ -112,23 +163,24 @@ struct xmlrpc_clientparms { not the caller is new enough to have supplied a certain parameter. */ +XMLRPC_DLLEXPORT const char * xmlrpc_client_get_default_transport(xmlrpc_env * const env); /* 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 +** arguments except 'userHandle' will be deallocated internally; please do ** not free any of them yourself. -** WARNING: param_array may (or may not) be NULL if fault->fault_occurred +** WARNING: 'paramArray' may (or may not) be NULL if fault->fault_occurred ** is true, and you set up the call using xmlrpc_client_call_asynch. ** WARNING: If asynchronous calls are still pending when the library is ** shut down, your handler may (or may not) be called with a fault. */ -typedef void (*xmlrpc_response_handler) (const char *server_url, - const char *method_name, - xmlrpc_value *param_array, - void *user_data, - xmlrpc_env *fault, - xmlrpc_value *result); +typedef void xmlrpc_response_handler(const char * serverUrl, + const char * methodName, + xmlrpc_value * paramArray, + void * userHandle, + xmlrpc_env * fault, + xmlrpc_value * result); /*========================================================================= @@ -147,73 +199,98 @@ typedef void (*xmlrpc_response_handler) (const char *server_url, typedef struct _xmlrpc_server_info xmlrpc_server_info; /* Create a new server info record, pointing to the specified server. */ +XMLRPC_DLLEXPORT xmlrpc_server_info * 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. */ +XMLRPC_DLLEXPORT extern xmlrpc_server_info * xmlrpc_server_info_copy(xmlrpc_env * const envP, xmlrpc_server_info * const srcP); +XMLRPC_DLLEXPORT void xmlrpc_server_info_free(xmlrpc_server_info * const serverP); +XMLRPC_DLLEXPORT void xmlrpc_server_info_set_user(xmlrpc_env * const envP, xmlrpc_server_info * const serverInfoP, const char * const username, const char * const password); +XMLRPC_DLLEXPORT void xmlrpc_server_info_set_basic_auth(xmlrpc_env * const envP, xmlrpc_server_info * const serverP, const char * const username, const char * const password); +XMLRPC_DLLEXPORT void xmlrpc_server_info_allow_auth_basic(xmlrpc_env * const envP, xmlrpc_server_info * const sP); +XMLRPC_DLLEXPORT void xmlrpc_server_info_disallow_auth_basic(xmlrpc_env * const envP, xmlrpc_server_info * const sP); +XMLRPC_DLLEXPORT void xmlrpc_server_info_allow_auth_digest(xmlrpc_env * const envP, xmlrpc_server_info * const sP); +XMLRPC_DLLEXPORT void xmlrpc_server_info_disallow_auth_digest(xmlrpc_env * const envP, xmlrpc_server_info * const sP); +XMLRPC_DLLEXPORT void xmlrpc_server_info_allow_auth_negotiate(xmlrpc_env * const envP, xmlrpc_server_info * const sP); +XMLRPC_DLLEXPORT void xmlrpc_server_info_disallow_auth_negotiate(xmlrpc_env * const envP, xmlrpc_server_info * const sP); +XMLRPC_DLLEXPORT void xmlrpc_server_info_allow_auth_ntlm(xmlrpc_env * const envP, xmlrpc_server_info * const sP); +XMLRPC_DLLEXPORT void xmlrpc_server_info_disallow_auth_ntlm(xmlrpc_env * const envP, xmlrpc_server_info * const sP); +/* These are for backward compatibility -- they can't be exported from a + Windows DLL. xmlrpc_server_version() is preferred. +*/ extern unsigned int const xmlrpc_client_version_major; extern unsigned int const xmlrpc_client_version_minor; extern unsigned int const xmlrpc_client_version_point; +XMLRPC_DLLEXPORT +void +xmlrpc_client_version(unsigned int * const majorP, + unsigned int * const minorP, + unsigned int * const pointP); + +XMLRPC_DLLEXPORT void xmlrpc_client_setup_global_const(xmlrpc_env * const envP); +XMLRPC_DLLEXPORT void xmlrpc_client_teardown_global_const(void); +XMLRPC_DLLEXPORT void xmlrpc_client_create(xmlrpc_env * const envP, int const flags, @@ -223,9 +300,11 @@ xmlrpc_client_create(xmlrpc_env * const envP, unsigned int const parmSize, xmlrpc_client ** const clientPP); +XMLRPC_DLLEXPORT void xmlrpc_client_destroy(xmlrpc_client * const clientP); +XMLRPC_DLLEXPORT void xmlrpc_client_transport_call2( xmlrpc_env * const envP, @@ -234,6 +313,7 @@ xmlrpc_client_transport_call2( xmlrpc_mem_block * const callXmlP, xmlrpc_mem_block ** const respXmlPP); +XMLRPC_DLLEXPORT void xmlrpc_client_call2(xmlrpc_env * const envP, struct xmlrpc_client * const clientP, @@ -242,6 +322,7 @@ xmlrpc_client_call2(xmlrpc_env * const envP, xmlrpc_value * const paramArrayP, xmlrpc_value ** const resultPP); +XMLRPC_DLLEXPORT void xmlrpc_client_call2f(xmlrpc_env * const envP, xmlrpc_client * const clientP, @@ -251,32 +332,58 @@ xmlrpc_client_call2f(xmlrpc_env * const envP, const char * const format, ...); +XMLRPC_DLLEXPORT +void +xmlrpc_client_call2f_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_DLLEXPORT void xmlrpc_client_event_loop_finish(xmlrpc_client * const clientP); +XMLRPC_DLLEXPORT void xmlrpc_client_event_loop_finish_timeout(xmlrpc_client * const clientP, unsigned long const milliseconds); +XMLRPC_DLLEXPORT 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); - +xmlrpc_client_start_rpc(xmlrpc_env * const envP, + struct xmlrpc_client * const clientP, + const xmlrpc_server_info * const serverInfoP, + const char * const methodName, + xmlrpc_value * const paramArrayP, + xmlrpc_response_handler responseHandler, + void * const userData); + +XMLRPC_DLLEXPORT 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, + xmlrpc_response_handler responseHandler, void * const userData, const char * const format, ...); +XMLRPC_DLLEXPORT +void +xmlrpc_client_start_rpcf_va(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, + va_list args); + +XMLRPC_DLLEXPORT void xmlrpc_client_set_interrupt(xmlrpc_client * const clientP, int * const interruptP); diff --git a/libs/xmlrpc-c/include/xmlrpc-c/client.hpp b/libs/xmlrpc-c/include/xmlrpc-c/client.hpp index de6d073..f757b6a 100644 --- a/libs/xmlrpc-c/include/xmlrpc-c/client.hpp +++ b/libs/xmlrpc-c/include/xmlrpc-c/client.hpp @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -13,9 +14,9 @@ namespace xmlrpc_c { -class clientTransactionPtr; +class XMLRPC_DLLEXPORT clientTransactionPtr; -class clientTransaction : public girmem::autoObject { +class XMLRPC_DLLEXPORT clientTransaction : public girmem::autoObject { friend class clientTransactionPtr; @@ -26,11 +27,14 @@ public: virtual void finishErr(girerr::error const& error) = 0; + virtual void + progress(struct xmlrpc_progress_data const& progressData) const = 0; + protected: clientTransaction(); }; -class clientTransactionPtr : public girmem::autoObjectPtr { +class XMLRPC_DLLEXPORT clientTransactionPtr : public girmem::autoObjectPtr { public: clientTransactionPtr(); @@ -43,9 +47,9 @@ public: operator->() const; }; -class clientPtr; +class XMLRPC_DLLEXPORT clientPtr; -class client : public girmem::autoObject { +class XMLRPC_DLLEXPORT 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. @@ -77,7 +81,7 @@ public: setInterrupt(int *); }; -class clientPtr : public girmem::autoObjectPtr { +class XMLRPC_DLLEXPORT clientPtr : public girmem::autoObjectPtr { public: clientPtr(); @@ -90,7 +94,7 @@ public: get() const; }; -class serverAccessor : public girmem::autoObject { +class XMLRPC_DLLEXPORT serverAccessor : public girmem::autoObject { public: serverAccessor(xmlrpc_c::clientPtr const clientP, @@ -106,7 +110,7 @@ private: xmlrpc_c::carriageParmPtr const carriageParmP; }; -class serverAccessorPtr : public girmem::autoObjectPtr { +class XMLRPC_DLLEXPORT serverAccessorPtr : public girmem::autoObjectPtr { public: serverAccessorPtr(); @@ -120,7 +124,7 @@ public: get() const; }; -class connection { +class XMLRPC_DLLEXPORT connection { /*---------------------------------------------------------------------------- A nexus of a particular client and a particular server, along with carriage parameters for performing RPCs between the two. @@ -140,7 +144,7 @@ public: xmlrpc_c::carriageParm * carriageParmP; }; -class client_xml : public xmlrpc_c::client { +class XMLRPC_DLLEXPORT client_xml : public xmlrpc_c::client { /*---------------------------------------------------------------------------- A client that uses XML-RPC XML in the RPC. This class does not define how the XML gets transported, though (i.e. does not require HTTP). @@ -180,7 +184,7 @@ private: struct client_xml_impl * implP; }; -class xmlTransaction_client : public xmlrpc_c::xmlTransaction { +class XMLRPC_DLLEXPORT xmlTransaction_client : public xmlrpc_c::xmlTransaction { public: xmlTransaction_client(xmlrpc_c::clientTransactionPtr const& tranP); @@ -190,11 +194,15 @@ public: void finishErr(girerr::error const& error) const; + + void + progress(xmlrpc_progress_data const& progressData) const; + private: xmlrpc_c::clientTransactionPtr const tranP; }; -class xmlTransaction_clientPtr : public xmlTransactionPtr { +class XMLRPC_DLLEXPORT xmlTransaction_clientPtr : public xmlTransactionPtr { public: xmlTransaction_clientPtr(); @@ -206,21 +214,23 @@ public: class rpcPtr; -class rpc : public clientTransaction { +class XMLRPC_DLLEXPORT rpc : public clientTransaction { /*---------------------------------------------------------------------------- An RPC. An RPC consists of method name, parameters, and result. It does not specify in any way how the method name and parameters get turned into a result. It does not presume XML or HTTP. - - You don't create an object of this class directly. All references to - an rpc object should be by an rpcPtr object. Create a new RPC by - creating a new rpcPtr. Accordingly, our constructors and destructors - are protected, but available to our friend class rpcPtr. - + + You don't normally create or reference an object of this class directly, + but rather via an 'rpcPtr' object. That takes care of deleting the object + when you are done with it (but not before). This is critical if you plan + to use the 'start' method, because without an rpcPtr reference, the system + will destroy the object under the covers when the RPC finishes, and there + is no way for you to guarantee you won't still access it after it finishes + (because of accesses within Xmlrpc-c calls such as the call that finishes + the RPC or just rpc::start). + In order to do asynchronous RPCs, you normally have to create a derived - class that defines a useful notifyComplete(). If you do that, you'll - want to make sure the derived class objects get accessed only via rpcPtrs - as well. + class that defines a useful notifyComplete(). -----------------------------------------------------------------------------*/ friend class xmlrpc_c::rpcPtr; @@ -248,6 +258,9 @@ public: virtual void notifyComplete(); + virtual void + progress(struct xmlrpc_progress_data const& progressData) const; + bool isFinished() const; @@ -269,7 +282,7 @@ private: struct rpc_impl * implP; }; -class rpcPtr : public clientTransactionPtr { +class XMLRPC_DLLEXPORT rpcPtr : public clientTransactionPtr { public: rpcPtr(); diff --git a/libs/xmlrpc-c/include/xmlrpc-c/client_global.h b/libs/xmlrpc-c/include/xmlrpc-c/client_global.h index 4f388fc..7d7a11b 100644 --- a/libs/xmlrpc-c/include/xmlrpc-c/client_global.h +++ b/libs/xmlrpc-c/include/xmlrpc-c/client_global.h @@ -1,6 +1,9 @@ #ifndef CLIENT_GLOBAL_H_INCLUDED #define CLIENT_GLOBAL_H_INCLUDED +#include +#include + /*========================================================================= ** Initialization and Shutdown **========================================================================= @@ -12,11 +15,13 @@ #define XMLRPC_CLIENT_NO_FLAGS (0) #define XMLRPC_CLIENT_SKIP_LIBWWW_INIT (1) +XMLRPC_DLLEXPORT extern void xmlrpc_client_init(int const flags, const char * const appname, const char * const appversion); +XMLRPC_DLLEXPORT void xmlrpc_client_init2(xmlrpc_env * const env, int const flags, @@ -25,6 +30,7 @@ xmlrpc_client_init2(xmlrpc_env * const env, const struct xmlrpc_clientparms * const clientparms, unsigned int const parm_size); +XMLRPC_DLLEXPORT extern void xmlrpc_client_cleanup(void); @@ -35,6 +41,7 @@ xmlrpc_client_cleanup(void); ** functions from inside an asynchronous callback! */ +XMLRPC_DLLEXPORT xmlrpc_value * xmlrpc_client_call(xmlrpc_env * const envP, const char * const server_url, @@ -42,12 +49,14 @@ xmlrpc_client_call(xmlrpc_env * const envP, const char * const format, ...); +XMLRPC_DLLEXPORT xmlrpc_value * xmlrpc_client_call_params(xmlrpc_env * const envP, const char * const serverUrl, const char * const methodName, xmlrpc_value * const paramArrayP); +XMLRPC_DLLEXPORT xmlrpc_value * xmlrpc_client_call_server(xmlrpc_env * const envP, const xmlrpc_server_info * const server, @@ -55,6 +64,7 @@ xmlrpc_client_call_server(xmlrpc_env * const envP, const char * const format, ...); +XMLRPC_DLLEXPORT xmlrpc_value * xmlrpc_client_call_server_params( xmlrpc_env * const envP, @@ -62,6 +72,7 @@ xmlrpc_client_call_server_params( const char * const method_name, xmlrpc_value * const paramArrayP); +XMLRPC_DLLEXPORT void xmlrpc_client_transport_call( xmlrpc_env * const envP, @@ -83,6 +94,7 @@ xmlrpc_client_transport_call( ** 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. */ +XMLRPC_DLLEXPORT void xmlrpc_client_call_asynch(const char * const server_url, const char * const method_name, @@ -93,6 +105,7 @@ xmlrpc_client_call_asynch(const char * const server_url, /* As above, but use an xmlrpc_server_info object. The server object can be ** safely destroyed as soon as this function returns. */ +XMLRPC_DLLEXPORT void xmlrpc_client_call_server_asynch(xmlrpc_server_info * const server, const char * const method_name, @@ -104,6 +117,7 @@ xmlrpc_client_call_server_asynch(xmlrpc_server_info * const server, /* As above, but the parameter list is supplied as an xmlrpc_value ** containing an array. */ +XMLRPC_DLLEXPORT void xmlrpc_client_call_asynch_params(const char * const server_url, const char * const method_name, @@ -113,6 +127,7 @@ xmlrpc_client_call_asynch_params(const char * const server_url, /* As above, but use an xmlrpc_server_info object. The server object can be ** safely destroyed as soon as this function returns. */ +XMLRPC_DLLEXPORT void xmlrpc_client_call_server_asynch_params( xmlrpc_server_info * const server, @@ -130,11 +145,13 @@ xmlrpc_client_call_server_asynch_params( /* Finish all outstanding asynchronous calls. Alternatively, the loop ** will exit if someone calls xmlrpc_client_event_loop_end. */ +XMLRPC_DLLEXPORT extern void xmlrpc_client_event_loop_finish_asynch(void); /* Finish all outstanding asynchronous calls. */ +XMLRPC_DLLEXPORT extern void xmlrpc_client_event_loop_finish_asynch_timeout(unsigned long const milliseconds); diff --git a/libs/xmlrpc-c/include/xmlrpc-c/client_int.h b/libs/xmlrpc-c/include/xmlrpc-c/client_int.h index dabdcaf..79f7ade 100644 --- a/libs/xmlrpc-c/include/xmlrpc-c/client_int.h +++ b/libs/xmlrpc-c/include/xmlrpc-c/client_int.h @@ -86,6 +86,35 @@ xmlrpc_client_event_loop_end (void); extern int xmlrpc_client_asynch_calls_are_unfinished (void); + + +/*========================================================================= +** Interface between global client and general client functions. +** (These are necessary because there are some global client functions +** that don't have exported private client versions because we don't like +** them and have them for global functions only for backward compatibility. +** The global client functions existed before any private client ones did). +**========================================================================= */ +void +xmlrpc_client_call_server2_va(xmlrpc_env * const envP, + struct xmlrpc_client * const clientP, + const xmlrpc_server_info * const serverInfoP, + const char * const methodName, + const char * const format, + va_list args, + xmlrpc_value ** const resultPP); + +void +xmlrpc_client_start_rpcf_server_va( + xmlrpc_env * const envP, + struct xmlrpc_client * const clientP, + const xmlrpc_server_info * const serverInfoP, + const char * const methodName, + xmlrpc_response_handler responseHandler, + void * const userData, + const char * const format, + va_list args); + /* Copyright (C) 2001 by First Peer, Inc. All rights reserved. ** ** Redistribution and use in source and binary forms, with or without diff --git a/libs/xmlrpc-c/include/xmlrpc-c/client_simple.hpp b/libs/xmlrpc-c/include/xmlrpc-c/client_simple.hpp index 52e6c2b..5252363 100644 --- a/libs/xmlrpc-c/include/xmlrpc-c/client_simple.hpp +++ b/libs/xmlrpc-c/include/xmlrpc-c/client_simple.hpp @@ -3,13 +3,13 @@ #include +#include #include #include namespace xmlrpc_c { - -class clientSimple { +class XMLRPC_DLLEXPORT clientSimple { public: clientSimple(); diff --git a/libs/xmlrpc-c/include/xmlrpc-c/client_transport.hpp b/libs/xmlrpc-c/include/xmlrpc-c/client_transport.hpp index 8d6053d..ddeabf5 100644 --- a/libs/xmlrpc-c/include/xmlrpc-c/client_transport.hpp +++ b/libs/xmlrpc-c/include/xmlrpc-c/client_transport.hpp @@ -3,6 +3,8 @@ #include #include + +#include #include #include #include @@ -11,9 +13,9 @@ namespace xmlrpc_c { -class carriageParmPtr; +class XMLRPC_DLLEXPORT carriageParmPtr; -class carriageParm : public girmem::autoObject { +class XMLRPC_DLLEXPORT 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 @@ -30,7 +32,7 @@ protected: carriageParm(); }; -class carriageParmPtr : public girmem::autoObjectPtr { +class XMLRPC_DLLEXPORT carriageParmPtr : public girmem::autoObjectPtr { public: carriageParmPtr(); @@ -46,9 +48,9 @@ public: //---------------------------------------------------------------------------- -class xmlTransactionPtr; +class XMLRPC_DLLEXPORT xmlTransactionPtr; -class xmlTransaction : public girmem::autoObject { +class XMLRPC_DLLEXPORT xmlTransaction : public girmem::autoObject { friend class xmlTransactionPtr; @@ -59,11 +61,14 @@ public: virtual void finishErr(girerr::error const& error) const; + virtual void + progress(struct xmlrpc_progress_data const& progressData) const; + protected: xmlTransaction(); }; -class xmlTransactionPtr : public girmem::autoObjectPtr { +class XMLRPC_DLLEXPORT xmlTransactionPtr : public girmem::autoObjectPtr { public: xmlTransactionPtr(); @@ -75,7 +80,7 @@ public: //---------------------------------------------------------------------------- -class clientXmlTransport : public girmem::autoObject { +class XMLRPC_DLLEXPORT clientXmlTransport : public girmem::autoObject { /*---------------------------------------------------------------------------- An object which transports XML to and from an XML-RPC server for an XML-RPC client. @@ -105,11 +110,16 @@ public: xmlrpc_mem_block * const responseXmlMP, xmlrpc_env const transportEnv); + static void + progress( + struct xmlrpc_call_info * const callInfoP, + struct xmlrpc_progress_data const progressData); + virtual void setInterrupt(int * const interruptP); }; -class clientXmlTransportPtr : public girmem::autoObjectPtr { +class XMLRPC_DLLEXPORT clientXmlTransportPtr : public girmem::autoObjectPtr { public: clientXmlTransportPtr(); @@ -127,7 +137,7 @@ public: HTTP ===========================================================================*/ -class carriageParm_http0 : public xmlrpc_c::carriageParm { +class XMLRPC_DLLEXPORT carriageParm_http0 : public xmlrpc_c::carriageParm { public: carriageParm_http0(std::string const serverUrl); @@ -179,7 +189,7 @@ protected: instantiate(std::string const serverUrl); }; -class carriageParm_http0Ptr : public xmlrpc_c::carriageParmPtr { +class XMLRPC_DLLEXPORT carriageParm_http0Ptr : public xmlrpc_c::carriageParmPtr { public: carriageParm_http0Ptr(); @@ -189,7 +199,7 @@ public: operator->() const; }; -class clientXmlTransport_http : public xmlrpc_c::clientXmlTransport { +class XMLRPC_DLLEXPORT clientXmlTransport_http : public xmlrpc_c::clientXmlTransport { /*---------------------------------------------------------------------------- A base class for client XML transports that use the simple, classic C HTTP transports. @@ -230,13 +240,13 @@ protected: curl ===========================================================================*/ -class carriageParm_curl0 : public xmlrpc_c::carriageParm_http0 { +class XMLRPC_DLLEXPORT carriageParm_curl0 : public xmlrpc_c::carriageParm_http0 { public: carriageParm_curl0(std::string const serverUrl); }; -class carriageParm_curl0Ptr : public xmlrpc_c::carriageParm_http0Ptr { +class XMLRPC_DLLEXPORT carriageParm_curl0Ptr : public xmlrpc_c::carriageParm_http0Ptr { public: carriageParm_curl0Ptr(); @@ -246,16 +256,21 @@ public: operator->() const; }; -class clientXmlTransport_curl : public xmlrpc_c::clientXmlTransport_http { +class XMLRPC_DLLEXPORT clientXmlTransport_curl : public xmlrpc_c::clientXmlTransport_http { public: + struct constrOpt_impl; + class constrOpt { public: constrOpt(); + ~constrOpt(); + constrOpt(constrOpt&); constrOpt & network_interface (std::string const& arg); constrOpt & no_ssl_verifypeer (bool const& arg); constrOpt & no_ssl_verifyhost (bool const& arg); + constrOpt & dont_advertise (bool const& arg); constrOpt & user_agent (std::string const& arg); constrOpt & ssl_cert (std::string const& arg); constrOpt & sslcerttype (std::string const& arg); @@ -272,49 +287,15 @@ public: 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; + constrOpt & proxy (std::string const& arg); + constrOpt & proxy_port (unsigned int const& arg); + constrOpt & proxy_auth (unsigned int const& arg); + constrOpt & proxy_userpwd (std::string const& arg); + constrOpt & proxy_type (xmlrpc_httpproxytype const& arg); + + private: + struct constrOpt_impl * implP; + friend class clientXmlTransport_curl; }; clientXmlTransport_curl(constrOpt const& opt); @@ -335,14 +316,14 @@ private: libwww ===========================================================================*/ -class carriageParm_libwww0 : public xmlrpc_c::carriageParm_http0 { +class XMLRPC_DLLEXPORT carriageParm_libwww0 : public xmlrpc_c::carriageParm_http0 { public: carriageParm_libwww0(std::string const serverUrl); }; -class carriageParm_libwww0Ptr : public xmlrpc_c::carriageParm_http0Ptr { +class XMLRPC_DLLEXPORT carriageParm_libwww0Ptr : public xmlrpc_c::carriageParm_http0Ptr { public: carriageParm_libwww0Ptr(); @@ -352,7 +333,7 @@ public: operator->() const; }; -class clientXmlTransport_libwww : public xmlrpc_c::clientXmlTransport_http { +class XMLRPC_DLLEXPORT clientXmlTransport_libwww : public xmlrpc_c::clientXmlTransport_http { public: clientXmlTransport_libwww(std::string const appname = "", @@ -365,14 +346,14 @@ public: wininet ===========================================================================*/ -class carriageParm_wininet0 : public xmlrpc_c::carriageParm_http0 { +class XMLRPC_DLLEXPORT carriageParm_wininet0 : public xmlrpc_c::carriageParm_http0 { public: carriageParm_wininet0(std::string const serverUrl); }; -class carriageParm_wininet0Ptr : public xmlrpc_c::carriageParm_http0Ptr { +class XMLRPC_DLLEXPORT carriageParm_wininet0Ptr : public xmlrpc_c::carriageParm_http0Ptr { public: carriageParm_wininet0Ptr(); @@ -382,7 +363,7 @@ public: operator->() const; }; -class clientXmlTransport_wininet : public xmlrpc_c::clientXmlTransport_http { +class XMLRPC_DLLEXPORT clientXmlTransport_wininet : public xmlrpc_c::clientXmlTransport_http { public: clientXmlTransport_wininet(bool const allowInvalidSslCerts = false); @@ -394,15 +375,15 @@ public: pstream ===========================================================================*/ -class packetSocket; +class XMLRPC_DLLEXPORT packetSocket; -class carriageParm_pstream : public xmlrpc_c::carriageParm { +class XMLRPC_DLLEXPORT 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 { +class XMLRPC_DLLEXPORT carriageParm_pstreamPtr : public xmlrpc_c::carriageParmPtr { public: carriageParm_pstreamPtr(); @@ -413,21 +394,22 @@ public: operator->() const; }; -class clientXmlTransport_pstream : public xmlrpc_c::clientXmlTransport { +class XMLRPC_DLLEXPORT clientXmlTransport_pstream : public xmlrpc_c::clientXmlTransport { public: + struct constrOpt_impl; + class constrOpt { public: constrOpt(); + ~constrOpt(); + constrOpt(constrOpt&); constrOpt & fd (int const& arg); - struct { - int fd; - } value; - struct { - bool fd; - } present; + private: + struct constrOpt_impl * implP; + friend class clientXmlTransport_pstream; }; clientXmlTransport_pstream(constrOpt const& opt); diff --git a/libs/xmlrpc-c/include/xmlrpc-c/config.h.in b/libs/xmlrpc-c/include/xmlrpc-c/config.h.in deleted file mode 100644 index 2575010..0000000 --- a/libs/xmlrpc-c/include/xmlrpc-c/config.h.in +++ /dev/null @@ -1,37 +0,0 @@ -#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 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 @HAVE_WCHAR_H_DEFINE@ -#ifdef WIN32 - /* SOCKET is a type defined by . Anyone who - uses XMLRPC_SOCKET on a WIN32 system must #include - - */ - #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 diff --git a/libs/xmlrpc-c/include/xmlrpc-c/girerr.hpp b/libs/xmlrpc-c/include/xmlrpc-c/girerr.hpp index 1008722..62fd677 100644 --- a/libs/xmlrpc-c/include/xmlrpc-c/girerr.hpp +++ b/libs/xmlrpc-c/include/xmlrpc-c/girerr.hpp @@ -4,11 +4,13 @@ #include #include +#include + #define HAVE_GIRERR_ERROR namespace girerr { -class error : public std::exception { +class XMLRPC_DLLEXPORT error : public std::exception { public: error(std::string const& what_arg) : _what(what_arg) {} @@ -23,8 +25,11 @@ private: // throwf() always throws a girerr::error . +XMLRPC_DLLEXPORT void -throwf(const char * const format, ...); +throwf(const char * const format, ...) + XMLRPC_PRINTF_ATTR(1,2) + XMLRPC_NORETURN_ATTR; } // namespace diff --git a/libs/xmlrpc-c/include/xmlrpc-c/girmem.hpp b/libs/xmlrpc-c/include/xmlrpc-c/girmem.hpp index 2eed408..80ef8fc 100644 --- a/libs/xmlrpc-c/include/xmlrpc-c/girmem.hpp +++ b/libs/xmlrpc-c/include/xmlrpc-c/girmem.hpp @@ -1,6 +1,8 @@ #ifndef GIRMEM_HPP_INCLUDED #define GIRMEM_HPP_INCLUDED +#include +#include /* The following pthread crap mirrors what is in pthreadx.h, which is what girmem.cpp uses to declare the lock interface. We can't simply @@ -15,7 +17,7 @@ a pthread_mutex_t member, and on Windows, there's no such type. */ -#ifndef WIN32 +#if XMLRPC_HAVE_PTHREAD # include typedef pthread_mutex_t girmem_lock; #else @@ -25,9 +27,9 @@ namespace girmem { -class autoObjectPtr; +class XMLRPC_DLLEXPORT autoObjectPtr; -class autoObject { +class XMLRPC_DLLEXPORT autoObject { friend class autoObjectPtr; public: @@ -43,7 +45,7 @@ private: unsigned int refcount; }; -class autoObjectPtr { +class XMLRPC_DLLEXPORT autoObjectPtr { public: autoObjectPtr(); autoObjectPtr(girmem::autoObject * objectP); diff --git a/libs/xmlrpc-c/include/xmlrpc-c/inttypes.h b/libs/xmlrpc-c/include/xmlrpc-c/inttypes.h index fe1feb5..1e470e5 100644 --- a/libs/xmlrpc-c/include/xmlrpc-c/inttypes.h +++ b/libs/xmlrpc-c/include/xmlrpc-c/inttypes.h @@ -9,6 +9,9 @@ typedef unsigned __int64 xmlrpc_uint64_t; #else #include +#ifdef __INTERIX +# include +#endif typedef uint16_t xmlrpc_uint16_t; typedef uint32_t xmlrpc_uint32_t; diff --git a/libs/xmlrpc-c/include/xmlrpc-c/json.h b/libs/xmlrpc-c/include/xmlrpc-c/json.h new file mode 100644 index 0000000..d7b8453 --- /dev/null +++ b/libs/xmlrpc-c/include/xmlrpc-c/json.h @@ -0,0 +1,39 @@ +#ifndef XMLRPC_JSON_H_INCLUDED +#define XMLRPC_JSON_H_INCLUDED + +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* + Parse a given string as JSON and return its value as an XML-RPC value + object. + + @param envP xmlrpc environment for error handling + @param buf holds a pointer to a ziro terminated string + @return the value generated or NULL (check error) +*/ +xmlrpc_value * +xmlrpc_parse_json(xmlrpc_env * const envP, + const char * const json); + + +/* + Serialize an XML-RPC value object into JSON. + + @param envP holds the xmlrpc execution environment + @param valP holds the value to serialize + @param out holds a mem block containing the result +*/ +void +xmlrpc_serialize_json(xmlrpc_env * const envP, + xmlrpc_value * const valP, + xmlrpc_mem_block * const jsonP); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XMLRPC_JSON_H_INCLUDED */ diff --git a/libs/xmlrpc-c/include/xmlrpc-c/oldcppwrapper.hpp b/libs/xmlrpc-c/include/xmlrpc-c/oldcppwrapper.hpp index 78a9c51..858fdd3 100644 --- a/libs/xmlrpc-c/include/xmlrpc-c/oldcppwrapper.hpp +++ b/libs/xmlrpc-c/include/xmlrpc-c/oldcppwrapper.hpp @@ -27,17 +27,18 @@ #include #include + +#include #include #include #include - //========================================================================= // XmlRpcFault //========================================================================= // A C++ exception class representing an XML-RPC fault. -class XmlRpcFault { +class XMLRPC_DLLEXPORT XmlRpcFault { private: xmlrpc_env mFault; @@ -51,9 +52,9 @@ public: XmlRpcFault (const xmlrpc_env *env); ~XmlRpcFault (void); - int getFaultCode (void) const; - std::string getFaultString (void) const; - xmlrpc_env *getFaultEnv (void); + inline int getFaultCode (void) const; + std::string getFaultString (void) const; + inline xmlrpc_env * getFaultEnv (void); }; inline int XmlRpcFault::getFaultCode (void) const { @@ -74,7 +75,7 @@ inline xmlrpc_env *XmlRpcFault::getFaultEnv (void) { // xmlrpc_parse_value(env, v, "(i)", &i); // env.throwIfFaultOccurred(); -class XmlRpcEnv { +class XMLRPC_DLLEXPORT XmlRpcEnv { private: xmlrpc_env mEnv; @@ -128,7 +129,7 @@ inline void XmlRpcEnv::throwIfFaultOccurred (void) const { // // So reference counting for the xmlrpc_value is quite a nightmare. -class XmlRpcValue { +class XMLRPC_DLLEXPORT XmlRpcValue { private: xmlrpc_value *mValue; @@ -257,7 +258,7 @@ inline xmlrpc_value *XmlRpcValue::borrowReference (void) const { // XmlRpcClient //========================================================================= -class XmlRpcClient { +class XMLRPC_DLLEXPORT XmlRpcClient { private: std::string mServerUrl; @@ -344,7 +345,7 @@ inline XmlRpcValue XmlRpcClient::call (std::string method_name, // XmlRpcGenSrv //========================================================================= -class XmlRpcGenSrv { +class XMLRPC_DLLEXPORT XmlRpcGenSrv { private: diff --git a/libs/xmlrpc-c/include/xmlrpc-c/packetsocket.hpp b/libs/xmlrpc-c/include/xmlrpc-c/packetsocket.hpp index 64b7221..2ad7a46 100644 --- a/libs/xmlrpc-c/include/xmlrpc-c/packetsocket.hpp +++ b/libs/xmlrpc-c/include/xmlrpc-c/packetsocket.hpp @@ -15,20 +15,21 @@ #include #include +#include #include namespace xmlrpc_c { -class packet : public girmem::autoObject { +class XMLRPC_DLLEXPORT packet : public girmem::autoObject { public: packet(); packet(const unsigned char * const data, - size_t const dataLength); + size_t const dataLength); packet(const char * const data, - size_t const dataLength); + size_t const dataLength); ~packet(); @@ -54,7 +55,7 @@ private: -class packetPtr: public girmem::autoObjectPtr { +class XMLRPC_DLLEXPORT packetPtr: public girmem::autoObjectPtr { public: packetPtr(); @@ -67,7 +68,9 @@ public: -class packetSocket { +class XMLRPC_DLLEXPORT packetSocket_impl; + +class XMLRPC_DLLEXPORT packetSocket { /*---------------------------------------------------------------------------- This is an Internet communication vehicle that transmits individual variable-length packets of text. @@ -106,56 +109,7 @@ public: 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 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(); - + packetSocket_impl * implP; }; diff --git a/libs/xmlrpc-c/include/xmlrpc-c/registry.hpp b/libs/xmlrpc-c/include/xmlrpc-c/registry.hpp index 1182b86..81db5b0 100644 --- a/libs/xmlrpc-c/include/xmlrpc-c/registry.hpp +++ b/libs/xmlrpc-c/include/xmlrpc-c/registry.hpp @@ -1,10 +1,12 @@ #ifndef REGISTRY_HPP_INCLUDED #define REGISTRY_HPP_INCLUDED +#include #include #include #include +#include #include #include #include @@ -12,7 +14,20 @@ namespace xmlrpc_c { -class method : public girmem::autoObject { +class XMLRPC_DLLEXPORT callInfo { +/*---------------------------------------------------------------------------- + Information about how an XML-RPC call arrived. + + This base class carries no information; Servers that don't have any + call information to provide might use this. Servers that do have call + information to provide define a derived class of this that contains + information pertinent to that kind of server. +-----------------------------------------------------------------------------*/ +public: + virtual ~callInfo() {}; // This makes it polymorphic +}; + +class XMLRPC_DLLEXPORT method : public girmem::autoObject { /*---------------------------------------------------------------------------- An XML-RPC method. @@ -68,7 +83,34 @@ protected: */ -class methodPtr : public girmem::autoObjectPtr { +class XMLRPC_DLLEXPORT method2 : public method { +/*---------------------------------------------------------------------------- + An XML-RPC method. + + This base class is abstract. You can't create an object in it. + Define a useful method with this as a base class, with an + execute() method. + + This differs from class 'method' in that the execute() method gets + call information ('callInfo'). +-----------------------------------------------------------------------------*/ +public: + method2(); + + virtual ~method2(); + + virtual void + execute(xmlrpc_c::paramList const& paramList, + const xmlrpc_c::callInfo * const callInfoP, + xmlrpc_c::value * const resultP) = 0; + + void + execute(xmlrpc_c::paramList const& paramList, + xmlrpc_c::value * const resultP); + +}; + +class XMLRPC_DLLEXPORT methodPtr : public girmem::autoObjectPtr { public: methodPtr(xmlrpc_c::method * const methodP); @@ -77,7 +119,7 @@ public: operator->() const; }; -class defaultMethod : public girmem::autoObject { +class XMLRPC_DLLEXPORT defaultMethod : public girmem::autoObject { public: virtual ~defaultMethod(); @@ -88,7 +130,7 @@ public: xmlrpc_c::value * const resultP) = 0; }; -class defaultMethodPtr : public girmem::autoObjectPtr { +class XMLRPC_DLLEXPORT defaultMethodPtr : public girmem::autoObjectPtr { public: defaultMethodPtr(); @@ -102,9 +144,9 @@ public: get() const; }; +struct registry_impl; - -class registry : public girmem::autoObject { +class XMLRPC_DLLEXPORT 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 @@ -126,7 +168,7 @@ public: void disableIntrospection(); - class shutdown { + class XMLRPC_DLLEXPORT shutdown { public: virtual ~shutdown() = 0; virtual void @@ -141,36 +183,24 @@ public: setDialect(xmlrpc_dialect const dialect); void - processCall(std::string const& body, - std::string * const responseP) const; + processCall(std::string const& callXml, + std::string * const responseXmlP) const; - xmlrpc_registry * - c_registry() const; - /* This is meant to be private except to other objects in the - Xmlrpc-c library. - */ + void + processCall(std::string const& callXml, + const xmlrpc_c::callInfo * const callInfoP, + std::string * const responseXmlP) const; + + size_t + maxStackSize() const; private: - xmlrpc_registry * c_registryP; - // Pointer to the C registry object we use to implement this - // object. - - std::list 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. - - 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. + registry_impl * implP; }; -class registryPtr : public girmem::autoObjectPtr { +class XMLRPC_DLLEXPORT registryPtr : public girmem::autoObjectPtr { public: registryPtr(); diff --git a/libs/xmlrpc-c/include/xmlrpc-c/select_int.h b/libs/xmlrpc-c/include/xmlrpc-c/select_int.h index 3b42a1d..7a43ec3 100644 --- a/libs/xmlrpc-c/include/xmlrpc-c/select_int.h +++ b/libs/xmlrpc-c/include/xmlrpc-c/select_int.h @@ -1,11 +1,12 @@ #ifndef SELECT_INT_H_INCLUDED #define SELECT_INT_H_INCLUDED -#ifndef WIN32 +#if HAVE_SYS_SELECT_H #include #endif #include +#include "xmlrpc-c/c_util.h" #include "xmlrpc-c/time_int.h" #ifdef WIN32 #ifndef sigset_t @@ -13,6 +14,7 @@ typedef int sigset_t; #endif #endif +XMLRPC_DLLEXPORT int xmlrpc_pselect(int const n, fd_set * const readfdsP, diff --git a/libs/xmlrpc-c/include/xmlrpc-c/server.h b/libs/xmlrpc-c/include/xmlrpc-c/server.h index 70d4896..11256fe 100644 --- a/libs/xmlrpc-c/include/xmlrpc-c/server.h +++ b/libs/xmlrpc-c/include/xmlrpc-c/server.h @@ -3,6 +3,7 @@ #ifndef XMLRPC_SERVER_H_INCLUDED #define XMLRPC_SERVER_H_INCLUDED +#include #include #ifdef __cplusplus @@ -37,19 +38,32 @@ typedef xmlrpc_value * xmlrpc_value * const paramArrayP, void * const serverInfo); +/* These are for backward compatibility -- they can't be exported from a + Windows DLL. xmlrpc_server_version() is preferred. +*/ extern unsigned int const xmlrpc_server_version_major; extern unsigned int const xmlrpc_server_version_minor; extern unsigned int const xmlrpc_server_version_point; +XMLRPC_DLLEXPORT +void +xmlrpc_server_version(unsigned int * const majorP, + unsigned int * const minorP, + unsigned int * const pointP); + +XMLRPC_DLLEXPORT xmlrpc_registry * xmlrpc_registry_new(xmlrpc_env * const envP); +XMLRPC_DLLEXPORT void xmlrpc_registry_free(xmlrpc_registry * const registryP); +XMLRPC_DLLEXPORT void xmlrpc_registry_disable_introspection(xmlrpc_registry * const registryP); +XMLRPC_DLLEXPORT void xmlrpc_registry_add_method(xmlrpc_env * const envP, xmlrpc_registry * const registryP, @@ -58,6 +72,7 @@ xmlrpc_registry_add_method(xmlrpc_env * const envP, xmlrpc_method const method, void * const serverInfo); +XMLRPC_DLLEXPORT void xmlrpc_registry_add_method_w_doc(xmlrpc_env * const envP, xmlrpc_registry * const registryP, @@ -68,6 +83,7 @@ xmlrpc_registry_add_method_w_doc(xmlrpc_env * const envP, const char * const signatureString, const char * const help); +XMLRPC_DLLEXPORT void xmlrpc_registry_add_method2(xmlrpc_env * const envP, xmlrpc_registry * const registryP, @@ -77,12 +93,30 @@ xmlrpc_registry_add_method2(xmlrpc_env * const envP, const char * const help, void * const serverInfo); +struct xmlrpc_method_info3 { + const char * methodName; + xmlrpc_method2 methodFunction; + void * serverInfo; + size_t stackSize; + const char * signatureString; + const char * help; +}; + +XMLRPC_DLLEXPORT +void +xmlrpc_registry_add_method3( + xmlrpc_env * const envP, + xmlrpc_registry * const registryP, + const struct xmlrpc_method_info3 * const infoP); + +XMLRPC_DLLEXPORT void xmlrpc_registry_set_default_method(xmlrpc_env * const envP, xmlrpc_registry * const registryP, xmlrpc_default_method const handler, void * const userData); +XMLRPC_DLLEXPORT void xmlrpc_registry_set_preinvoke_method(xmlrpc_env * const envP, xmlrpc_registry * const registryP, @@ -95,11 +129,13 @@ typedef void xmlrpc_server_shutdown_fn(xmlrpc_env * const envP, const char * const comment, void * const callInfo); +XMLRPC_DLLEXPORT void xmlrpc_registry_set_shutdown(xmlrpc_registry * const registryP, xmlrpc_server_shutdown_fn * const shutdownFn, void * const context); +XMLRPC_DLLEXPORT void xmlrpc_registry_set_dialect(xmlrpc_env * const envP, xmlrpc_registry * const registryP, @@ -109,6 +145,7 @@ xmlrpc_registry_set_dialect(xmlrpc_env * const envP, Lower interface -- services to be used by an HTTP request handler -----------------------------------------------------------------------------*/ +XMLRPC_DLLEXPORT void xmlrpc_registry_process_call2(xmlrpc_env * const envP, xmlrpc_registry * const registryP, @@ -117,6 +154,7 @@ xmlrpc_registry_process_call2(xmlrpc_env * const envP, void * const callInfo, xmlrpc_mem_block ** const outputPP); +XMLRPC_DLLEXPORT xmlrpc_mem_block * xmlrpc_registry_process_call(xmlrpc_env * const envP, xmlrpc_registry * const registryP, @@ -124,6 +162,10 @@ xmlrpc_registry_process_call(xmlrpc_env * const envP, const char * const xmlData, size_t const xmlLen); +XMLRPC_DLLEXPORT +size_t +xmlrpc_registry_max_stackSize(xmlrpc_registry * const registryP); + #ifdef __cplusplus } #endif diff --git a/libs/xmlrpc-c/include/xmlrpc-c/server_abyss.h b/libs/xmlrpc-c/include/xmlrpc-c/server_abyss.h index 975fa0e..36bcb11 100644 --- a/libs/xmlrpc-c/include/xmlrpc-c/server_abyss.h +++ b/libs/xmlrpc-c/include/xmlrpc-c/server_abyss.h @@ -16,6 +16,7 @@ #endif #include /* For XMLRPC_SOCKET */ +#include #include #include @@ -33,9 +34,11 @@ extern "C" { ** of your program, when it is only one thread. **=======================================================================*/ +XMLRPC_DLLEXPORT void xmlrpc_server_abyss_global_init(xmlrpc_env * const envP); +XMLRPC_DLLEXPORT void xmlrpc_server_abyss_global_term(void); @@ -68,6 +71,9 @@ typedef struct { const char * uri_path; xmlrpc_bool chunk_response; xmlrpc_bool enable_shutdown; + const char * allow_origin; + xmlrpc_bool access_ctl_expires; + unsigned int access_ctl_max_age; } xmlrpc_server_abyss_parms; @@ -85,10 +91,11 @@ typedef struct { ** Simple server with Abyss under the covers **=======================================================================*/ +XMLRPC_DLLEXPORT void xmlrpc_server_abyss(xmlrpc_env * const envP, const xmlrpc_server_abyss_parms * const parms, - unsigned int const parm_size); + unsigned int const parmSize); /*========================================================================= ** Object-oriented XML-RPC server with Abyss under the covers @@ -96,39 +103,47 @@ xmlrpc_server_abyss(xmlrpc_env * const envP, typedef struct xmlrpc_server_abyss xmlrpc_server_abyss_t; +XMLRPC_DLLEXPORT 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); +XMLRPC_DLLEXPORT void xmlrpc_server_abyss_destroy(xmlrpc_server_abyss_t * const serverP); +XMLRPC_DLLEXPORT void xmlrpc_server_abyss_run_server(xmlrpc_env * const envP, xmlrpc_server_abyss_t * const serverP); +XMLRPC_DLLEXPORT void xmlrpc_server_abyss_terminate(xmlrpc_env * const envP, xmlrpc_server_abyss_t * const serverP); +XMLRPC_DLLEXPORT void xmlrpc_server_abyss_reset_terminate(xmlrpc_env * const envP, xmlrpc_server_abyss_t * const serverP); +XMLRPC_DLLEXPORT void xmlrpc_server_abyss_use_sigchld(xmlrpc_server_abyss_t * const serverP); typedef struct xmlrpc_server_abyss_sig xmlrpc_server_abyss_sig; +XMLRPC_DLLEXPORT void xmlrpc_server_abyss_setup_sig( xmlrpc_env * const envP, xmlrpc_server_abyss_t * const serverP, xmlrpc_server_abyss_sig ** const oldHandlersPP); +XMLRPC_DLLEXPORT void xmlrpc_server_abyss_restore_sig( const xmlrpc_server_abyss_sig * const oldHandlersP); @@ -139,21 +154,78 @@ xmlrpc_server_abyss_restore_sig( ** Functions to make an XML-RPC server out of your own Abyss server **=======================================================================*/ +typedef void +xmlrpc_call_processor(xmlrpc_env * const envP, + void * const processorArg, + const char * const callXml, + size_t const callXmlLen, + TSession * const abyssSessionP, + xmlrpc_mem_block ** const responseXmlPP); + +typedef struct { + xmlrpc_call_processor * xml_processor; + void * xml_processor_arg; + size_t xml_processor_max_stack; + const char * uri_path; + xmlrpc_bool chunk_response; + const char * allow_origin; + /* NULL means don't answer HTTP access control query */ + xmlrpc_bool access_ctl_expires; + unsigned int access_ctl_max_age; +} xmlrpc_server_abyss_handler_parms; + +#define XMLRPC_AHPSIZE(MBRNAME) \ + XMLRPC_STRUCTSIZE(xmlrpc_server_abyss_handler_parms, MBRNAME) + +/* XMLRPC_AHPSIZE(xyz) is the minimum size a struct + xmlrpc_server_abyss_handler_parms must be to include the 'xyz' member. + This is essential to forward and 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. +*/ + + +XMLRPC_DLLEXPORT +void +xmlrpc_server_abyss_set_handler3( + xmlrpc_env * const envP, + TServer * const srvP, + const xmlrpc_server_abyss_handler_parms * const parms, + unsigned int const parmSize); + +XMLRPC_DLLEXPORT +void +xmlrpc_server_abyss_set_handler2( + TServer * const srvP, + const char * const uriPath, + xmlrpc_call_processor xmlProcessor, + void * const xmlProcessorArg, + size_t const xmlProcessorMaxStackSize, + xmlrpc_bool const chunkResponse); + +XMLRPC_DLLEXPORT void xmlrpc_server_abyss_set_handlers2(TServer * const srvP, const char * const filename, xmlrpc_registry * const registryP); +XMLRPC_DLLEXPORT void xmlrpc_server_abyss_set_handlers(TServer * const serverP, xmlrpc_registry * const registryP); +XMLRPC_DLLEXPORT void xmlrpc_server_abyss_set_handler(xmlrpc_env * const envP, TServer * const serverP, const char * const filename, xmlrpc_registry * const registryP); +XMLRPC_DLLEXPORT +void +xmlrpc_server_abyss_set_default_handler(TServer * const serverP); + /*========================================================================= ** Handy Abyss Extensions **=======================================================================*/ @@ -171,6 +243,7 @@ xmlrpc_server_abyss_set_handler(xmlrpc_env * const envP, ** Once you call this routine, it is illegal to modify the server any ** more, including changing any method registry. */ +XMLRPC_DLLEXPORT void xmlrpc_server_abyss_run(void); @@ -180,6 +253,7 @@ xmlrpc_server_abyss_run(void); ** function. 'runfirstArg' is the argument the server passes to the runfirst ** function. **/ +XMLRPC_DLLEXPORT void xmlrpc_server_abyss_run_first(runfirstFn const runfirst, void * const runfirstArg); @@ -200,29 +274,34 @@ xmlrpc_server_abyss_run_first(runfirstFn const runfirst, ** Or use a regular method registry and call ** xmlrpc_server_abyss_set_handlers(). **/ +XMLRPC_DLLEXPORT void xmlrpc_server_abyss_init(int const flags, const char * const config_file); /* This is called automatically by xmlrpc_server_abyss_init. */ +XMLRPC_DLLEXPORT void xmlrpc_server_abyss_init_registry (void); /* Fetch the internal registry, if you happen to need it. If you're using this, you really shouldn't be using the built-in registry at all. It exists today only for backward compatibilty. */ +XMLRPC_DLLEXPORT extern xmlrpc_registry * xmlrpc_server_abyss_registry (void); /* 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. */ +XMLRPC_DLLEXPORT 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. */ +XMLRPC_DLLEXPORT extern void xmlrpc_server_abyss_add_method_w_doc (char * const method_name, xmlrpc_method const method, diff --git a/libs/xmlrpc-c/include/xmlrpc-c/server_abyss.hpp b/libs/xmlrpc-c/include/xmlrpc-c/server_abyss.hpp index 1ff9043..44636f9 100644 --- a/libs/xmlrpc-c/include/xmlrpc-c/server_abyss.hpp +++ b/libs/xmlrpc-c/include/xmlrpc-c/server_abyss.hpp @@ -5,18 +5,25 @@ #include // For XMLRPC_SOCKET (= SOCKET) #endif -#include "xmlrpc-c/config.h" // For XMLRPC_SOCKET -#include "xmlrpc-c/base.hpp" -#include "abyss.h" +#include // For XMLRPC_SOCKET +#include +#include +#include +#include namespace xmlrpc_c { -class serverAbyss { +struct serverAbyss_impl; + +class XMLRPC_DLLEXPORT serverAbyss { public: - class constrOpt { + struct constrOpt_impl; + + class XMLRPC_DLLEXPORT constrOpt { public: constrOpt(); + ~constrOpt(); constrOpt & registryPtr (xmlrpc_c::registryPtr const& arg); constrOpt & registryP (const xmlrpc_c::registry * const& arg); @@ -29,33 +36,14 @@ public: constrOpt & dontAdvertise (bool const& arg); constrOpt & uriPath (std::string const& arg); constrOpt & chunkResponse (bool const& arg); + constrOpt & allowOrigin (std::string const& arg); + constrOpt & accessCtlMaxAge (unsigned int const& arg); + constrOpt & serverOwnsSignals (bool const& arg); + constrOpt & expectSigchld (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; + private: + struct constrOpt_impl * implP; + friend class serverAbyss; }; serverAbyss(constrOpt const& opt); @@ -82,10 +70,15 @@ public: void runConn(int const socketFd); +#ifndef WIN32 + void + sigchld(pid_t pid); +#endif + void terminate(); - class shutdown : public xmlrpc_c::registry::shutdown { + class XMLRPC_DLLEXPORT shutdown : public xmlrpc_c::registry::shutdown { public: shutdown(xmlrpc_c::serverAbyss * const severAbyssP); virtual ~shutdown(); @@ -95,35 +88,64 @@ public: }; private: - // 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); + serverAbyss_impl * implP; void initialize(constrOpt const& opt); }; +class XMLRPC_DLLEXPORT callInfo_serverAbyss : public xmlrpc_c::callInfo { +/*---------------------------------------------------------------------------- + This is information about how an XML-RPC call arrived via an Abyss server. + It is available to the user's XML-RPC method execute() method, so for + example an XML-RPC method might execute differently depending upon the + IP address of the client. + + This is for a user of a xmlrpc_c::serverAbyss server. +-----------------------------------------------------------------------------*/ +public: + callInfo_serverAbyss(xmlrpc_c::serverAbyss * const abyssServerP, + TSession * const abyssSessionP); + + xmlrpc_c::serverAbyss * const serverAbyssP; + // The server that is processing the RPC. + TSession * const abyssSessionP; + // The HTTP transaction that embodies the RPC. You can ask this + // object things like what the IP address of the client is. +}; + +class XMLRPC_DLLEXPORT callInfo_abyss : public xmlrpc_c::callInfo { +/*---------------------------------------------------------------------------- + This is information about how an XML-RPC call arrived via an Abyss server. + It is available to the user's XML-RPC method execute() method, so for + example an XML-RPC method might execute differently depending upon the + IP address of the client. + + This is for a user with his own Abyss server, using + the "set_handlers" routines to make it into an XML-RPC server. +-----------------------------------------------------------------------------*/ +public: + callInfo_abyss(TSession * const abyssSessionP); + + TSession * abyssSessionP; + // The HTTP transaction that embodies the RPC. You can ask this + // object things like what the IP address of the client is. +}; +XMLRPC_DLLEXPORT void server_abyss_set_handlers(TServer * const srvP, xmlrpc_c::registry const& registry, std::string const& uriPath = "/RPC2"); +XMLRPC_DLLEXPORT void server_abyss_set_handlers(TServer * const srvP, const xmlrpc_c::registry * const registryP, std::string const& uriPath = "/RPC2"); +XMLRPC_DLLEXPORT void server_abyss_set_handlers(TServer * const srvP, xmlrpc_c::registryPtr const registryPtr, diff --git a/libs/xmlrpc-c/include/xmlrpc-c/server_cgi.h b/libs/xmlrpc-c/include/xmlrpc-c/server_cgi.h index ad926aa..e43b9e7 100644 --- a/libs/xmlrpc-c/include/xmlrpc-c/server_cgi.h +++ b/libs/xmlrpc-c/include/xmlrpc-c/server_cgi.h @@ -6,38 +6,45 @@ #ifndef XMLRPC_CGI_H_INCLUDED #define XMLRPC_CGI_H_INCLUDED +#include #include #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ - +XMLRPC_DLLEXPORT void xmlrpc_server_cgi_process_call(xmlrpc_registry * const registryP); #define XMLRPC_CGI_NO_FLAGS (0) +XMLRPC_DLLEXPORT extern void -xmlrpc_cgi_init (int flags); +xmlrpc_cgi_init(int const flags); +XMLRPC_DLLEXPORT extern xmlrpc_registry * xmlrpc_cgi_registry (void); +XMLRPC_DLLEXPORT void xmlrpc_cgi_add_method(const char * const method_name, xmlrpc_method const method, void * const user_data); +XMLRPC_DLLEXPORT void xmlrpc_cgi_add_method_w_doc(const char * const method_name, xmlrpc_method const method, void * const user_data, const char * const signature, const char * const help); +XMLRPC_DLLEXPORT extern void xmlrpc_cgi_process_call (void); +XMLRPC_DLLEXPORT extern void xmlrpc_cgi_cleanup (void); diff --git a/libs/xmlrpc-c/include/xmlrpc-c/server_cgi.hpp b/libs/xmlrpc-c/include/xmlrpc-c/server_cgi.hpp new file mode 100644 index 0000000..a030ee5 --- /dev/null +++ b/libs/xmlrpc-c/include/xmlrpc-c/server_cgi.hpp @@ -0,0 +1,45 @@ +#ifndef SERVER_CGI_HPP_INCLUDED +#define SERVER_CGI_HPP_INCLUDED + +#include +#include + +namespace xmlrpc_c { + +class XMLRPC_DLLEXPORT serverCgi { + +public: + + class XMLRPC_DLLEXPORT constrOpt { + public: + constrOpt(); + + constrOpt & registryPtr (xmlrpc_c::registryPtr const& arg); + constrOpt & registryP (const xmlrpc_c::registry * const& arg); + + struct value { + xmlrpc_c::registryPtr registryPtr; + const xmlrpc_c::registry * registryP; + } value; + struct { + bool registryPtr; + bool registryP; + } present; + }; + + serverCgi(constrOpt const& opt); + + ~serverCgi(); + + void + processCall(); + +private: + + struct serverCgi_impl * implP; +}; + + +} // namespace + +#endif diff --git a/libs/xmlrpc-c/include/xmlrpc-c/server_pstream.hpp b/libs/xmlrpc-c/include/xmlrpc-c/server_pstream.hpp index b542532..c365f9a 100644 --- a/libs/xmlrpc-c/include/xmlrpc-c/server_pstream.hpp +++ b/libs/xmlrpc-c/include/xmlrpc-c/server_pstream.hpp @@ -3,36 +3,36 @@ #ifdef WIN32 #include /* For XMLRPC_SOCKET (= SOCKET) */ +typedef int socklen_t; +#else +#include #endif #include /* For XMLRPC_SOCKET */ +#include #include #include namespace xmlrpc_c { -class serverPstreamConn { +class XMLRPC_DLLEXPORT serverPstreamConn { public: - class constrOpt { + struct constrOpt_impl; + + class XMLRPC_DLLEXPORT constrOpt { public: constrOpt(); + ~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; + private: + struct constrOpt_impl * implP; + friend class serverPstreamConn; }; serverPstreamConn(constrOpt const& opt); @@ -40,33 +40,122 @@ public: ~serverPstreamConn(); void + runOnce(xmlrpc_c::callInfo * const callInfoP, + volatile const int * const interruptP, + bool * const eofP); + + void runOnce(volatile const int * const interruptP, bool * const eofP); void runOnce(bool * const eofP); + void + runOnceNoWait(callInfo * const callInfoP, + bool * const eofP, + bool * const didOneP); + + void + runOnceNoWait(bool * const eofP, + bool * const didOneP); + + void + runOnceNoWait(bool * const eofP); + + void + run(xmlrpc_c::callInfo * const callInfoP, + volatile const int * const interruptP); + + void + run(volatile const int * const interruptP); + + void + run(); + private: + struct serverPstreamConn_impl * implP; +}; - // '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; +class XMLRPC_DLLEXPORT serverPstream { - packetSocket * packetSocketP; - // The packet socket over which we received RPCs. - // This is permanently connected to our fixed client. +public: + + struct constrOpt_impl; + + class XMLRPC_DLLEXPORT constrOpt { + public: + constrOpt(); + ~constrOpt(); + + constrOpt & registryPtr (xmlrpc_c::registryPtr const& arg); + constrOpt & registryP (const xmlrpc_c::registry * const& arg); + constrOpt & socketFd (XMLRPC_SOCKET const& arg); + + private: + struct constrOpt_impl * implP; + friend class serverPstream; + }; + + serverPstream(constrOpt const& opt); + + virtual ~serverPstream(); // This makes it polymorphic void - establishRegistry(constrOpt const& opt); + runSerial(volatile const int * const interruptP); void - establishPacketSocket(constrOpt const& opt); + runSerial(); + + void + terminate(); + + class shutdown : public xmlrpc_c::registry::shutdown { + public: + shutdown(xmlrpc_c::serverPstream * const severAbyssP); + virtual ~shutdown(); + void doit(std::string const& comment, void * const callInfo) const; + private: + xmlrpc_c::serverPstream * const serverPstreamP; + }; + +private: + struct serverPstream_impl * implP; +}; + +// Note: there is no xmlrpc_c::callInfo_serverPstreamConn . That's +// because the serverPstreamConn server is so low-level that the user +// defines his own derived class of xmlrpc_c::callInfo. He creates an +// object of that class and passes it to the 'runOnce' method. The +// server then passes it on through to the user's XML-RPC method +// execute() method. + +class XMLRPC_DLLEXPORT callInfo_serverPstream : public xmlrpc_c::callInfo { +/*---------------------------------------------------------------------------- + This is information about how an XML-RPC call arrived to the server. It is + available to the user's XML-RPC method execute() method, so for example an + XML-RPC method might execute differently depending upon the IP address of + the client. + + This is for a user of a xmlrpc_c::serverPstream server. +-----------------------------------------------------------------------------*/ +public: + callInfo_serverPstream( + xmlrpc_c::serverPstream * const serverP, + struct sockaddr const clientAddr, + socklen_t const clientAddrSize); + + xmlrpc_c::serverPstream * const serverP; + // The server that is processing the RPC. + struct sockaddr const clientAddr; + // The address (typically, IP address and TCP port) of the XML-RPC + // client. This is a Unix OS type. + socklen_t const clientAddrSize; + // Size in bytes of the valid part of 'clientAddr'. (Usually implied + // by type of socket, as well as the address type member of + // 'clientAddr', but here because it's technically part of the POSIX + // socket interface). }; diff --git a/libs/xmlrpc-c/include/xmlrpc-c/server_w32httpsys.h b/libs/xmlrpc-c/include/xmlrpc-c/server_w32httpsys.h index 085f6e3..4c054c0 100644 --- a/libs/xmlrpc-c/include/xmlrpc-c/server_w32httpsys.h +++ b/libs/xmlrpc-c/include/xmlrpc-c/server_w32httpsys.h @@ -38,6 +38,7 @@ #ifndef _XMLRPC_SERVER_HTTPSYS_H_ #define _XMLRPC_SERVER_HTTPSYS_H_ 1 +#include "c_util.h" #include "transport_config.h" #ifdef __cplusplus @@ -81,6 +82,7 @@ typedef struct { not the caller is new enough to have supplied a certain parameter. */ +XMLRPC_DLLEXPORT void xmlrpc_server_httpsys( xmlrpc_env * const envP, @@ -92,4 +94,4 @@ xmlrpc_server_httpsys( } #endif /* __cplusplus */ -#endif \ No newline at end of file +#endif diff --git a/libs/xmlrpc-c/include/xmlrpc-c/sleep_int.h b/libs/xmlrpc-c/include/xmlrpc-c/sleep_int.h index be18e8f..369fd24 100644 --- a/libs/xmlrpc-c/include/xmlrpc-c/sleep_int.h +++ b/libs/xmlrpc-c/include/xmlrpc-c/sleep_int.h @@ -1,7 +1,18 @@ #ifndef SLEEP_INT_H_INCLUDED #define SLEEP_INT_H_INCLUDED +#include "xmlrpc-c/c_util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +XMLRPC_DLLEXPORT void xmlrpc_millisecond_sleep(unsigned int const milliseconds); +#ifdef __cplusplus +} +#endif + #endif diff --git a/libs/xmlrpc-c/include/xmlrpc-c/string_int.h b/libs/xmlrpc-c/include/xmlrpc-c/string_int.h index fa787cb..04ac8c7 100644 --- a/libs/xmlrpc-c/include/xmlrpc-c/string_int.h +++ b/libs/xmlrpc-c/include/xmlrpc-c/string_int.h @@ -13,22 +13,37 @@ extern "C" { #endif -extern const char * const xmlrpc_strsol; +XMLRPC_DLLEXPORT +bool +xmlrpc_strnomem(const char * const string); +XMLRPC_DLLEXPORT +const char * +xmlrpc_strnomemval(void); + +XMLRPC_DLLEXPORT void xmlrpc_vasprintf(const char ** const retvalP, const char * const fmt, va_list varargs); -void GNU_PRINTF_ATTR(2,3) +XMLRPC_DLLEXPORT +void XMLRPC_PRINTF_ATTR(2,3) xmlrpc_asprintf(const char ** const retvalP, const char * const fmt, ...); +XMLRPC_DLLEXPORT const char * -xmlrpc_strdupnull(const char * const string); +xmlrpc_strdupsol(const char * const string); +XMLRPC_DLLEXPORT void xmlrpc_strfree(const char * const string); +XMLRPC_DLLEXPORT +const char * +xmlrpc_strdupnull(const char * const string); + +XMLRPC_DLLEXPORT void xmlrpc_strfreenull(const char * const string); @@ -46,6 +61,11 @@ xmlrpc_memeq(const void * const a, return (memcmp(a, b, size) == 0); } +/* strcasecmp doesn't exist on some systems without _BSD_SOURCE, so + xmlrpc_strcaseeq() can't either. +*/ +#ifdef _BSD_SOURCE + static __inline__ bool xmlrpc_strcaseeq(const char * const a, const char * const b) { @@ -59,6 +79,7 @@ xmlrpc_strcaseeq(const char * const a, #error "This platform has no known case-independent string compare fn" #endif } +#endif static __inline__ bool xmlrpc_strneq(const char * const a, @@ -67,16 +88,42 @@ xmlrpc_strneq(const char * const a, return (strncmp(a, b, len) == 0); } +XMLRPC_DLLEXPORT const char * xmlrpc_makePrintable(const char * const input); +XMLRPC_DLLEXPORT const char * xmlrpc_makePrintable_lp(const char * const input, size_t const inputLength); +XMLRPC_DLLEXPORT const char * xmlrpc_makePrintableChar(char const input); +/*----------------------------------------------------------------*/ +/* Standard string functions with destination array 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))) +#define STRSCAT(A,B) \ + (strncat((A), (B), sizeof(A)-strlen(A)), *((A)+sizeof(A)-1) = '\0') + +/* We could do this, but it works only in GNU C +#define SSPRINTF(TARGET, REST...) \ + (snprintf(TARGET, sizeof(TARGET) , ## REST)) + +Or this, but it works only in C99 compilers, which leaves out MSVC +before 2005 and can't handle the zero variable argument case except +by an MSVC extension: + +#define SSPRINTF(TARGET, ...) \ + (snprintf(TARGET, sizeof(TARGET) , __VA_ARGS__)) + +*/ + #ifdef __cplusplus } #endif diff --git a/libs/xmlrpc-c/include/xmlrpc-c/string_number.h b/libs/xmlrpc-c/include/xmlrpc-c/string_number.h new file mode 100644 index 0000000..570a192 --- /dev/null +++ b/libs/xmlrpc-c/include/xmlrpc-c/string_number.h @@ -0,0 +1,21 @@ +#ifndef STRING_NUMBER_H_INCLUDED +#define STRING_NUMBER_H_INCLUDED + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +XMLRPC_DLLEXPORT +void +xmlrpc_parse_int64(xmlrpc_env * const envP, + const char * const str, + xmlrpc_int64 * const i64P); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libs/xmlrpc-c/include/xmlrpc-c/time_int.h b/libs/xmlrpc-c/include/xmlrpc-c/time_int.h index 4db4537..705f2c8 100644 --- a/libs/xmlrpc-c/include/xmlrpc-c/time_int.h +++ b/libs/xmlrpc-c/include/xmlrpc-c/time_int.h @@ -16,18 +16,22 @@ } xmlrpc_timespec; #endif +XMLRPC_DLLEXPORT void xmlrpc_gettimeofday(xmlrpc_timespec * const todP); +XMLRPC_DLLEXPORT void xmlrpc_timegm(const struct tm * const brokenTime, time_t * const timeValueP, const char ** const errorP); +XMLRPC_DLLEXPORT void xmlrpc_localtime(time_t const datetime, struct tm * const tmP); +XMLRPC_DLLEXPORT void xmlrpc_gmtime(time_t const datetime, struct tm * const resultP); diff --git a/libs/xmlrpc-c/include/xmlrpc-c/timeout.hpp b/libs/xmlrpc-c/include/xmlrpc-c/timeout.hpp index ef347e5..1da4a2f 100644 --- a/libs/xmlrpc-c/include/xmlrpc-c/timeout.hpp +++ b/libs/xmlrpc-c/include/xmlrpc-c/timeout.hpp @@ -1,13 +1,16 @@ #ifndef XMLRPC_TIMEOUT_H_INCLUDED #define XMLRPC_TIMEOUT_H_INCLUDED +#include + namespace xmlrpc_c { -struct timeout { +struct XMLRPC_DLLEXPORT timeout { timeout() : finite(false) {} - timeout(unsigned int const duration) : duration(duration) {} + timeout(unsigned int const duration) : + finite(true), duration(duration) {} // 'duration' is the timeout time in milliseconds bool finite; diff --git a/libs/xmlrpc-c/include/xmlrpc-c/transport.h b/libs/xmlrpc-c/include/xmlrpc-c/transport.h index 13d901f..be53e18 100644 --- a/libs/xmlrpc-c/include/xmlrpc-c/transport.h +++ b/libs/xmlrpc-c/include/xmlrpc-c/transport.h @@ -38,12 +38,17 @@ typedef void (*xmlrpc_transport_asynch_complete)( xmlrpc_mem_block * const responseXmlP, xmlrpc_env const env); +typedef void (*xmlrpc_transport_progress)( + struct xmlrpc_call_info * const callInfoP, + struct xmlrpc_progress_data const data); + typedef void (*xmlrpc_transport_send_request)( xmlrpc_env * const envP, struct xmlrpc_client_transport * const clientTransportP, const xmlrpc_server_info * const serverP, xmlrpc_mem_block * const xmlP, xmlrpc_transport_asynch_complete complete, + xmlrpc_transport_progress progress, struct xmlrpc_call_info * const callInfoP); typedef void (*xmlrpc_transport_call)( diff --git a/libs/xmlrpc-c/include/xmlrpc-c/transport_int.h b/libs/xmlrpc-c/include/xmlrpc-c/transport_int.h deleted file mode 100644 index 80b92ca..0000000 --- a/libs/xmlrpc-c/include/xmlrpc-c/transport_int.h +++ /dev/null @@ -1,42 +0,0 @@ -/* Copyright information is at the end of the file */ -#ifndef XMLRPC_TRANSPORT_INT_H_INCLUDED -#define XMLRPC_TRANSPORT_INT_H_INCLUDED - -#ifdef __cplusplus -extern "C" { -#endif - -#include "pthreadx.h" /* For threading helpers. */ - -/*========================================================================= -** Transport Helper Functions and declarations. -**========================================================================= -*/ -typedef struct _running_thread_info -{ - struct _running_thread_info * Next; - struct _running_thread_info * Last; - - pthread_t _thread; -} running_thread_info; - - -/* list of running Async callback functions. */ -typedef struct _running_thread_list -{ - running_thread_info * AsyncThreadHead; - running_thread_info * AsyncThreadTail; -} running_thread_list; - -/* MRB-WARNING: Only call when you have successfully -** acquired the Lock/Unlock mutex! */ -void register_asynch_thread (running_thread_list *list, pthread_t *thread); - -/* MRB-WARNING: Only call when you have successfully -** acquired the Lock/Unlock mutex! */ -void unregister_asynch_thread (running_thread_list *list, pthread_t *thread); - - -#ifdef __cplusplus -} -#endif diff --git a/libs/xmlrpc-c/include/xmlrpc-c/util.h b/libs/xmlrpc-c/include/xmlrpc-c/util.h index 2cad286..3a6404d 100644 --- a/libs/xmlrpc-c/include/xmlrpc-c/util.h +++ b/libs/xmlrpc-c/include/xmlrpc-c/util.h @@ -4,7 +4,10 @@ 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. + exists primarily because other Xmlrpc-c libraries use the utilities, + but the utilities are also documented for use by Xmlrpc-c users. + For use by Xmlrpc-c users, they are considered to be part of the + libxmlrpc library. libxmlrpc_util is a prerequisite of libxmlrpc. By Bryan Henderson, San Jose, CA 05.09.21. @@ -18,7 +21,7 @@ #include #include /* Defines XMLRPC_HAVE_WCHAR */ -#include /* for GNU_PRINTF_ATTR */ +#include /* for XMLRPC_PRINTF_ATTR */ #if XMLRPC_HAVE_WCHAR #include @@ -28,7 +31,6 @@ extern "C" { #endif - /*========================================================================= ** C struct size computations **=======================================================================*/ @@ -40,7 +42,7 @@ extern "C" { */ #define _XMLRPC_STRUCT_MEMBER_OFFSET(TYPE, MBRNAME) \ - ((unsigned long)(char*)&((TYPE *)0)->MBRNAME) + ((size_t)(char*)&((TYPE *)0)->MBRNAME) #define _XMLRPC_STRUCT_MEMBER_SIZE(TYPE, MBRNAME) \ sizeof(((TYPE *)0)->MBRNAME) #define XMLRPC_STRUCTSIZE(TYPE, MBRNAME) \ @@ -71,6 +73,7 @@ extern "C" { #define XMLRPC_ASSERT(cond) while (0) {} #endif +XMLRPC_DLLEXPORT void xmlrpc_assertion_failed(const char * const fileName, int const lineNumber); @@ -124,38 +127,44 @@ typedef struct _xmlrpc_env { /* Initialize and destroy the contents of the provided xmlrpc_env object. ** These functions will never fail. */ +XMLRPC_DLLEXPORT void xmlrpc_env_init (xmlrpc_env* env); +XMLRPC_DLLEXPORT 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. */ +XMLRPC_DLLEXPORT void xmlrpc_env_set_fault(xmlrpc_env * const env, int const faultCode, const char * const faultDescription); /* The same as the above, but using varargs */ +XMLRPC_DLLEXPORT void xmlrpc_set_fault_formatted_v(xmlrpc_env * const envP, int const code, const char * const format, - va_list const args); + va_list args); /* The same as the above, but using a printf-style format string. */ +XMLRPC_DLLEXPORT void xmlrpc_env_set_fault_formatted(xmlrpc_env * const envP, int const code, const char * const format, - ...) GNU_PRINTF_ATTR(3,4); + ...) XMLRPC_PRINTF_ATTR(3,4); /* This one infers XMLRPC_INTERNAL_ERROR and has a shorter name. So a call takes up less source code space. */ +XMLRPC_DLLEXPORT void xmlrpc_faultf(xmlrpc_env * const envP, const char * const format, - ...) GNU_PRINTF_ATTR(2,3); + ...) XMLRPC_PRINTF_ATTR(2,3); /* A simple debugging assertion. */ #define XMLRPC_ASSERT_ENV_OK(envP) \ @@ -223,32 +232,40 @@ typedef struct _xmlrpc_mem_block { } xmlrpc_mem_block; /* Allocate a new xmlrpc_mem_block. */ +XMLRPC_DLLEXPORT 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. */ +XMLRPC_DLLEXPORT void xmlrpc_mem_block_free (xmlrpc_mem_block* const block); /* Initialize the contents of the provided xmlrpc_mem_block. */ +XMLRPC_DLLEXPORT 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. */ +XMLRPC_DLLEXPORT void xmlrpc_mem_block_clean (xmlrpc_mem_block* const block); /* Get the size and contents of the xmlrpc_mem_block. */ +XMLRPC_DLLEXPORT size_t xmlrpc_mem_block_size(const xmlrpc_mem_block * const block); +XMLRPC_DLLEXPORT void * xmlrpc_mem_block_contents(const xmlrpc_mem_block * const block); /* Resize an xmlrpc_mem_block, preserving as much of the contents as ** possible. */ +XMLRPC_DLLEXPORT 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. */ +XMLRPC_DLLEXPORT void xmlrpc_mem_block_append (xmlrpc_env* const env, xmlrpc_mem_block* const block, const void * const data, size_t const len); @@ -295,12 +312,14 @@ void xmlrpc_mem_block_append ** UTF-8 Encoding and Decoding **=======================================================================*/ +XMLRPC_DLLEXPORT void xmlrpc_validate_utf8(xmlrpc_env * const envP, const char * const utf8Data, size_t const utf8Len); /* Decode a UTF-8 string. */ +XMLRPC_DLLEXPORT xmlrpc_mem_block * xmlrpc_utf8_to_wcs(xmlrpc_env * const envP, const char * const utf8_data, @@ -309,15 +328,18 @@ xmlrpc_utf8_to_wcs(xmlrpc_env * const envP, /* Encode a UTF-8 string. */ #if XMLRPC_HAVE_WCHAR +XMLRPC_DLLEXPORT xmlrpc_mem_block * xmlrpc_wcs_to_utf8(xmlrpc_env * const envP, const wchar_t * const wcsData, size_t const wcsLen); #endif +XMLRPC_DLLEXPORT void xmlrpc_force_to_utf8(char * const buffer); +XMLRPC_DLLEXPORT void xmlrpc_force_to_xml_chars(char * const buffer); diff --git a/libs/xmlrpc-c/include/xmlrpc-c/util_int.h b/libs/xmlrpc-c/include/xmlrpc-c/util_int.h index 8dbc11c..db5c5e9 100644 --- a/libs/xmlrpc-c/include/xmlrpc-c/util_int.h +++ b/libs/xmlrpc-c/include/xmlrpc-c/util_int.h @@ -1,14 +1,19 @@ #ifndef XMLRPC_C_UTIL_INT_H_INCLUDED #define XMLRPC_C_UTIL_INT_H_INCLUDED +/* This file contains facilities for use by Xmlrpc-c code, but not intended + to be included in a user compilation. + + Names in here might conflict with other names in a user's compilation + if included in a user compilation. + + The facilities may change in future releases. +*/ + #include "util.h" -#ifndef MIN #define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif -#ifndef MAX #define MAX(a,b) ((a) > (b) ? (a) : (b)) -#endif /* When we deallocate a pointer in a struct, we often replace it with ** this and throw in a few assertions here and there. */ diff --git a/libs/xmlrpc-c/include/xmlrpc-c/xml.hpp b/libs/xmlrpc-c/include/xmlrpc-c/xml.hpp index a77731f..9e6ca90 100644 --- a/libs/xmlrpc-c/include/xmlrpc-c/xml.hpp +++ b/libs/xmlrpc-c/include/xmlrpc-c/xml.hpp @@ -2,31 +2,53 @@ #define XML_HPP_INCLUDED #include +#include #include namespace xmlrpc_c { namespace xml { +XMLRPC_DLLEXPORT void generateCall(std::string const& methodName, xmlrpc_c::paramList const& paramList, std::string * const callXmlP); +XMLRPC_DLLEXPORT void generateCall(std::string const& methodName, xmlrpc_c::paramList const& paramList, xmlrpc_dialect const dialect, std::string * const callXmlP); +XMLRPC_DLLEXPORT +void +parseCall(std::string const& callXml, + std::string * const methodNameP, + xmlrpc_c::paramList * const paramListP); + +XMLRPC_DLLEXPORT +void +generateResponse(xmlrpc_c::rpcOutcome const& outcome, + xmlrpc_dialect const dialect, + std::string * const respXmlP); + +XMLRPC_DLLEXPORT +void +generateResponse(xmlrpc_c::rpcOutcome const& outcome, + std::string * const respXmlP); + +XMLRPC_DLLEXPORT void parseSuccessfulResponse(std::string const& responseXml, xmlrpc_c::value * const resultP); +XMLRPC_DLLEXPORT void parseResponse(std::string const& responseXml, xmlrpc_c::rpcOutcome * const outcomeP); - +XMLRPC_DLLEXPORT void trace(std::string const& label, std::string const& xml); diff --git a/libs/xmlrpc-c/irix-common.make b/libs/xmlrpc-c/irix-common.make deleted file mode 100644 index 9f4ac62..0000000 --- a/libs/xmlrpc-c/irix-common.make +++ /dev/null @@ -1,31 +0,0 @@ -# -*-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)=%) diff --git a/libs/xmlrpc-c/irix-common.mk b/libs/xmlrpc-c/irix-common.mk new file mode 100644 index 0000000..b0c936e --- /dev/null +++ b/libs/xmlrpc-c/irix-common.mk @@ -0,0 +1,31 @@ +# -*-makefile-*- <-- an Emacs control + +# See unix-common.mk for an explanation of this file. This file is +# analogous to unix-common.mk, but is for an Irix system. + +SONAME = $(@:%.$(MAJ):%) + +SHLIB_CMD = $(CCLD) $(LADD) $(LDFLAGS_SHLIB) -o $@ $^ + +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)=%) diff --git a/libs/xmlrpc-c/lib/Makefile.depend b/libs/xmlrpc-c/lib/Makefile.depend deleted file mode 100644 index e69de29..0000000 diff --git a/libs/xmlrpc-c/lib/abyss/.cvsignore b/libs/xmlrpc-c/lib/abyss/.cvsignore deleted file mode 100644 index e69de29..0000000 diff --git a/libs/xmlrpc-c/lib/abyss/Makefile.depend b/libs/xmlrpc-c/lib/abyss/Makefile.depend deleted file mode 100644 index e69de29..0000000 diff --git a/libs/xmlrpc-c/lib/abyss/change.log b/libs/xmlrpc-c/lib/abyss/change.log deleted file mode 100644 index 2d32d1a..0000000 --- a/libs/xmlrpc-c/lib/abyss/change.log +++ /dev/null @@ -1,34 +0,0 @@ - Change log for the ABYSS Web Server - ----------------------------------- - -Version 0.3 (March 23,2000): ----------------------------- -* Handles conditional GET requests (by date) -* Conforms to all the MUSTs of the RFC2616 (newer version of the HTTP/1.1 protocol draft) -* New configuration options (such as pidfile for UNIX systems...) -* Handles HEAD and OPTIONS methods -* Many bug fixes -* Tested on Sun-OS 5.7 -* Second public release - -Version 0.2 beta (February 7,2000): ------------------------------------ -* Handles GET on static files -* Handles correctly range requests -* Conforms to 80% of the MUSTs of the RFC2068 (HTTP/1.1 protocol draft) -* Improved code portability (Win32 and UNIX platforms) -* Tested on Linux 2.2 and Win95/98 -* First public release - -Version 0.1 (January 2000): ---------------------------- -* Completely rewritten in C -* Speed improvement -* New memory allocation scheme (using pools) -* Never released - -Version 0.0 (January 2000): ---------------------------- -* Initial version -* Written in C++ -* Never released \ No newline at end of file diff --git a/libs/xmlrpc-c/lib/abyss/htdocs/index.htm b/libs/xmlrpc-c/lib/abyss/htdocs/index.htm deleted file mode 100644 index f0369a5..0000000 --- a/libs/xmlrpc-c/lib/abyss/htdocs/index.htm +++ /dev/null @@ -1,21 +0,0 @@ - - -ABYSS is working !!! - - -

Congratulations, ABYSS is working !!!

-
-

-ABYSS Web Server is working correctly on your system. You should now change this -page with yours. -
-Please include in your web pages (at least the first), the 'Powered by ABYSS' -banner to promote the use of ABYSS. -

-
-

-

-Copyright © 2000 Moez Mahfoudh. All rights reserved. - -

- diff --git a/libs/xmlrpc-c/lib/abyss/patch_notes.txt b/libs/xmlrpc-c/lib/abyss/patch_notes.txt deleted file mode 100644 index 8ca4f77..0000000 --- a/libs/xmlrpc-c/lib/abyss/patch_notes.txt +++ /dev/null @@ -1,114 +0,0 @@ -Notes about the Abyss Patch -- By: Rosimildo da Silva, Jan 31, 2001. -------------------------------------------------------------------- - -This file contains some notes about the changes made to the -Abyss source tree. The changes were required to fix a few -bugs, and port the base code to compile under CygWin, -and Borland C++ free compiler. The free compiler for -Win32 from Borland can be downloaded from here: - - http://www.borland.com/bcppbuilder/freecompiler/ - - -What is new: - - + Package should compile out of the box under CygWin - - + Added makefiles and changes to use Borland C++ compiler -under WIN32 as well as VC++ 6.0 - - + Fix Abyss.dsp to use the proper thread safe libraries, -and updated to VC++ 6.0 - - + Fixed thread leaks ( handles ) - - - -Applying the patch to Abyss-0.3.tar.gz --------------------------------------- - - + get archive from here: - http://abyss.linuxave.net/abyss-0.3.tar.gz -WARNING: this site seems to be dead for the last two months. - - + cd /work ( any dir ) - tar xzvf abyss-0.3.tar.gz - cd abyss - patch -p1 - ( BCC_PATH=d:\bcb5 ) - - make -f makefile.bcc32 - - c) VC++ 6.0 - cd abyss\src - msdev Abyss.dsp - ( Or just open the workspace with Visual Studio, and you know - the drill ). -NOTE: Under Cygwin, after I apply the patch, Visual Studio was unable to -recognize the workspace. ??? - - -List of changes done to the ABYSS http server: ( ChangesLog ) ----------------------------------------------- - - + changed _WIN32 to ABYSS_WIN32. THis solve the problem that the -macro _WIN32 is defined under CygWin. CygWin has a unix like -api ( _UNIX ), so the macro _UNIX should be defined then. -Under CygWin we would have _UNIX and _WIN32 defined at the same -time. - - - + Theead API -- Added two extra functions: ThreadExit() and -ThreadClose(). These allows the resources of the threads to be -released when the thread has complete its duty serving the -request. - - + Added extra flag to TConn structure to make possible the -management of the worker threads by the server. - - - + Changed allocation of TConn array from stack to heap. This -would cause problems on certain system ( specially embedded systems ), -where the stack sizes arr not that large. - - + Changed ServerRun to free thread resources when the connection -for the thread is closed. - - + Changed main.c to make the sginal registration conforming with -the usage of the _FORK option. - - + Change ThreadCreate to be able to specify the "stack size" of the -worker's threads ( pthread ). Defined lable for it. - - - + Added flag _NO_USERS to disable check for users and groups. -This is useful for embedded systems where no users are available. - - + Updated VC++ workspace to version 6.0 - - - + Changed the creation of the thread under WIN32 to use a RTL -function ( _beginthreadex ), as recommend by MS, instead of using -the naked WIN32 API. - --- -Rosimildo da Silva rdasilva@connectel.com -ConnectTel, Inc. Austin, TX -- USA -Phone : 512-338-1111 Fax : 512-918-0449 -Company Page: http://www.connecttel.com -Home Page: http://members.nbci.com/rosimildo/ diff --git a/libs/xmlrpc-c/lib/abyss/readme.txt b/libs/xmlrpc-c/lib/abyss/readme.txt deleted file mode 100644 index c42ca1f..0000000 --- a/libs/xmlrpc-c/lib/abyss/readme.txt +++ /dev/null @@ -1,160 +0,0 @@ - - - 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 - -Configuration: --------------- - -Edit the conf/abyss.conf file and change the values of the available -options. - -Bugs: ------ - -Please email bug reports to mmoez@bigfoot.com - -To do: ------- - - * CGI/1.1 support - * Web based configuration/administration - * Speed improvement - * File caching system - * Throttling - * PUT method handling - * ... - -License: --------- - -ABYSS Web Server is licensed under a modified BSD type license: - - Copyright (C) 2000 Moez Mahfoudh. All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - * Redistributions of source code must retain the above - copyright notice, this list of conditions and the following - disclaimer. - * 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. - * 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 ``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 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. diff --git a/libs/xmlrpc-c/lib/abyss/src/.cvsignore b/libs/xmlrpc-c/lib/abyss/src/.cvsignore deleted file mode 100644 index e69de29..0000000 diff --git a/libs/xmlrpc-c/lib/abyss/src/Abyss.dsp b/libs/xmlrpc-c/lib/abyss/src/Abyss.dsp deleted file mode 100644 index c989392..0000000 --- a/libs/xmlrpc-c/lib/abyss/src/Abyss.dsp +++ /dev/null @@ -1,136 +0,0 @@ -# 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) Console Application" 0x0103 - -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) Console Application") -!MESSAGE "Abyss - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -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 "../bin" -# PROP Intermediate_Dir "objs" -# 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 "../../../" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "ABYSS_WIN32" /YX /FD /c -# ADD BASE RSC /l 0x40c /d "NDEBUG" -# ADD RSC /l 0x40c /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 wsock32.lib /nologo /subsystem:console /machine:I386 - -!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 "../bin" -# PROP Intermediate_Dir "objs" -# 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 /c -# ADD CPP /nologo /MT /W3 /Gm /GX /ZI /Od /I "../../../" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "ABYSS_WIN32" /YX /FD /c -# ADD BASE RSC /l 0x40c /d "_DEBUG" -# ADD RSC /l 0x40c /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 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib wsock32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept - -!ENDIF - -# Begin Target - -# Name "Abyss - Win32 Release" -# Name "Abyss - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "c" -# Begin Source File - -SOURCE=.\conf.c -# End Source File -# Begin Source File - -SOURCE=.\conn.c -# End Source File -# Begin Source File - -SOURCE=.\data.c -# End Source File -# Begin Source File - -SOURCE=.\file.c -# End Source File -# Begin Source File - -SOURCE=.\http.c -# End Source File -# Begin Source File - -SOURCE=.\main.c -# End Source File -# Begin Source File - -SOURCE=.\server.c -# End Source File -# Begin Source File - -SOURCE=.\socket.c -# End Source File -# Begin Source File - -SOURCE=.\thread.c -# End Source File -# Begin Source File - -SOURCE=.\trace.c -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h" -# Begin Source File - -SOURCE=.\abyss.h -# End Source File -# End Group -# End Target -# End Project diff --git a/libs/xmlrpc-c/lib/abyss/src/Abyss.dsw b/libs/xmlrpc-c/lib/abyss/src/Abyss.dsw deleted file mode 100644 index 4e27c99..0000000 --- a/libs/xmlrpc-c/lib/abyss/src/Abyss.dsw +++ /dev/null @@ -1,29 +0,0 @@ -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> -{{{ -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### - diff --git a/libs/xmlrpc-c/lib/abyss/src/Makefile b/libs/xmlrpc-c/lib/abyss/src/Makefile index fc57122..b3f39ef 100644 --- a/libs/xmlrpc-c/lib/abyss/src/Makefile +++ b/libs/xmlrpc-c/lib/abyss/src/Makefile @@ -50,7 +50,7 @@ MAJ=3 include $(SRCDIR)/common.mk -CFLAGS = $(CFLAGS_COMMON) -D_UNIX $(CFLAGS_PERSONAL) $(CADD) +CFLAGS_LOCAL = -D_UNIX INCLUDES = -Iblddir -Isrcdir -Isrcdir/include -Isrcdir/lib/util/include @@ -59,27 +59,23 @@ ABYSS_SHLIB = $(call shlibfn,libxmlrpc_abyss) 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 - # 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_abyss.a $(TARGET_SHARED_LIBS) $(TARGET_SHARED_LE_LIBS) +all: libxmlrpc_abyss.a $(TARGET_SHARED_LIBRARIES) $(TARGET_SHARED_LE_LIBS) -# 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_LIBRARY_NAMES +$(ABYSS_SHLIB): $(TARGET_MODS:%=%.osh) \ + $(LIBXMLRPC_UTIL) +$(ABYSS_SHLIB): LIBOBJECTS = $(TARGET_MODS:%=%.osh) +$(ABYSS_SHLIB): LIBDEP = -L$(LIBXMLRPC_UTIL_DIR) -lxmlrpc_util +ifeq ($(ENABLE_ABYSS_THREADS),yes) + $(ABYSS_SHLIB): LIBDEP += -lpthread +endif # Rule for this is in common.mk, courtesy of TARGET_STATIC_LIBRARIES: @@ -94,7 +90,7 @@ libxmlrpc_abyss.a: LIBOBJECTS = $(TARGET_MODS:%=%.o) # Abyss library are in common.mk, courtesy of TARGET_MODS. -# Need this dependency for those who don't use Makefile.depend. +# Need this dependency for those who don't use depend.mk. # Without it, version.h doesn't get created. response.o response.osh handler.o handler.osh: version.h @@ -116,4 +112,4 @@ install: install-common .PHONY: dep dep: dep-common -include Makefile.depend +include depend.mk diff --git a/libs/xmlrpc-c/lib/abyss/src/Makefile.depend b/libs/xmlrpc-c/lib/abyss/src/Makefile.depend deleted file mode 100644 index e69de29..0000000 diff --git a/libs/xmlrpc-c/lib/abyss/src/channel.c b/libs/xmlrpc-c/lib/abyss/src/channel.c index af81c62..5044e23 100644 --- a/libs/xmlrpc-c/lib/abyss/src/channel.c +++ b/libs/xmlrpc-c/lib/abyss/src/channel.c @@ -13,6 +13,7 @@ #include #include "bool.h" +#include "int.h" #include "mallocvar.h" #include "xmlrpc-c/util_int.h" #include "xmlrpc-c/abyss.h" @@ -83,7 +84,7 @@ ChannelTerm(void) { functions that are particular to an implementation. */ -static uint const channelSignature = 0x06060B; +static unsigned int const channelSignature = 0x06060B; void ChannelCreate(const struct TChannelVtbl * const vtblP, diff --git a/libs/xmlrpc-c/lib/abyss/src/channel.h b/libs/xmlrpc-c/lib/abyss/src/channel.h index c5924bc..6e5ae7e 100644 --- a/libs/xmlrpc-c/lib/abyss/src/channel.h +++ b/libs/xmlrpc-c/lib/abyss/src/channel.h @@ -60,7 +60,7 @@ struct TChannelVtbl { }; struct _TChannel { - uint signature; + unsigned int 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 diff --git a/libs/xmlrpc-c/lib/abyss/src/chanswitch.c b/libs/xmlrpc-c/lib/abyss/src/chanswitch.c index b89e6de..c39e4c0 100644 --- a/libs/xmlrpc-c/lib/abyss/src/chanswitch.c +++ b/libs/xmlrpc-c/lib/abyss/src/chanswitch.c @@ -11,6 +11,7 @@ #include #include "bool.h" +#include "int.h" #include "mallocvar.h" #include "xmlrpc-c/util_int.h" #include "xmlrpc-c/abyss.h" @@ -81,7 +82,7 @@ ChanSwitchTerm(void) { functions that are particular to an implementation. */ -static uint const switchSignature = 0x06060A; +static unsigned int const switchSignature = 0x06060A; void ChanSwitchCreate(const struct TChanSwitchVtbl * const vtblP, diff --git a/libs/xmlrpc-c/lib/abyss/src/chanswitch.h b/libs/xmlrpc-c/lib/abyss/src/chanswitch.h index 4ff7949..c216f95 100644 --- a/libs/xmlrpc-c/lib/abyss/src/chanswitch.h +++ b/libs/xmlrpc-c/lib/abyss/src/chanswitch.h @@ -36,7 +36,7 @@ struct TChanSwitchVtbl { }; struct _TChanSwitch { - uint signature; + unsigned int 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 diff --git a/libs/xmlrpc-c/lib/abyss/src/conf.c b/libs/xmlrpc-c/lib/abyss/src/conf.c index 982615f..e0feff9 100644 --- a/libs/xmlrpc-c/lib/abyss/src/conf.c +++ b/libs/xmlrpc-c/lib/abyss/src/conf.c @@ -32,6 +32,9 @@ ** ******************************************************************************/ +#define _XOPEN_SOURCE 600 /* For strdup() */ +#define _BSD_SOURCE /* For xmlrpc_strcaseeq */ + #include #include #include @@ -96,10 +99,10 @@ ConfReadLine(TFile * const fileP, if (c == CR || c == LF) break; - *buffer = '\0'; + *z = '\0'; /* Discard comments */ - p = strchr(z, '#'); + p = strchr(buffer, '#'); if (p) *p = '\0'; diff --git a/libs/xmlrpc-c/lib/abyss/src/conn.c b/libs/xmlrpc-c/lib/abyss/src/conn.c index f76cc22..e6cd0b3 100644 --- a/libs/xmlrpc-c/lib/abyss/src/conn.c +++ b/libs/xmlrpc-c/lib/abyss/src/conn.c @@ -31,6 +31,8 @@ connJob(void * const userHandle) { /*---------------------------------------------------------------------------- This is the root function for a thread that processes a connection (performs HTTP transactions). + + We never return. We ultimately exit the thread. -----------------------------------------------------------------------------*/ TConn * const connectionP = userHandle; @@ -44,11 +46,21 @@ connJob(void * const userHandle) { after we exit. */ - //ThreadExit(0); + + /* Note that ThreadExit() runs a cleanup function, which in our + case is connDone(). + */ + ThreadExit(connectionP->threadP, 0); } +/* This is the maximum amount of stack that 'connJob' itself uses -- + does not count what user's connection job function uses. +*/ +#define CONNJOB_STACK 1024 + + static void connDone(TConn * const connectionP) { @@ -79,6 +91,7 @@ static void makeThread(TConn * const connectionP, enum abyss_foreback const foregroundBackground, bool const useSigchld, + size_t const jobStackSize, const char ** const errorP) { switch (foregroundBackground) { @@ -91,6 +104,7 @@ makeThread(TConn * const connectionP, connectionP->hasOwnThread = TRUE; ThreadCreate(&connectionP->threadP, connectionP, &connJob, &threadDone, useSigchld, + CONNJOB_STACK + jobStackSize, &error); if (error) { xmlrpc_asprintf(errorP, "Unable to create thread to " @@ -110,6 +124,7 @@ ConnCreate(TConn ** const connectionPP, TChannel * const channelP, void * const channelInfoP, TThreadProc * const job, + size_t const jobStackSize, TThreadDoneFn * const done, enum abyss_foreback const foregroundBackground, bool const useSigchld, @@ -150,7 +165,7 @@ ConnCreate(TConn ** const connectionPP, connectionP->server = serverP; connectionP->channelP = channelP; connectionP->channelInfoP = channelInfoP; - connectionP->buffer[0] = '\0'; + connectionP->buffer.b[0] = '\0'; connectionP->buffersize = 0; connectionP->bufferpos = 0; connectionP->finished = FALSE; @@ -160,7 +175,8 @@ ConnCreate(TConn ** const connectionPP, connectionP->outbytes = 0; connectionP->trace = getenv("ABYSS_TRACE_CONN"); - makeThread(connectionP, foregroundBackground, useSigchld, errorP); + makeThread(connectionP, foregroundBackground, useSigchld, + jobStackSize, errorP); } *connectionPP = connectionP; } @@ -185,6 +201,7 @@ ConnProcess(TConn * const connectionP) { /* There's a background thread to handle this connection. Set it running. */ + assert(connectionP->threadP); retval = ThreadRun(connectionP->threadP); } else { /* No background thread. We just handle it here while Caller waits. */ @@ -199,9 +216,11 @@ ConnProcess(TConn * const connectionP) { void ConnWaitAndRelease(TConn * const connectionP) { - if (connectionP->hasOwnThread) + + if (connectionP->hasOwnThread) { + assert(connectionP->threadP); ThreadWaitAndRelease(connectionP->threadP); - + } free(connectionP); } @@ -220,20 +239,31 @@ ConnReadInit(TConn * const connectionP) { if (connectionP->buffersize > connectionP->bufferpos) { connectionP->buffersize -= connectionP->bufferpos; - memmove(connectionP->buffer, - connectionP->buffer + connectionP->bufferpos, + memmove(connectionP->buffer.b, + connectionP->buffer.b + connectionP->bufferpos, connectionP->buffersize); connectionP->bufferpos = 0; } else connectionP->buffersize = connectionP->bufferpos = 0; - connectionP->buffer[connectionP->buffersize] = '\0'; + connectionP->buffer.b[connectionP->buffersize] = '\0'; connectionP->inbytes = connectionP->outbytes = 0; } +static void +traceReadTimeout(TConn * const connectionP, + uint32_t const timeout) { + + if (connectionP->trace) + fprintf(stderr, "TIMED OUT waiting over %u seconds " + "for data from client.\n", timeout); +} + + + static size_t nextLineSize(const char * const string, size_t const startPos, @@ -261,9 +291,11 @@ nextLineSize(const char * const string, static void -traceBuffer(const char * const label, - const char * const buffer, - unsigned int const size) { +traceBuffer(const char * const label, + const unsigned char * const buffer, + unsigned int const size) { + + const char * const buffer_t = (const char *)buffer; size_t cursor; /* Index into buffer[] */ @@ -272,9 +304,9 @@ traceBuffer(const char * const label, for (cursor = 0; cursor < size; ) { /* Print one line of buffer */ - size_t const lineSize = nextLineSize(buffer, cursor, size); + size_t const lineSize = nextLineSize(buffer_t, cursor, size); const char * const printableLine = - xmlrpc_makePrintable_lp(&buffer[cursor], lineSize); + xmlrpc_makePrintable_lp(&buffer_t[cursor], lineSize); fprintf(stderr, "%s\n", printableLine); @@ -288,12 +320,22 @@ traceBuffer(const char * const label, static void +traceBufferText(const char * const label, + const char * const buffer, + unsigned int const size) { + + traceBuffer(label, (const unsigned char *)buffer, size); +} + + + +static void traceChannelRead(TConn * const connectionP, unsigned int const size) { if (connectionP->trace) traceBuffer("READ FROM CHANNEL", - connectionP->buffer + connectionP->buffersize, size); + connectionP->buffer.b + connectionP->buffersize, size); } @@ -307,7 +349,7 @@ traceChannelWrite(TConn * const connectionP, if (connectionP->trace) { const char * const label = failed ? "FAILED TO WRITE TO CHANNEL" : "WROTE TO CHANNEL"; - traceBuffer(label, buffer, size); + traceBufferText(label, buffer, size); } } @@ -321,71 +363,136 @@ bufferSpace(TConn * const connectionP) { -bool -ConnRead(TConn * const connectionP, - uint32_t const timeout) { +static void +readFromChannel(TConn * const connectionP, + bool * const eofP, + const char ** const errorP) { /*---------------------------------------------------------------------------- - Read some stuff on connection *connectionP from the channel. - - Don't wait more than 'timeout' seconds for data to arrive. Fail if - nothing arrives within that time. + Read some data from the channel of Connection *connectionP. - 'timeout' must be before the end of time. + Iff there is none available to read, return *eofP == true. -----------------------------------------------------------------------------*/ - time_t const deadline = time(NULL) + timeout; + uint32_t bytesRead; + bool readError; - bool cantGetData; - bool gotData; + ChannelRead(connectionP->channelP, + connectionP->buffer.b + connectionP->buffersize, + bufferSpace(connectionP) - 1, + &bytesRead, &readError); - cantGetData = FALSE; - gotData = FALSE; - - while (!gotData && !cantGetData) { - int const timeLeft = (int)(deadline - time(NULL)); + if (readError) + xmlrpc_asprintf(errorP, "Error reading from channel"); + else { + *errorP = NULL; + if (bytesRead > 0) { + *eofP = FALSE; + traceChannelRead(connectionP, bytesRead); + connectionP->inbytes += bytesRead; + connectionP->buffersize += bytesRead; + connectionP->buffer.t[connectionP->buffersize] = '\0'; + } else + *eofP = TRUE; + } +} - if (timeLeft <= 0) - cantGetData = TRUE; - else { - bool const waitForRead = TRUE; - bool const waitForWrite = FALSE; - - bool readyForRead; - bool failed; + + +static void +dealWithReadTimeout(bool * const timedOutP, + bool const timedOut, + uint32_t const timeout, + const char ** const errorP) { + + if (timedOutP) + *timedOutP = timedOut; + else { + if (timedOut) + xmlrpc_asprintf(errorP, "Read from Abyss client " + "connection timed out after %u seconds " + "or was interrupted", + timeout); + } +} + + + +static void +dealWithReadEof(bool * const eofP, + bool const eof, + const char ** const errorP) { + + if (eofP) + *eofP = eof; + else { + if (eof) + xmlrpc_asprintf(errorP, "Read from Abyss client " + "connection failed because client closed the " + "connection"); + } +} + + + +void +ConnRead(TConn * const connectionP, + uint32_t const timeout, + bool * const eofP, + bool * const timedOutP, + const char ** const errorP) { +/*---------------------------------------------------------------------------- + Read some stuff on connection *connectionP from the channel. Read it into + the connection's buffer. + + Don't wait more than 'timeout' seconds for data to arrive. If no data has + arrived by then and 'timedOutP' is null, fail. If 'timedOut' is non-null, + return as *timedOutP whether 'timeout' seconds passed without any data + arriving. + + Also, stop waiting upon any interruption and treat it the same as a + timeout. An interruption is either a signal received (and caught) at + an appropriate time or a ChannelInterrupt() call before or during the + wait. + + If 'eofP' is non-null, return *eofP == true, without reading anything, iff + there will no more data forthcoming on the connection because client has + closed the connection. If 'eofP' is null, fail in that case. +-----------------------------------------------------------------------------*/ + uint32_t const timeoutMs = timeout * 1000; + + if (timeoutMs < timeout) + /* Arithmetic overflow */ + xmlrpc_asprintf(errorP, "Timeout value is too large"); + else { + bool const waitForRead = TRUE; + bool const waitForWrite = FALSE; + + bool readyForRead; + bool failed; - ChannelWait(connectionP->channelP, waitForRead, waitForWrite, - timeLeft * 1000, &readyForRead, NULL, &failed); + ChannelWait(connectionP->channelP, waitForRead, waitForWrite, + timeoutMs, &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; - } + if (failed) + xmlrpc_asprintf(errorP, + "Wait for stuff to arrive from client failed."); + else { + bool eof; + if (readyForRead) { + readFromChannel(connectionP, &eof, errorP); + } else { + /* Wait was interrupted, either by our requested timeout, + a (caught) signal, or a ChannelInterrupt(). + */ + traceReadTimeout(connectionP, timeout); + *errorP = NULL; + eof = FALSE; } + if (!*errorP) + dealWithReadTimeout(timedOutP, !readyForRead, timeout, errorP); + if (!*errorP) + dealWithReadEof(eofP, eof, errorP); } } - if (gotData) - return TRUE; - else - return FALSE; } @@ -429,12 +536,13 @@ ConnWriteFromFile(TConn * const connectionP, uint32_t waittime; bool success; uint32_t readChunkSize; + uint32_t ChunkSize = 4096 * 2; /* read buffer size */ if (rate > 0) { readChunkSize = MIN(buffersize, rate); /* One second's worth */ waittime = (1000 * buffersize) / rate; } else { - readChunkSize = buffersize; + readChunkSize = ChunkSize; waittime = 0; } @@ -443,30 +551,42 @@ ConnWriteFromFile(TConn * const connectionP, 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; + uint64_t bytesread = 0; + + int32_t bytesReadThisTime = 0; + char * chunk = (char *) buffer; /* the beginning */ + do { + + if ((bytesReadThisTime = FileRead(fileP, chunk, readChunkSize)) <= 0 ) + break; + + bytesread += bytesReadThisTime; + chunk += bytesReadThisTime; + + /* fix bug in ms ie as it doesn't render text/plain properly */ + /* if CRLFs are split between reassembled tcp packets, */ + /* ie "might" undeterministically render extra empty lines */ + /* if it ends in CR or LF, read an extra chunk until the buffer is full */ + /* or end of file is reached. You may still have bad luck, complaints go to MS) */ + +/* if (bytesReadThisTime == readChunkSize && chunk - (char *) buffer + readChunkSize < buffersize) { + * char * end = chunk - 1; + * if (*end == CR || *end == LF) { + * continue; + * } + * } + */ + if (!bytesReadThisTime || !ConnWrite(connectionP, buffer, chunk - (char *) buffer)) { + break; + } - assert(bytesToRead == bytesToRead64); /* readChunkSize is uint32 */ + chunk = (char *) buffer; /* a new beginning */ - bytesReadThisTime = FileRead(fileP, buffer, bytesToRead); - bytesread += bytesReadThisTime; - - if (bytesReadThisTime > 0) - ConnWrite(connectionP, buffer, bytesReadThisTime); - else - break; - - if (waittime > 0) + if (waittime > 0) xmlrpc_millisecond_sleep(waittime); - } + + } while (bytesReadThisTime == readChunkSize); + retval = (bytesread >= totalBytesToRead); } return retval; diff --git a/libs/xmlrpc-c/lib/abyss/src/conn.h b/libs/xmlrpc-c/lib/abyss/src/conn.h index 51eb169..d48103d 100644 --- a/libs/xmlrpc-c/lib/abyss/src/conn.h +++ b/libs/xmlrpc-c/lib/abyss/src/conn.h @@ -47,8 +47,15 @@ struct _TConn { */ const char * trace; TThreadProc * job; + /* The function to run, in a connection thread, to conduct business + on the connection. It reads stuff and writes stuff and, when it + is done with the connection, exits. + */ TThreadDoneFn * done; - char buffer[BUFFER_SIZE]; + union { + unsigned char b[BUFFER_SIZE]; /* Just bytes */ + char t[BUFFER_SIZE]; /* Taken as text */ + } buffer; }; typedef struct _TConn TConn; @@ -63,6 +70,7 @@ ConnCreate(TConn ** const connectionPP, TChannel * const channelP, void * const channelInfoP, TThreadProc * const job, + size_t const jobStackSize, TThreadDoneFn * const done, enum abyss_foreback const foregroundBackground, bool const useSigchld, @@ -82,9 +90,12 @@ ConnWrite(TConn * const connectionP, const void * const buffer, uint32_t const size); -bool -ConnRead(TConn * const c, - uint32_t const timems); +void +ConnRead(TConn * const connectionP, + uint32_t const timeout, + bool * const eofP, + bool * const timedOutP, + const char ** const errorP); void ConnReadInit(TConn * const connectionP); diff --git a/libs/xmlrpc-c/lib/abyss/src/data.c b/libs/xmlrpc-c/lib/abyss/src/data.c index c698505..f81f834 100644 --- a/libs/xmlrpc-c/lib/abyss/src/data.c +++ b/libs/xmlrpc-c/lib/abyss/src/data.c @@ -32,6 +32,8 @@ ** *******************************************************************************/ +#define _XOPEN_SOURCE 600 /* Make sure strdup() is in */ + #include #include #include @@ -198,20 +200,20 @@ ListAddFromString(TList * const list, bool -ListFindString(TList * const sl, +ListFindString(TList * const listP, const char * const str, uint16_t * const indexP) { - uint16_t i; + if (listP->item && str) { + unsigned int i; - if (sl->item && str) - for (i=0;isize;i++) - if (strcmp(str,(char *)(sl->item[i]))==0) - { - *indexP=i; + for (i = 0; i < listP->size; ++i) { + if (xmlrpc_streq(str, (char *)(listP->item[i]))) { + *indexP = i; return TRUE; - }; - + } + } + } return FALSE; } @@ -435,7 +437,7 @@ TableFindIndex(TTable * const t, { for (i=*index;isize;i++) if (hash==t->item[i].hash) - if (strcmp(t->item[i].name,name)==0) + if (xmlrpc_streq(t->item[i].name,name)) { *index=i; return TRUE; diff --git a/libs/xmlrpc-c/lib/abyss/src/file.c b/libs/xmlrpc-c/lib/abyss/src/file.c index b428c0c..4417f05 100644 --- a/libs/xmlrpc-c/lib/abyss/src/file.c +++ b/libs/xmlrpc-c/lib/abyss/src/file.c @@ -111,6 +111,7 @@ createFileImage(TFile ** const filePP, int rc; if (createFile) + /* Unix prefers S_IWUSR, but some Windows knows only S_IWRITE */ rc = open(name, attrib | O_CREAT, S_IWRITE | S_IREAD); else rc = open(name, attrib); diff --git a/libs/xmlrpc-c/lib/abyss/src/handler.c b/libs/xmlrpc-c/lib/abyss/src/handler.c index 9f5a7e6..01a2550 100644 --- a/libs/xmlrpc-c/lib/abyss/src/handler.c +++ b/libs/xmlrpc-c/lib/abyss/src/handler.c @@ -5,6 +5,9 @@ Copyright information is at end of file =============================================================================*/ + +#define _XOPEN_SOURCE 600 /* Make sure strdup() is in */ + #include #include #include @@ -458,15 +461,15 @@ handleDirectory(TSession * const sessionP, 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); + if (ResponseWriteStart(sessionP)) { + + if (sessionP->requestInfo.method!=m_head) + sendDirectoryDocument(&list, ascending, sort, text, + sessionP->requestInfo.uri, mimeTypeP, + sessionP); + HTTPWriteEndChunk(sessionP); + } ListFree(&list); } PoolFree(&pool); @@ -504,20 +507,20 @@ sendBody(TSession * const sessionP, /*---------------------------------------------------------------------------- 'start0' and 'end0' are meaningful only if the session has ranges. -----------------------------------------------------------------------------*/ - char buffer[4096]; + char buffer[4096*8]; if (sessionP->ranges.size == 0) - ConnWriteFromFile(sessionP->conn, fileP, 0, filesize - 1, + ConnWriteFromFile(sessionP->connP, fileP, 0, filesize - 1, buffer, sizeof(buffer), 0); else if (sessionP->ranges.size == 1) - ConnWriteFromFile(sessionP->conn, fileP, start0, end0, + ConnWriteFromFile(sessionP->connP, 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); + ConnWrite(sessionP->connP, "--", 2); + ConnWrite(sessionP->connP, BOUNDARY, strlen(BOUNDARY)); + ConnWrite(sessionP->connP, CRLF, 2); if (i < sessionP->ranges.size) { uint64_t start; @@ -534,12 +537,12 @@ sendBody(TSession * const sessionP, composeEntityHeader(&entityHeader, mediatype, start, end, filesize); - ConnWrite(sessionP->conn, + ConnWrite(sessionP->connP, entityHeader, strlen(entityHeader)); xmlrpc_strfree(entityHeader); - ConnWriteFromFile(sessionP->conn, fileP, start, end, + ConnWriteFromFile(sessionP->connP, fileP, start, end, buffer, sizeof(buffer), 0); } } @@ -559,8 +562,8 @@ sendFileAsResponse(TSession * const sessionP, 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 */ + uint64_t start = 0; /* Defined only if session has one range */ + uint64_t end = 0; /* Defined only if session has one range */ switch (sessionP->ranges.size) { case 0: @@ -601,10 +604,9 @@ sendFileAsResponse(TSession * const sessionP, addLastModifiedHeader(sessionP, fileModTime); - ResponseWriteStart(sessionP); - - if (sessionP->requestInfo.method != m_head) - sendBody(sessionP, fileP, filesize, mediatype, start, end); + if (ResponseWriteStart(sessionP)) + if (sessionP->requestInfo.method != m_head) + sendBody(sessionP, fileP, filesize, mediatype, start, end); } @@ -749,6 +751,9 @@ HandlerDefaultBuiltin(TSession * const sessionP) { +size_t const HandlerDefaultBuiltinStack = 1024; + + /****************************************************************************** ** ** server.c diff --git a/libs/xmlrpc-c/lib/abyss/src/handler.h b/libs/xmlrpc-c/lib/abyss/src/handler.h index 4f9dc95..a8f2f3e 100644 --- a/libs/xmlrpc-c/lib/abyss/src/handler.h +++ b/libs/xmlrpc-c/lib/abyss/src/handler.h @@ -28,4 +28,6 @@ HandlerAddDefaultFN(BIHandler * const handlerP, abyss_bool HandlerDefaultBuiltin(TSession * const sessionP); +extern size_t const HandlerDefaultBuiltinStack; + #endif diff --git a/libs/xmlrpc-c/lib/abyss/src/http.c b/libs/xmlrpc-c/lib/abyss/src/http.c index 1e55bc8..4f9ef10 100644 --- a/libs/xmlrpc-c/lib/abyss/src/http.c +++ b/libs/xmlrpc-c/lib/abyss/src/http.c @@ -1,5 +1,8 @@ /* Copyright information is at the end of the file */ +#define _XOPEN_SOURCE 600 /* For strdup() */ +#define _BSD_SOURCE /* For xmlrpc_strcaseeq() */ + #include #include #include @@ -13,6 +16,7 @@ #include "mallocvar.h" #include "xmlrpc-c/util.h" #include "xmlrpc-c/string_int.h" +#include "xmlrpc-c/base64_int.h" #include "xmlrpc-c/abyss.h" #include "server.h" @@ -43,8 +47,8 @@ initRequestInfo(TRequestInfo * const requestInfoP, 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. + controlled by the header, use the defaults -- I.e. the value that + applies if the request contains no applicable header field. -----------------------------------------------------------------------------*/ XMLRPC_ASSERT_PTR_OK(requestLine); XMLRPC_ASSERT_PTR_OK(path); @@ -79,6 +83,9 @@ freeRequestInfo(TRequestInfo * const requestInfoP) { xmlrpc_strfree(requestInfoP->uri); xmlrpc_strfree(requestInfoP->requestline); + + xmlrpc_strfree(requestInfoP->query); + } @@ -91,7 +98,7 @@ RequestInit(TSession * const sessionP, time(&sessionP->date); - sessionP->conn = connectionP; + sessionP->connP = connectionP; sessionP->responseStarted = FALSE; @@ -102,8 +109,8 @@ RequestInit(TSession * const sessionP, ListInit(&sessionP->cookies); ListInit(&sessionP->ranges); - TableInit(&sessionP->request_headers); - TableInit(&sessionP->response_headers); + TableInit(&sessionP->requestHeaderFields); + TableInit(&sessionP->responseHeaderFields); sessionP->status = 0; /* No status from handler yet */ @@ -120,8 +127,8 @@ RequestFree(TSession * const sessionP) { ListFree(&sessionP->cookies); ListFree(&sessionP->ranges); - TableFree(&sessionP->request_headers); - TableFree(&sessionP->response_headers); + TableFree(&sessionP->requestHeaderFields); + TableFree(&sessionP->responseHeaderFields); StringFree(&(sessionP->header)); } @@ -137,7 +144,7 @@ firstLfPos(TConn * const connectionP, If there is no LF in the buffer at or after 'lineStart', return NULL. -----------------------------------------------------------------------------*/ const char * const bufferEnd = - connectionP->buffer + connectionP->buffersize; + connectionP->buffer.t + connectionP->buffersize; char * p; @@ -168,20 +175,25 @@ getLineInBuffer(TConn * const connectionP, bool error; char * lfPos; - assert(lineStart <= connectionP->buffer + connectionP->buffersize); + assert(lineStart <= connectionP->buffer.t + connectionP->buffersize); error = FALSE; /* initial value */ lfPos = NULL; /* initial value */ while (!error && !lfPos) { int const timeLeft = (int)(deadline - time(NULL)); - if (timeLeft <= 0) error = TRUE; else { lfPos = firstLfPos(connectionP, lineStart); - if (!lfPos) - error = !ConnRead(connectionP, timeLeft); + if (!lfPos) { + const char * readError; + ConnRead(connectionP, timeLeft, NULL, NULL, &readError); + if (readError) { + error = TRUE; + xmlrpc_strfree(readError); + } + } } } *errorP = error; @@ -228,36 +240,36 @@ convertLineEnd(char * const lineStart, static void -getRestOfHeader(TConn * const connectionP, - char * const lineEnd, - time_t const deadline, - const char ** const headerEndP, - bool * const errorP) { +getRestOfField(TConn * const connectionP, + char * const lineEnd, + time_t const deadline, + const char ** const fieldEndP, + 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 + its current read position) the first line of an HTTP header field, 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; + Some or all of the rest of the field 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. + We return the location of the end of the whole field as *headerEndP. + We do not remove the field from the buffer, but we do modify the + buffer so as to join the multiple lines of the field into a single + line, and to NUL-terminate the field. -----------------------------------------------------------------------------*/ - char * const headerStart = connectionP->buffer + connectionP->bufferpos; + char * const fieldStart = connectionP->buffer.t + connectionP->bufferpos; - char * headerEnd; - /* End of the header lines we've seen at so far */ - bool gotWholeHeader; + char * fieldEnd; + /* End of the field lines we've seen at so far */ + bool gotWholeField; bool error; - headerEnd = lineEnd; /* initial value - end of 1st line */ + fieldEnd = lineEnd; /* initial value - end of 1st line */ - for (gotWholeHeader = FALSE, error = FALSE; - !gotWholeHeader && !error;) { + for (gotWholeField = FALSE, error = FALSE; + !gotWholeField && !error;) { char * nextLineEnd; @@ -265,51 +277,51 @@ getRestOfHeader(TConn * const connectionP, 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, + getLineInBuffer(connectionP, fieldEnd, deadline, &nextLineEnd, &error); if (!error) { - if (isContinuationLine(headerEnd)) { + if (isContinuationLine(fieldEnd)) { /* Join previous line to this one */ - convertLineEnd(headerEnd, headerStart, ' '); + convertLineEnd(fieldEnd, fieldStart, ' '); /* Add this line to the header */ - headerEnd = nextLineEnd; + fieldEnd = nextLineEnd; } else { - gotWholeHeader = TRUE; - *headerEndP = headerEnd; + gotWholeField = TRUE; - /* NUL-terminate the whole header */ - convertLineEnd(headerEnd, headerStart, '\0'); + /* NUL-terminate the whole field */ + convertLineEnd(fieldEnd, fieldStart, '\0'); } } } - *errorP = error; + *fieldEndP = fieldEnd; + *errorP = error; } static void -readHeader(TConn * const connectionP, - time_t const deadline, - bool * const endOfHeadersP, - char ** const headerP, - bool * const errorP) { +readField(TConn * const connectionP, + time_t const deadline, + bool * const endOfHeaderP, + char ** const fieldP, + bool * const errorP) { /*---------------------------------------------------------------------------- - Read an HTTP header, or the end of headers empty line, on connection + Read an HTTP header field, or the end of header empty line, on connection *connectionP. - An HTTP header is basically a line, except that if a line starts + An HTTP header field 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. + The first line of an HTTP header field is never empty; an empty line + signals the end of the HTTP header 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 + line delimiter at the end of the field or EOH mark; we may read + much more. But we leave everything after the field or EOH (and its line delimiter) in the internal buffer, with the buffer pointer pointing to it. @@ -317,12 +329,12 @@ readHeader(TConn * const connectionP, 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 + We return as *fieldP the next field 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. + the connection's internal buffer. Iff there is no next field, we + return *endOfHeaderP == true and nothing meaningful as *fieldP. -----------------------------------------------------------------------------*/ - char * const bufferStart = connectionP->buffer + connectionP->bufferpos; + char * const bufferStart = connectionP->buffer.t + connectionP->bufferpos; bool error; char * lineEnd; @@ -334,26 +346,26 @@ readHeader(TConn * const connectionP, error = TRUE; else if (isEmptyLine(bufferStart)) { /* Consume the EOH mark from the buffer */ - connectionP->bufferpos = lineEnd - connectionP->buffer; - *endOfHeadersP = TRUE; + connectionP->bufferpos = lineEnd - connectionP->buffer.t; + *endOfHeaderP = TRUE; } else { - /* We have the first line of a header; there may be more. */ + /* We have the first line of a field; there may be more. */ - const char * headerEnd; + const char * fieldEnd; - *endOfHeadersP = FALSE; + *endOfHeaderP = FALSE; - getRestOfHeader(connectionP, lineEnd, deadline, - &headerEnd, &error); + getRestOfField(connectionP, lineEnd, deadline, + &fieldEnd, &error); if (!error) { - *headerP = bufferStart; + *fieldP = 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; + connectionP->bufferpos = fieldEnd - connectionP->buffer.t; } } } @@ -367,7 +379,7 @@ skipToNonemptyLine(TConn * const connectionP, time_t const deadline, bool * const errorP) { - char * const bufferStart = connectionP->buffer + connectionP->bufferpos; + char * const bufferStart = connectionP->buffer.t + connectionP->bufferpos; bool gotNonEmptyLine; bool error; @@ -393,7 +405,7 @@ skipToNonemptyLine(TConn * const connectionP, /* Consume all the empty lines; advance buffer pointer to first non-empty line. */ - connectionP->bufferpos = lineStart - connectionP->buffer; + connectionP->bufferpos = lineStart - connectionP->buffer.t; } *errorP = error; } @@ -401,40 +413,45 @@ skipToNonemptyLine(TConn * const connectionP, static void -readRequestHeader(TSession * const sessionP, - time_t const deadline, - char ** const requestLineP, - uint16_t * const httpErrorCodeP) { +readRequestField(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. + Read the HTTP 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. + the HTTP document. We leave it positioned after the request field. 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'. + Fail if we can't get the field before 'deadline'. - Return as *requestLineP the request header read. This ASCIIZ string is + Return as *requestLineP the request field 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. + are not able to read the request field, or 0 if we can. If we can't, *requestLineP is meaningless. -----------------------------------------------------------------------------*/ - char * line = NULL; - bool error = FALSE; - bool endOfHeaders = FALSE; + char * line; + bool error; + bool endOfHeader; - skipToNonemptyLine(sessionP->conn, deadline, &error); + skipToNonemptyLine(sessionP->connP, deadline, &error); - if (!error) - readHeader(sessionP->conn, deadline, &endOfHeaders, &line, &error); + if (!error) { + readField(sessionP->connP, deadline, &endOfHeader, &line, &error); + /* End of header is delimited by an empty line, and we skipped all + the empty lines above, so readField() could not have encountered + EOH: + */ + assert(!endOfHeader); + } if (error) *httpErrorCodeP = 408; /* Request Timeout */ else { @@ -484,6 +501,7 @@ unescapeUri(char * const uri, } } break; + default: *y++ = *x++; break; @@ -498,6 +516,7 @@ static void parseHostPort(const char * const hostport, const char ** const hostP, unsigned short * const portP, + const char ** const errorP, uint16_t * const httpErrorCodeP) { /*---------------------------------------------------------------------------- Parse a 'hostport', a string in the form www.acme.com:8080 . @@ -512,28 +531,32 @@ parseHostPort(const char * const hostport, buffer = strdup(hostport); - colonPos = strchr(buffer, ':'); + colonPos = strrchr(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) + if (*p || port == 0) { + xmlrpc_asprintf(errorP, "There is nothing, or something " + "non-numeric for the port number after the " + "colon in '%s'", hostport); *httpErrorCodeP = 400; /* Bad Request */ - else { + } else { *hostP = strdup(buffer); *portP = port; - *httpErrorCodeP = 0; + *errorP = NULL; } } else { *hostP = strdup(buffer); *portP = 80; - *httpErrorCodeP = 0; + *errorP = NULL; } free(buffer); } @@ -596,6 +619,7 @@ parseRequestUri(char * const requestUri, requestUriNoQuery = requestUri; } + if (requestUriNoQuery[0] == '/') { *hostP = NULL; *pathP = strdup(requestUriNoQuery); @@ -634,8 +658,15 @@ parseRequestUri(char * const requestUri, hostport = hostportpath; *httpErrorCodeP = 0; } - if (!*httpErrorCodeP) - parseHostPort(hostport, &host, &port, httpErrorCodeP); + if (!*httpErrorCodeP) { + const char * error; + parseHostPort(hostport, &host, &port, + &error, httpErrorCodeP); + if (error) + xmlrpc_strfree(error); + else + *httpErrorCodeP = 0; + } if (*httpErrorCodeP) xmlrpc_strfree(path); @@ -764,9 +795,10 @@ strtolower(char * const s) { static void -getFieldNameToken(char ** const pP, - char ** const fieldNameP, - uint16_t * const httpErrorCodeP) { +getFieldNameToken(char ** const pP, + char ** const fieldNameP, + const char ** const errorP, + 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. @@ -779,30 +811,34 @@ getFieldNameToken(char ** const pP, NextToken((const char **)pP); fieldName = GetToken(pP); - if (!fieldName) + if (!fieldName) { + xmlrpc_asprintf(errorP, "The header has no field name token"); *httpErrorCodeP = 400; /* Bad Request */ - else { - if (fieldName[strlen(fieldName)-1] != ':') + } else { + if (fieldName[strlen(fieldName)-1] != ':') { /* Not a valid field name */ + xmlrpc_asprintf(errorP, "The field name token '%s' " + "does not end with a colon (:)", fieldName); *httpErrorCodeP = 400; /* Bad Request */ - else { + } else { fieldName[strlen(fieldName)-1] = '\0'; /* remove trailing colon */ strtolower(fieldName); - *httpErrorCodeP = 0; /* no error */ - *fieldNameP = fieldName; + *errorP = NULL; } } + *fieldNameP = fieldName; } static void -processHeader(const char * const fieldName, - char * const fieldValue, - TSession * const sessionP, - uint16_t * const httpErrorCodeP) { +processField(const char * const fieldName, + char * const fieldValue, + TSession * const sessionP, + const char ** const errorP, + uint16_t * const httpErrorCodeP) { /*---------------------------------------------------------------------------- We may modify *fieldValue, and we put pointers to *fieldValue and *fieldName into *sessionP. @@ -810,7 +846,7 @@ processHeader(const char * const fieldName, We must fix this some day. *sessionP should point to individual malloc'ed strings. -----------------------------------------------------------------------------*/ - *httpErrorCodeP = 0; /* initial assumption */ + *errorP = NULL; /* initial assumption */ if (xmlrpc_streq(fieldName, "connection")) { if (xmlrpc_strcaseeq(fieldValue, "keep-alive")) @@ -823,7 +859,7 @@ processHeader(const char * const fieldName, sessionP->requestInfo.host = NULL; } parseHostPort(fieldValue, &sessionP->requestInfo.host, - &sessionP->requestInfo.port, httpErrorCodeP); + &sessionP->requestInfo.port, errorP, httpErrorCodeP); } else if (xmlrpc_streq(fieldName, "from")) sessionP->requestInfo.from = fieldValue; else if (xmlrpc_streq(fieldName, "user-agent")) @@ -834,12 +870,21 @@ processHeader(const char * const fieldName, if (xmlrpc_strneq(fieldValue, "bytes=", 6)) { bool succeeded; succeeded = ListAddFromString(&sessionP->ranges, &fieldValue[6]); - *httpErrorCodeP = succeeded ? 0 : 400; + if (!succeeded) { + xmlrpc_asprintf(errorP, "ListAddFromString() failed for " + "\"range: bytes=...\" header value '%s'", + &fieldValue[6]); + *httpErrorCodeP = 400; + } } } else if (xmlrpc_streq(fieldName, "cookies")) { bool succeeded; succeeded = ListAddFromString(&sessionP->cookies, fieldValue); - *httpErrorCodeP = succeeded ? 0 : 400; + if (!succeeded) { + xmlrpc_asprintf(errorP, "ListAddFromString() failed for " + "cookies: header value '%s'", fieldValue); + *httpErrorCodeP = 400; + } } else if (xmlrpc_streq(fieldName, "expect")) { if (xmlrpc_strcaseeq(fieldValue, "100-continue")) sessionP->continueRequired = TRUE; @@ -849,53 +894,55 @@ processHeader(const char * const fieldName, static void -readAndProcessHeaders(TSession * const sessionP, - time_t const deadline, - uint16_t * const httpErrorCodeP) { +readAndProcessHeaderFields(TSession * const sessionP, + time_t const deadline, + const char ** const errorP, + 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. + Read all the HTTP header fields from the session *sessionP, which has at + least one field coming. Update *sessionP to reflect the information in the + fields. + + If we find an error in the fields or while trying to read them, we return + a text explanation of the problem as *errorP and an appropriate HTTP error + code as *httpErrorCodeP. Otherwise, we return *errorP = NULL and nothing + as *httpErrorCodeP. -----------------------------------------------------------------------------*/ - bool endOfHeaders; + bool endOfHeader; - /* Calling us doesn't make sense if there is already a valid request */ - if (sessionP->validRequest) { - return; - } - - *httpErrorCodeP = 0; /* initial assumption */ - endOfHeaders = false; /* Caller assures us there is at least one header */ + assert(!sessionP->validRequest); + /* Calling us doesn't make sense if there is already a valid request */ + + *errorP = NULL; /* initial assumption */ + endOfHeader = false; /* Caller assures us there is at least one header */ - while (!endOfHeaders && !*httpErrorCodeP) { - char * header; + while (!endOfHeader && !*errorP) { + char * field; bool error; - readHeader(sessionP->conn, deadline, &endOfHeaders, &header, &error); - if (error) + readField(sessionP->connP, deadline, &endOfHeader, &field, &error); + if (error) { + xmlrpc_asprintf(errorP, "Failed to read header from " + "client connection."); *httpErrorCodeP = 408; /* Request Timeout */ - else { - if (!endOfHeaders) { + } else { + if (!endOfHeader) { char * p; char * fieldName; - p = &header[0]; - getFieldNameToken(&p, &fieldName, httpErrorCodeP); - if (!*httpErrorCodeP) { + p = &field[0]; + getFieldNameToken(&p, &fieldName, errorP, httpErrorCodeP); + if (!*errorP) { char * fieldValue; NextToken((const char **)&p); fieldValue = p; - TableAdd(&sessionP->request_headers, + TableAdd(&sessionP->requestHeaderFields, fieldName, fieldValue); - processHeader(fieldName, fieldValue, sessionP, - httpErrorCodeP); + processField(fieldName, fieldValue, sessionP, errorP, + httpErrorCodeP); } } } @@ -905,8 +952,10 @@ readAndProcessHeaders(TSession * const sessionP, void -RequestRead(TSession * const sessionP, - uint32_t const timeout) { +RequestRead(TSession * const sessionP, + uint32_t const timeout, + const char ** const errorP, + uint16_t * const httpErrorCodeP) { /*---------------------------------------------------------------------------- Read the headers of a new HTTP request (assuming nothing has yet been read on the session). @@ -922,28 +971,38 @@ RequestRead(TSession * const sessionP, uint16_t httpErrorCode; /* zero for no error */ char * requestLine; /* In connection;s internal buffer */ - readRequestHeader(sessionP, deadline, &requestLine, &httpErrorCode); - if (!httpErrorCode) { + readRequestField(sessionP, deadline, &requestLine, &httpErrorCode); + if (httpErrorCode) { + xmlrpc_asprintf(errorP, "Problem getting the request header"); + *httpErrorCodeP = httpErrorCode; + } else { TMethod httpMethod; const char * host; const char * path; const char * query; unsigned short port; - bool moreHeaders; + bool moreFields; parseRequestLine(requestLine, &httpMethod, &sessionP->version, &host, &port, &path, &query, - &moreHeaders, &httpErrorCode); + &moreFields, &httpErrorCode); - if (!httpErrorCode) { + if (httpErrorCode) { + xmlrpc_asprintf(errorP, "Unable to parse the request header " + "'%s'", requestLine); + *httpErrorCodeP = httpErrorCode; + } else { initRequestInfo(&sessionP->requestInfo, sessionP->version, requestLine, httpMethod, host, port, path, query); - if (moreHeaders) - readAndProcessHeaders(sessionP, deadline, &httpErrorCode); + if (moreFields) { + readAndProcessHeaderFields(sessionP, deadline, + errorP, httpErrorCodeP); + } else + *errorP = NULL; - if (httpErrorCode == 0) + if (!*errorP) sessionP->validRequest = true; xmlrpc_strfreenull(host); @@ -951,8 +1010,6 @@ RequestRead(TSession * const sessionP, xmlrpc_strfreenull(query); } } - if (httpErrorCode) - ResponseStatus(sessionP, httpErrorCode); } @@ -961,7 +1018,7 @@ char * RequestHeaderValue(TSession * const sessionP, const char * const name) { - return (TableFind(&sessionP->request_headers, name)); + return (TableFind(&sessionP->requestHeaderFields, name)); } @@ -999,10 +1056,10 @@ RequestValidURIPath(TSession * const sessionP) { if (*(p++) == '/') { if (*p == '/') break; - else if ((strncmp(p,"./",2) == 0) || (strcmp(p, ".") == 0)) + else if ((xmlrpc_strneq(p,"./", 2)) || (xmlrpc_streq(p, "."))) ++p; - else if ((strncmp(p, "../", 2) == 0) || - (strcmp(p, "..") == 0)) { + else if ((xmlrpc_strneq(p, "../", 2)) || + (xmlrpc_streq(p, ".."))) { p += 2; --i; if (i == 0) @@ -1029,14 +1086,14 @@ RequestAuth(TSession * const sessionP, /*---------------------------------------------------------------------------- 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. + If the request executing on session *sessionP 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. + When we return TRUE, we also set the username in the request info for the + session to 'user' so that a future SessionGetRequestInfo can get it. -----------------------------------------------------------------------------*/ bool authorized; char * authHdrPtr; @@ -1055,7 +1112,7 @@ RequestAuth(TSession * const sessionP, NextToken((const char **)&authHdrPtr); xmlrpc_asprintf(&userPass, "%s:%s", user, pass); - Base64Encode(userPass, userPassEncoded); + xmlrpc_base64Encode(userPass, userPassEncoded); xmlrpc_strfree(userPass); if (xmlrpc_streq(authHdrPtr, userPassEncoded)) { @@ -1208,24 +1265,19 @@ 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); - } + if (ConnWrite(sessionP->connP, chunkHeader, strlen(chunkHeader))) + if (ConnWrite(sessionP->connP, buffer, len)) + return ConnWrite(sessionP->connP, "\r\n", 2); + + return FALSE; } else - succeeded = ConnWrite(sessionP->conn, buffer, len); + return ConnWrite(sessionP->connP, buffer, len); - return succeeded; } @@ -1233,14 +1285,13 @@ HTTPWriteBodyChunk(TSession * const sessionP, bool HTTPWriteEndChunk(TSession * const sessionP) { - bool retval; + bool retval = TRUE; 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; + retval = ConnWrite(sessionP->connP, "0\r\n\r\n", 5); + } return retval; } @@ -1266,7 +1317,7 @@ HTTPWriteContinue(TSession * const sessionP) { 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 ConnWrite(sessionP->conn, continueStatus, strlen(continueStatus)); + return ConnWrite(sessionP->connP, continueStatus, strlen(continueStatus)); } diff --git a/libs/xmlrpc-c/lib/abyss/src/http.h b/libs/xmlrpc-c/lib/abyss/src/http.h index acf491e..14a3168 100644 --- a/libs/xmlrpc-c/lib/abyss/src/http.h +++ b/libs/xmlrpc-c/lib/abyss/src/http.h @@ -1,6 +1,8 @@ #ifndef HTTP_H_INCLUDED #define HTTP_H_INCLUDED +#include + #include "bool.h" #include "conn.h" @@ -13,8 +15,10 @@ bool RequestValidURIPath(TSession * const r); bool RequestUnescapeURI(TSession *r); void -RequestRead(TSession * const sessionP, - uint32_t const timeout); +RequestRead(TSession * const sessionP, + uint32_t const timeout, + const char ** const errorP, + uint16_t * const httpErrorCodeP); void RequestInit(TSession * const r,TConn * const c); void RequestFree(TSession * const r); diff --git a/libs/xmlrpc-c/lib/abyss/src/main.c b/libs/xmlrpc-c/lib/abyss/src/main.c index e5741f3..875a260 100644 --- a/libs/xmlrpc-c/lib/abyss/src/main.c +++ b/libs/xmlrpc-c/lib/abyss/src/main.c @@ -42,7 +42,7 @@ #endif /* WIN32 */ #ifdef _UNIX -#include +#include #include #endif @@ -75,7 +75,7 @@ abyss_bool HandleTime(TSession *r) const char * dateString; const char * answer; - if (strcmp(r->uri,"/time")!=0) + if (!xmlrpc_streq(r->uri,"/time")) return FALSE; if (!RequestAuth(r,"Mot de passe","moez","hello")) @@ -100,7 +100,7 @@ abyss_bool HandleDump(TSession *r) { char z[50]; - if (strcmp(r->uri,"/name")!=0) + if (!xmlrpc_streq(r->uri,"/name")) return FALSE; sprintf(z,"Server name is %s", (r->server)->name ); @@ -125,7 +125,7 @@ abyss_bool HandleMIMEType(TSession *r) { char *m; - if (strncmp(r->uri,"/mime/",6)!=0) + if (!xmlrpc_strneq(r->uri, "/mime/", 6)) return FALSE; m=MIMETypeFromExt(r->uri+6); diff --git a/libs/xmlrpc-c/lib/abyss/src/response.c b/libs/xmlrpc-c/lib/abyss/src/response.c index 75421d4..235d787 100644 --- a/libs/xmlrpc-c/lib/abyss/src/response.c +++ b/libs/xmlrpc-c/lib/abyss/src/response.c @@ -6,6 +6,8 @@ Copyright information is at the end of the file =============================================================================*/ +#define _XOPEN_SOURCE 600 /* Make sure strdup() is in */ + #include #include #include @@ -16,11 +18,13 @@ #include "xmlrpc_config.h" #include "bool.h" +#include "int.h" #include "version.h" #include "mallocvar.h" #include "xmlrpc-c/string_int.h" #include "xmlrpc-c/abyss.h" +#include "trace.h" #include "server.h" #include "session.h" #include "file.h" @@ -39,10 +43,6 @@ ResponseError2(TSession * const sessionP, const char * errorDocument; - ResponseAddField(sessionP, "Content-type", "text/html"); - - ResponseWriteStart(sessionP); - xmlrpc_asprintf(&errorDocument, "Error %d" "" @@ -51,8 +51,12 @@ ResponseError2(TSession * const sessionP, "" "", sessionP->status, sessionP->status, explanation); - - ConnWrite(sessionP->conn, errorDocument, strlen(errorDocument)); + + ResponseAddField(sessionP, "Content-type", "text/html"); + ResponseContentLength(sessionP, strlen(errorDocument)); + + if (ResponseWriteStart(sessionP)) + ConnWrite(sessionP->connP, errorDocument, strlen(errorDocument)); xmlrpc_strfree(errorDocument); } @@ -123,20 +127,63 @@ ResponseStatusErrno(TSession * const sessionP) { +static bool +isValidHttpToken(const char * const token) { + + char const separators[] = "()<>@,;:\\\"/[]?={} \t"; + const char * p; + bool valid; + + for (p = &token[0], valid = true; *p; ++p) { + if (!isprint(*p) || strchr(separators, *p)) + valid = false; + } + return valid; +} + + + + +static bool +isValidHttpText(const char * const text) { + + const char * p; + bool valid; + + for (p = &text[0], valid = true; *p; ++p) { + if (!isprint(*p)) + valid = false; + } + return valid; +} + + + abyss_bool ResponseAddField(TSession * const sessionP, const char * const name, const char * const value) { - return TableAdd(&sessionP->response_headers, name, value); + abyss_bool succeeded; + + if (!isValidHttpToken(name)) { + TraceMsg("Supplied HTTP header field name is not a valid HTTP token"); + succeeded = false; + } else if (!isValidHttpText(value)) { + TraceMsg("Supplied HTTP header field value is not valid HTTP text"); + succeeded = false; + } else { + succeeded = TableAdd(&sessionP->responseHeaderFields, name, value); + } + return succeeded; } static void -addConnectionHeader(TSession * const sessionP) { +addConnectionHeaderFld(TSession * const sessionP) { - struct _TServer * const srvP = ConnServer(sessionP->conn)->srvP; + struct _TServer * const srvP = ConnServer(sessionP->connP)->srvP; if (HTTPKeepalive(sessionP)) { const char * keepaliveValue; @@ -156,7 +203,7 @@ addConnectionHeader(TSession * const sessionP) { static void -addDateHeader(TSession * const sessionP) { +addDateHeaderFld(TSession * const sessionP) { if (sessionP->status >= 200) { const char * dateValue; @@ -173,11 +220,11 @@ addDateHeader(TSession * const sessionP) { static void -addServerHeader(TSession * const sessionP) { +addServerHeaderFld(TSession * const sessionP) { const char * serverValue; - xmlrpc_asprintf(&serverValue, "XMLRPC_ABYSS/%s", XMLRPC_C_VERSION); + xmlrpc_asprintf(&serverValue, "Freeswitch xmlrpc-c_abyss /%s", XMLRPC_C_VERSION); ResponseAddField(sessionP, "Server", serverValue); @@ -186,17 +233,107 @@ addServerHeader(TSession * const sessionP) { -void -ResponseWriteStart(TSession * const sessionP) { +static unsigned int +leadingWsCt(const char * const arg) { + + unsigned int i; + + for (i = 0; arg[i] && isspace(arg[i]); ++i); + + return i; +} + - struct _TServer * const srvP = ConnServer(sessionP->conn)->srvP; + +static unsigned int +trailingWsPos(const char * const arg) { unsigned int i; + for (i = strlen(arg); i > 0 && isspace(arg[i-1]); --i); + + return i; +} + + + +static const char * +formatFieldValue(const char * const unformatted) { +/*---------------------------------------------------------------------------- + Return the string of characters that goes after the colon on the + HTTP header field line, given that 'unformatted' is its basic value. +-----------------------------------------------------------------------------*/ + const char * retval; + + /* An HTTP header field value may not have leading or trailing white + space. + */ + char * buffer; + + buffer = malloc(strlen(unformatted) + 1); + + if (buffer == NULL) + retval = xmlrpc_strnomemval(); + else { + unsigned int const lead = leadingWsCt(unformatted); + unsigned int const trail = trailingWsPos(unformatted); + assert(trail >= lead); + strncpy(buffer, &unformatted[lead], trail - lead); + buffer[trail - lead] = '\0'; + retval = buffer; + } + return retval; +} + + + +static abyss_bool +sendHeader(TConn * const connP, + TTable const fields) { +/*---------------------------------------------------------------------------- + Send the HTTP response header whose fields are fields[]. + + Don't include the blank line that separates the header from the body. + + fields[] contains syntactically valid HTTP header field names and values. + But to the extent that int contains undefined field names or semantically + invalid values, the header we send is invalid. +-----------------------------------------------------------------------------*/ + unsigned int i; + abyss_bool ret = TRUE; + for (i = 0; i < fields.size && ret; ++i) { + TTableItem * const fieldP = &fields.item[i]; + const char * const fieldValue = formatFieldValue(fieldP->value); + + const char * line; + + xmlrpc_asprintf(&line, "%s: %s\r\n", fieldP->name, fieldValue); + if (!ConnWrite(connP, line, strlen(line))) + ret = FALSE; + xmlrpc_strfree(line); + xmlrpc_strfree(fieldValue); + } + return ret; +} + + +abyss_bool +ResponseWriteStart(TSession * const sessionP) { +/*---------------------------------------------------------------------------- + Begin the process of sending the response for an HTTP transaction + (i.e. Abyss session). + + As part of this, send the entire HTTP header for the response. +-----------------------------------------------------------------------------*/ + struct _TServer * const srvP = ConnServer(sessionP->connP)->srvP; + assert(!sessionP->responseStarted); if (sessionP->status == 0) { /* Handler hasn't set status. That's an error */ + TraceMsg("Abyss client called ResponseWriteStart() on " + "a session for which he has not set the request status " + "('status' member of TSession). Using status 500\n"); sessionP->status = 500; } @@ -205,31 +342,33 @@ ResponseWriteStart(TSession * const sessionP) { { const char * const reason = HTTPReasonByStatus(sessionP->status); const char * line; + abyss_bool ret = TRUE; xmlrpc_asprintf(&line,"HTTP/1.1 %u %s\r\n", sessionP->status, reason); - ConnWrite(sessionP->conn, line, strlen(line)); + ret = ConnWrite(sessionP->connP, line, strlen(line)); xmlrpc_strfree(line); + if (!ret) return FALSE; } - addConnectionHeader(sessionP); + + addConnectionHeaderFld(sessionP); if (sessionP->chunkedwrite && sessionP->chunkedwritemode) ResponseAddField(sessionP, "Transfer-Encoding", "chunked"); - addDateHeader(sessionP); + addDateHeaderFld(sessionP); if (srvP->advertise) - addServerHeader(sessionP); + addServerHeaderFld(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); - } + /* Note that sessionP->responseHeaderFields is defined to contain + syntactically but not necessarily semantically valid header + field names and values. + */ + if (sendHeader(sessionP->connP, sessionP->responseHeaderFields)) + if (ConnWrite(sessionP->connP, "\r\n", 2)) + return TRUE; - ConnWrite(sessionP->conn, "\r\n", 2); + return FALSE; } @@ -273,6 +412,26 @@ ResponseContentLength(TSession * const sessionP, } + +void +ResponseAccessControl(TSession * const abyssSessionP, + ResponseAccessCtl const accessControl) { + + if (accessControl.allowOrigin) { + ResponseAddField(abyssSessionP, "Access-Control-Allow-Origin", + accessControl.allowOrigin); + ResponseAddField(abyssSessionP, "Access-Control-Allow-Methods", + "POST"); + if (accessControl.expires) { + char buffer[64]; + sprintf(buffer, "%u", accessControl.maxAge); + ResponseAddField(abyssSessionP, "Access-Control-Max-Age", buffer); + } + } +} + + + /********************************************************************* ** MIMEType *********************************************************************/ @@ -309,6 +468,8 @@ void MIMETypeDestroy(MIMEType * const MIMETypeP) { PoolFree(&MIMETypeP->pool); + + free(MIMETypeP); } @@ -330,6 +491,9 @@ MIMETypeTerm(void) { if (globalMimeTypeP == NULL) abort(); + ListFree(&globalMimeTypeP->extList); + ListFree(&globalMimeTypeP->typeList); + MIMETypeDestroy(globalMimeTypeP); globalMimeTypeP = NULL; @@ -595,13 +759,17 @@ mimeTypeGuessFromFile(MIMEType * const MIMETypeP, if (ext && MIMETypeP) retval = MIMETypeFromExt2(MIMETypeP, ext); - + + if (!retval) { if (fileContainsText(fileName)) retval = "text/plain"; else retval = "application/octet-stream"; } + + if (!strcmp(retval, "text/plain")) + retval = "text/plain; charset=utf-8"; return retval; } @@ -625,55 +793,6 @@ MIMETypeGuessFromFile(const char * const 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 diff --git a/libs/xmlrpc-c/lib/abyss/src/server.c b/libs/xmlrpc-c/lib/abyss/src/server.c index a52c823..392f368 100644 --- a/libs/xmlrpc-c/lib/abyss/src/server.c +++ b/libs/xmlrpc-c/lib/abyss/src/server.c @@ -1,4 +1,8 @@ /* Copyright information is at end of file */ + +#define _XOPEN_SOURCE 600 /* Make sure strdup() is in */ +#define _BSD_SOURCE /* Make sure setgroups()is in */ + #include #include #include @@ -35,6 +39,17 @@ #include "server.h" +struct uriHandler { + initHandlerFn init; + termHandlerFn term; + handleReq3Fn handleReq3; + handleReq2Fn handleReq2; + URIHandler handleReq1; + void * userdata; +}; + + + void ServerTerminate(TServer * const serverP) { @@ -44,10 +59,11 @@ ServerTerminate(TServer * const serverP) { if (srvP->chanSwitchP) { ChanSwitchInterrupt(srvP->chanSwitchP); - ChanSwitchDestroy(srvP->chanSwitchP); } } + + void ServerResetTerminate(TServer * const serverP) { @@ -108,25 +124,29 @@ logClose(struct _TServer * const srvP) { static void initChanSwitchStuff(struct _TServer * const srvP, bool const noAccept, - TChanSwitch * const userSwitchP, + TChanSwitch * const chanSwitchP, + bool const userChanSwitch, unsigned short const port, const char ** const errorP) { - if (userSwitchP) { + + if (chanSwitchP) { *errorP = NULL; srvP->serverAcceptsConnections = TRUE; - srvP->chanSwitchP = userSwitchP; + srvP->chanSwitchP = chanSwitchP; + srvP->weCreatedChanSwitch = !userChanSwitch; } else if (noAccept) { *errorP = NULL; srvP->serverAcceptsConnections = FALSE; srvP->chanSwitchP = NULL; + srvP->weCreatedChanSwitch = FALSE; } else { *errorP = NULL; srvP->serverAcceptsConnections = TRUE; srvP->chanSwitchP = NULL; + srvP->weCreatedChanSwitch = FALSE; srvP->port = port; } - srvP->weCreatedChanSwitch = FALSE; } @@ -134,7 +154,8 @@ initChanSwitchStuff(struct _TServer * const srvP, static void createServer(struct _TServer ** const srvPP, bool const noAccept, - TChanSwitch * const userChanSwitchP, + TChanSwitch * const chanSwitchP, + bool const userChanSwitch, unsigned short const portNumber, const char ** const errorP) { @@ -148,8 +169,8 @@ createServer(struct _TServer ** const srvPP, } else { srvP->terminationRequested = false; - initChanSwitchStuff(srvP, noAccept, userChanSwitchP, portNumber, - errorP); + initChanSwitchStuff(srvP, noAccept, chanSwitchP, userChanSwitch, + portNumber, errorP); if (!*errorP) { srvP->builtinHandlerP = HandlerCreate(); @@ -167,6 +188,7 @@ createServer(struct _TServer ** const srvPP, srvP->timeout = 15; srvP->advertise = TRUE; srvP->useSigchld = FALSE; + srvP->uriHandlerStackSize = 0; initUnixStuff(srvP); @@ -218,11 +240,14 @@ ServerCreate(TServer * const serverP, const char * const logFileName) { bool const noAcceptFalse = FALSE; + bool const userChanSwitchFalse = FALSE; bool success; const char * error; - createServer(&serverP->srvP, noAcceptFalse, NULL, portNumber, &error); + createServer(&serverP->srvP, noAcceptFalse, + NULL, userChanSwitchFalse, + portNumber, &error); if (error) { TraceMsg(error); @@ -291,10 +316,13 @@ ServerCreateSocket(TServer * const serverP, xmlrpc_strfree(error); } else { bool const noAcceptFalse = FALSE; + bool const userChanSwitchFalse = FALSE; const char * error; - createServer(&serverP->srvP, noAcceptFalse, chanSwitchP, 0, &error); + createServer(&serverP->srvP, noAcceptFalse, + chanSwitchP, userChanSwitchFalse, + 0, &error); if (error) { TraceMsg(error); @@ -305,6 +333,8 @@ ServerCreateSocket(TServer * const serverP, setNamePathLog(serverP, name, filesPath, logFileName); } + if (!success) + ChanSwitchDestroy(chanSwitchP); } return success; @@ -319,11 +349,14 @@ ServerCreateNoAccept(TServer * const serverP, const char * const logFileName) { bool const noAcceptTrue = TRUE; + bool const userChanSwitchFalse = FALSE; bool success; const char * error; - createServer(&serverP->srvP, noAcceptTrue, NULL, 0, &error); + createServer(&serverP->srvP, noAcceptTrue, + NULL, userChanSwitchFalse, + 0, &error); if (error) { TraceMsg(error); @@ -345,11 +378,14 @@ ServerCreateSwitch(TServer * const serverP, const char ** const errorP) { bool const noAcceptFalse = FALSE; + bool const userChanSwitchTrue = TRUE; assert(serverP); assert(chanSwitchP); - createServer(&serverP->srvP, noAcceptFalse, chanSwitchP, 0, errorP); + createServer(&serverP->srvP, noAcceptFalse, + chanSwitchP, userChanSwitchTrue, + 0, errorP); } @@ -383,7 +419,7 @@ terminateHandlers(TList * const handlersP) { if (handlersP->item) { unsigned int i; for (i = handlersP->size; i > 0; --i) { - URIHandler2 * const handlerP = handlersP->item[i-1]; + struct uriHandler * const handlerP = handlersP->item[i-1]; if (handlerP->term) handlerP->term(handlerP->userdata); } @@ -397,7 +433,7 @@ ServerFree(TServer * const serverP) { struct _TServer * const srvP = serverP->srvP; - if (srvP->weCreatedChanSwitch) + if (srvP->weCreatedChanSwitch && srvP->chanSwitchP) ChanSwitchDestroy(srvP->chanSwitchP); xmlrpc_strfree(srvP->name); @@ -456,7 +492,7 @@ void ServerSetKeepaliveTimeout(TServer * const serverP, xmlrpc_uint32_t const keepaliveTimeout) { - serverP->srvP->keepalivetimeout = keepaliveTimeout; + serverP->srvP->keepalivetimeout = MAX(keepaliveTimeout, 1); } @@ -465,7 +501,7 @@ void ServerSetKeepaliveMaxConn(TServer * const serverP, xmlrpc_uint32_t const keepaliveMaxConn) { - serverP->srvP->keepalivemaxconn = keepaliveMaxConn; + serverP->srvP->keepalivemaxconn = MAX(keepaliveMaxConn, 1); } @@ -497,6 +533,22 @@ ServerSetMimeType(TServer * const serverP, +static URIHandler2 +makeUriHandler2(const struct uriHandler * const handlerP) { + + URIHandler2 retval; + + retval.init = handlerP->init; + retval.term = handlerP->term; + retval.handleReq2 = handlerP->handleReq2; + retval.handleReq1 = handlerP->handleReq1; + retval.userdata = handlerP->userdata; + + return retval; +} + + + static void runUserHandler(TSession * const sessionP, struct _TServer * const srvP) { @@ -507,11 +559,14 @@ runUserHandler(TSession * const sessionP, for (i = srvP->handlers.size-1, handled = FALSE; i >= 0 && !handled; --i) { - URIHandler2 * const handlerP = srvP->handlers.item[i]; + const struct uriHandler * const handlerP = srvP->handlers.item[i]; - if (handlerP->handleReq2) - handlerP->handleReq2(handlerP, sessionP, &handled); - else if (handlerP->handleReq1) + if (handlerP->handleReq3) + handlerP->handleReq3(handlerP->userdata, sessionP, &handled); + if (handlerP->handleReq2) { + URIHandler2 handler2 = makeUriHandler2(handlerP); + handlerP->handleReq2(&handler2, sessionP, &handled); + } else if (handlerP->handleReq1) handled = handlerP->handleReq1(sessionP); } @@ -524,24 +579,81 @@ runUserHandler(TSession * const sessionP, static void -processDataFromClient(TConn * const connectionP, - bool const lastReqOnConn, - uint32_t const timeout, - bool * const keepAliveP) { +handleReqTooNewHttpVersion(TSession * const sessionP) { + + const char * msg; + + ResponseStatus(sessionP, 505); + + xmlrpc_asprintf(&msg, "Request is in HTTP Version %u" + "We understand only HTTP 1", + sessionP->version.major); + + ResponseError2(sessionP, msg); + + xmlrpc_strfree(msg); +} - TSession session = {0}; /* initilization, an afforadble alternative to random memory being misinterpreted! */ + + +static void +handleReqInvalidURI(TSession * const sessionP) { + + ResponseStatus(sessionP, 400); + + ResponseError2(sessionP, "Invalid URI"); +} + + + +static void +processRequestFromClient(TConn * const connectionP, + bool const lastReqOnConn, + uint32_t const timeout, + bool * const keepAliveP) { +/*---------------------------------------------------------------------------- + Get and execute one HTTP request from client connection *connectionP, + through the connection buffer. I.e. Some of the request may already be in + the connection buffer, and we may leave some of later requests in the + connection buffer. + + In fact, due to timing considerations, we assume the client has begun + sending the request, which as a practical matter means Caller has already + deposited some of it in the connection buffer. + + If there isn't one full request in the buffer now, we wait for one full + request to come through the buffer, up to 'timeout'. + + We return as *keepAliveP whether Caller should keep the connection + alive for a while for possible future requests from the client, based + on 'lastReqOnConn' and the content of the HTTP request. + + Executing the request consists primarily of calling the URI handlers that + are associated with the connection (*connectionP), passing each the request + information we read. Each handler can respond according to the HTTP method + (GET, POST, etc) and URL etc, and that response may be either to + execute the request and send the response or refuse the request and let + us call the next one in the list. +-----------------------------------------------------------------------------*/ + TSession session; + const char * error; + uint16_t httpErrorCode; RequestInit(&session, connectionP); session.serverDeniesKeepalive = lastReqOnConn; - RequestRead(&session, timeout); + RequestRead(&session, timeout, &error, &httpErrorCode); - if (session.status == 0) { + if (error) { + ResponseStatus(&session, httpErrorCode); + ResponseError2(&session, error); + xmlrpc_strfree(error); + } else { if (session.version.major >= 2) - ResponseStatus(&session, 505); + handleReqTooNewHttpVersion(&session); else if (!RequestValidURI(&session)) - ResponseStatus(&session, 400); + handleReqInvalidURI(&session); else runUserHandler(&session, connectionP->server->srvP); } @@ -582,21 +694,35 @@ serverFunc(void * const userHandle) { connectionDone = FALSE; while (!connectionDone) { - bool success; + bool timedOut, eof; + const char * readError; - /* Wait to read until timeout */ - success = ConnRead(connectionP, srvP->keepalivetimeout); - - if (!success) + /* Wait for and get beginning (at least ) of next request. We do + this separately from getting the rest of the request because we + treat dead time between requests differently from dead time in + the middle of a request. + */ + ConnRead(connectionP, srvP->keepalivetimeout, + &timedOut, &eof, &readError); + + if (readError) { + TraceMsg("Failed to read from Abyss connection. %s", readError); + xmlrpc_strfree(readError); connectionDone = TRUE; - else { + } else if (timedOut) { + connectionDone = TRUE; + } else if (eof) { + connectionDone = TRUE; + } else if (srvP->terminationRequested) { + connectionDone = TRUE; + } else { bool const lastReqOnConn = requestCount + 1 >= srvP->keepalivemaxconn; bool keepalive; - processDataFromClient(connectionP, lastReqOnConn, srvP->timeout, - &keepalive); + processRequestFromClient(connectionP, lastReqOnConn, srvP->timeout, + &keepalive); ++requestCount; @@ -611,6 +737,14 @@ serverFunc(void * const userHandle) { +/* This is the maximum amount of stack space, in bytes, serverFunc() + itself requires -- not counting what the user's request handler + (which serverFunc() calls) requires. +*/ +#define SERVER_FUNC_STACK 1024 + + + static void createSwitchFromPortNum(unsigned short const portNumber, TChanSwitch ** const chanSwitchPP, @@ -700,8 +834,8 @@ ServerInit(TServer * const serverP) { } if (retError) { TraceMsg("ServerInit() failed. %s", retError); - return 0; xmlrpc_strfree(retError); + return 0; } return 1; @@ -920,7 +1054,9 @@ acceptAndProcessNextConnection( waitForConnectionCapacity(outstandingConnListP); ConnCreate(&connectionP, serverP, channelP, channelInfoP, - &serverFunc, &destroyChannel, ABYSS_BACKGROUND, + &serverFunc, + SERVER_FUNC_STACK + srvP->uriHandlerStackSize, + &destroyChannel, ABYSS_BACKGROUND, srvP->useSigchld, &error); if (!error) { @@ -932,6 +1068,8 @@ acceptAndProcessNextConnection( destroy *channelP. */ } else { + TraceMsg("Failed to create an Abyss connection " + "out of new channel %lx. %s", channelP, error); xmlrpc_strfree(error); ChannelDestroy(channelP); free(channelInfoP); @@ -998,7 +1136,8 @@ serverRunChannel(TServer * const serverP, ConnCreate(&connectionP, serverP, channelP, channelInfoP, - &serverFunc, NULL, ABYSS_FOREGROUND, srvP->useSigchld, + &serverFunc, SERVER_FUNC_STACK + srvP->uriHandlerStackSize, + NULL, ABYSS_FOREGROUND, srvP->useSigchld, &error); if (error) { xmlrpc_asprintf(errorP, "Couldn't create HTTP connection out of " @@ -1230,24 +1369,43 @@ ServerDaemonize(TServer * const serverP) { -void -ServerAddHandler2(TServer * const serverP, - URIHandler2 * const handlerArgP, - abyss_bool * const successP) { +static void +serverAddHandler(TServer * const serverP, + initHandlerFn init, + termHandlerFn term, + URIHandler handleReq1, + handleReq2Fn handleReq2, + handleReq3Fn handleReq3, + void * const userdata, + size_t const handleReqStackSizeReq, + abyss_bool * const successP) { - URIHandler2 * handlerP; + struct _TServer * const srvP = serverP->srvP; + size_t handleReqStackSize = + handleReqStackSizeReq ? handleReqStackSizeReq : 128*1024; + + struct uriHandler * handlerP; MALLOCVAR(handlerP); if (handlerP == NULL) *successP = FALSE; else { - *handlerP = *handlerArgP; - + handlerP->init = init; + handlerP->term = term; + handlerP->handleReq1 = handleReq1; + handlerP->handleReq2 = handleReq2; + handlerP->handleReq3 = handleReq3; + handlerP->userdata = userdata; + + srvP->uriHandlerStackSize = + MAX(srvP->uriHandlerStackSize, handleReqStackSize); + if (handlerP->init == NULL) *successP = TRUE; - else - handlerP->init(handlerP, successP); - + else { + URIHandler2 handler2 = makeUriHandler2(handlerP); + handlerP->init(&handler2, successP); + } if (*successP) *successP = ListAdd(&serverP->srvP->handlers, handlerP); @@ -1258,20 +1416,42 @@ ServerAddHandler2(TServer * const serverP, -static URIHandler2 * -createHandler(URIHandler const function) { +void +ServerAddHandler3(TServer * const serverP, + const struct ServerReqHandler3 * const handlerP, + abyss_bool * const successP) { - URIHandler2 * handlerP; + serverAddHandler(serverP, NULL, handlerP->term, NULL, NULL, + handlerP->handleReq, handlerP->userdata, + handlerP->handleReqStackSize, successP); +} - MALLOCVAR(handlerP); - if (handlerP != NULL) { - handlerP->init = NULL; - handlerP->term = NULL; - handlerP->userdata = NULL; - handlerP->handleReq2 = NULL; - handlerP->handleReq1 = function; - } - return handlerP; + + +void +ServerAddHandler2(TServer * const serverP, + URIHandler2 * const handlerArgP, + abyss_bool * const successP) { + + /* This generation of the URI handler interface is strange because + it went through an unfortunate evolution. So it halfway looks like + the use supplies a handler object and Abyss calls its methods, and + halfway looks like the user simply describes his handler. + + Abyss calls handleReq2 with a pointer to a URIHandler2 like the + one which is our argument, but it isn't the same one. User can + discard *handlerArgP as soon as we return. + */ + + serverAddHandler(serverP, + handlerArgP->init, + handlerArgP->term, + handlerArgP->handleReq1, + handlerArgP->handleReq2, + NULL, + handlerArgP->userdata, + 0, + successP); } @@ -1280,35 +1460,45 @@ abyss_bool ServerAddHandler(TServer * const serverP, URIHandler const function) { - URIHandler2 * handlerP; - bool success; + URIHandler2 handler; + abyss_bool success; - handlerP = createHandler(function); + handler.init = NULL; + handler.term = NULL; + handler.userdata = NULL; + handler.handleReq2 = NULL; + handler.handleReq1 = function; - if (handlerP == NULL) - success = FALSE; - else { - success = ListAdd(&serverP->srvP->handlers, handlerP); + ServerAddHandler2(serverP, &handler, &success); - if (!success) - free(handlerP); - } return success; } +/* This is the maximum amount of stack we allow a user's default URI + handler to use. (If he exceeds this, results are undefined). + + We really ought to provide user a way to set this, as he can for + his non-default URI handlers. +*/ +#define USER_DEFAULT_HANDLER_STACK 128*1024 + void ServerDefaultHandler(TServer * const serverP, URIHandler const handler) { struct _TServer * const srvP = serverP->srvP; - if (handler) + if (handler) { srvP->defaultHandler = handler; - else { + srvP->uriHandlerStackSize = + MAX(srvP->uriHandlerStackSize, USER_DEFAULT_HANDLER_STACK); + } else { srvP->defaultHandler = HandlerDefaultBuiltin; srvP->defaultHandlerContext = srvP->builtinHandlerP; + srvP->uriHandlerStackSize = + MAX(srvP->uriHandlerStackSize, HandlerDefaultBuiltinStack); } } diff --git a/libs/xmlrpc-c/lib/abyss/src/server.h b/libs/xmlrpc-c/lib/abyss/src/server.h index 39aa63e..ed414b8 100644 --- a/libs/xmlrpc-c/lib/abyss/src/server.h +++ b/libs/xmlrpc-c/lib/abyss/src/server.h @@ -54,7 +54,7 @@ struct _TServer { Server calls each one in order until one reports that it handled it. - Each item in the list of of type 'URIHandler2'. + Each item in the list of of type 'uriHandler'. */ URIHandler defaultHandler; /* The handler for HTTP requests that aren't claimed by any handler @@ -75,6 +75,12 @@ struct _TServer { be aware of SIGCHLD and will instead poll for existence of PIDs to determine if a child has died. */ + size_t uriHandlerStackSize; + /* The maximum amount of stack any URI handler request handler + function will use. Note that this is just the requirement + of the function itself, not the stack size for the thread + that runs it. + */ #ifndef WIN32 uid_t uid; gid_t gid; diff --git a/libs/xmlrpc-c/lib/abyss/src/session.c b/libs/xmlrpc-c/lib/abyss/src/session.c index ae3a078..f0488e4 100644 --- a/libs/xmlrpc-c/lib/abyss/src/session.c +++ b/libs/xmlrpc-c/lib/abyss/src/session.c @@ -23,28 +23,34 @@ SessionRefillBuffer(TSession * const sessionP) { I.e. read data from the socket. -----------------------------------------------------------------------------*/ - struct _TServer * const srvP = sessionP->conn->server->srvP; + struct _TServer * const srvP = sessionP->connP->server->srvP; bool failed; failed = FALSE; /* initial value */ /* Reset our read buffer & flush data from previous reads. */ - ConnReadInit(sessionP->conn); + ConnReadInit(sessionP->connP); if (sessionP->continueRequired) failed = !HTTPWriteContinue(sessionP); if (!failed) { + const char * readError; + 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. + /* Read more network data into our buffer. Fail if we time out before + client sends any data or client closes the connection or there's + some network error. 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); + ConnRead(sessionP->connP, srvP->timeout, NULL, NULL, &readError); + if (readError) { + failed = TRUE; + xmlrpc_strfree(readError); + } } return !failed; } @@ -54,7 +60,7 @@ SessionRefillBuffer(TSession * const sessionP) { size_t SessionReadDataAvail(TSession * const sessionP) { - return sessionP->conn->buffersize - sessionP->conn->bufferpos; + return sessionP->connP->buffersize - sessionP->connP->bufferpos; } @@ -73,18 +79,18 @@ SessionGetReadData(TSession * const sessionP, 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; + uint32_t const bufferPos = sessionP->connP->bufferpos; - *outStartP = &sessionP->conn->buffer[bufferPos]; + *outStartP = &sessionP->connP->buffer.t[bufferPos]; - assert(bufferPos <= sessionP->conn->buffersize); + assert(bufferPos <= sessionP->connP->buffersize); - *outLenP = MIN(max, sessionP->conn->buffersize - bufferPos); + *outLenP = MIN(max, sessionP->connP->buffersize - bufferPos); /* move pointer past the bytes we are returning */ - sessionP->conn->bufferpos += *outLenP; + sessionP->connP->bufferpos += *outLenP; - assert(sessionP->conn->bufferpos <= sessionP->conn->buffersize); + assert(sessionP->connP->bufferpos <= sessionP->connP->buffersize); } @@ -102,7 +108,7 @@ void SessionGetChannelInfo(TSession * const sessionP, void ** const channelInfoPP) { - *channelInfoPP = sessionP->conn->channelInfoP; + *channelInfoPP = sessionP->connP->channelInfoP; } @@ -125,25 +131,24 @@ SessionLog(TSession * const sessionP) { DateToLogString(sessionP->date, &date); - ConnFormatClientAddr(sessionP->conn, &peerInfo); + ConnFormatClientAddr(sessionP->connP, &peerInfo); - xmlrpc_asprintf(&logline, "%s - %s - [%s] \"%s\" %d %d", + xmlrpc_asprintf(&logline, "%s - %s - [%s] \"%s\" %d %u", peerInfo, user, date, sessionP->validRequest ? sessionP->requestInfo.requestline : "???", sessionP->status, - sessionP->conn->outbytes + sessionP->connP->outbytes ); xmlrpc_strfree(peerInfo); xmlrpc_strfree(date); - if (logline) { - LogWrite(sessionP->conn->server, logline); + LogWrite(sessionP->connP->server, logline); + + xmlrpc_strfree(logline); - xmlrpc_strfree(logline); - } return true; } @@ -152,7 +157,7 @@ SessionLog(TSession * const sessionP) { void * SessionGetDefaultHandlerCtx(TSession * const sessionP) { - struct _TServer * const srvP = sessionP->conn->server->srvP; + struct _TServer * const srvP = sessionP->connP->server->srvP; return srvP->defaultHandlerContext; } diff --git a/libs/xmlrpc-c/lib/abyss/src/session.h b/libs/xmlrpc-c/lib/abyss/src/session.h index 058d543..07700e9 100644 --- a/libs/xmlrpc-c/lib/abyss/src/session.h +++ b/libs/xmlrpc-c/lib/abyss/src/session.h @@ -47,17 +47,29 @@ struct _TSession { ResponseWriteStart()) */ - struct _TConn * conn; + struct _TConn * connP; 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 requestHeaderFields; + /* All the fields of the header of the HTTP request. The key is the + field name in lower case. The value is the verbatim value from + the field. */ - TTable response_headers; + TTable responseHeaderFields; + /* All the fields of the header of the HTTP response. + This gets successively computed; at any moment, it is the list of + fields the user has requested so far. It also includes fields + Abyss itself has decided to include. (Blechh. This needs to be + cleaned up). + + Each table item is an HTTP header field. The Name component of the + table item is the header field name (it is syntactically valid but + not necessarily a defined field name) and the Value comonent is the + header field value (it is syntactically valid but not necessarily + semantically valid). + */ time_t date; diff --git a/libs/xmlrpc-c/lib/abyss/src/socket.c b/libs/xmlrpc-c/lib/abyss/src/socket.c index d76c611..4724e6d 100644 --- a/libs/xmlrpc-c/lib/abyss/src/socket.c +++ b/libs/xmlrpc-c/lib/abyss/src/socket.c @@ -9,6 +9,7 @@ #include #include +#include "int.h" #include "mallocvar.h" #include "xmlrpc-c/abyss.h" #include "channel.h" @@ -26,7 +27,7 @@ functions that are particular to an implementation. */ -static uint const socketSignature = 0x060609; +static unsigned int const socketSignature = 0x060609; static void diff --git a/libs/xmlrpc-c/lib/abyss/src/socket.h b/libs/xmlrpc-c/lib/abyss/src/socket.h index 20e8e09..50e67ba 100644 --- a/libs/xmlrpc-c/lib/abyss/src/socket.h +++ b/libs/xmlrpc-c/lib/abyss/src/socket.h @@ -17,10 +17,12 @@ so there may be few or no users of TSocket. ============================================================================*/ +#include "int.h" + #include "xmlrpc-c/abyss.h" struct _TSocket { - uint signature; + unsigned int 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 diff --git a/libs/xmlrpc-c/lib/abyss/src/socket_openssl.c b/libs/xmlrpc-c/lib/abyss/src/socket_openssl.c index e90be0d..3082851 100644 --- a/libs/xmlrpc-c/lib/abyss/src/socket_openssl.c +++ b/libs/xmlrpc-c/lib/abyss/src/socket_openssl.c @@ -126,6 +126,8 @@ channelDestroy(TChannel * const channelP) { SSL_shutdown(channelOpensslP->sslP); free(channelOpensslP); + channelP->implP = 0; + } diff --git a/libs/xmlrpc-c/lib/abyss/src/socket_unix.c b/libs/xmlrpc-c/lib/abyss/src/socket_unix.c index 6231852..9d5dc25 100644 --- a/libs/xmlrpc-c/lib/abyss/src/socket_unix.c +++ b/libs/xmlrpc-c/lib/abyss/src/socket_unix.c @@ -42,6 +42,7 @@ #define sane_close(_it) do {if (_it > -1) { close(_it) ; _it = -1; }} while (_it > -1) + typedef struct { int interruptorFd; int interrupteeFd; @@ -164,6 +165,7 @@ channelDestroy(TChannel * const channelP) { sane_close(socketUnixP->fd); free(socketUnixP); + channelP->implP = 0; } @@ -180,37 +182,44 @@ channelWrite(TChannel * const channelP, size_t bytesLeft; bool error; + int to_count = 0; assert(sizeof(size_t) >= sizeof(len)); - for (bytesLeft = len, error = FALSE; - bytesLeft > 0 && !error; - ) { - size_t const maxSend = (size_t)(-1) >> 1; + for (bytesLeft = len, error = FALSE; bytesLeft > 0 && !error; ) { + size_t const maxSend = 4096 * 2; /* with respect to resource allocation this might be a better value than 2^31 */ + ssize_t rc = 0; + + rc = send(socketUnixP->fd, buffer + len - bytesLeft, MIN(maxSend, bytesLeft), 0); + if (rc > 0) { /* 0 means connection closed; < 0 means severe error ; > 0 means bytes transferred */ + to_count = 0; + bytesLeft -= rc; + if (ChannelTraceIsActive) + fprintf(stderr, "Abyss: sent %d bytes: '%.*s'\n", rc, MIN(rc, 4096), buffer + len - bytesLeft); + } + else if (!rc) { + error = TRUE; + if (ChannelTraceIsActive) + fprintf(stderr, "\nAbyss: send() failed: socket closed"); + } + else { + error = TRUE; + if (errno == EWOULDBLOCK) { + usleep(20 * 1000); /* give socket another chance after xx millisec) */ + if (++to_count < 300) { + error = FALSE; + } + if (ChannelTraceIsActive) + fprintf(stderr, "\nAbyss: send() failed with errno %d (%s) cnt %d, will retry\n", errno, strerror(errno), to_count); + } + if (ChannelTraceIsActive) + fprintf(stderr, "Abyss: send() failed with errno=%d (%s)", errno, strerror(errno)); + } + } + + *failedP = error; - 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; } @@ -225,25 +234,29 @@ channelRead(TChannel * const channelP, 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); - } + int retries = 300; + + for (*failedP = TRUE; *failedP && retries; retries--) { + int rc = recv(socketUnixP->fd, buffer, bufferSize, 0); + if (rc < 0) { + if (errno == EWOULDBLOCK) { + if (ChannelTraceIsActive) + fprintf(stderr, "\nAbyss: recv() failed with errno %d (%s) cnt %d, will retry\n", errno, strerror(errno), retries); + usleep(20 * 1000); /* give socket another chance after xx millisec)*/ + *failedP = FALSE; + } else { + if (ChannelTraceIsActive) + fprintf(stderr, "\nAbyss: recv() failed with errno %d (%s)\n", errno, strerror(errno)); + break; + } + } else { + *failedP = FALSE; + *bytesReceivedP = rc; + + if (ChannelTraceIsActive) + fprintf(stderr, "Abyss channel: read %u bytes: '%.*s'\n", bytesReceivedP, (int)(*bytesReceivedP), buffer); + } + } } @@ -270,7 +283,7 @@ channelWait(TChannel * const channelP, one. We return before the requested condition holds if 'timeoutMs' - milliseconds pass. timoutMs == TIME_INFINITE means infinity. + milliseconds pass. timeoutMs == 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 @@ -312,8 +325,7 @@ channelWait(TChannel * const channelP, pollfds[1].events = POLLIN; rc = poll(pollfds, ARRAY_SIZE(pollfds), - timeoutMs == TIME_INFINITE ? -1 : timeoutMs); - + timeoutMs == TIME_INFINITE ? -1 : (int)timeoutMs); if (rc < 0) { if (errno == EINTR) { @@ -477,10 +489,9 @@ makeChannelInfo(struct abyss_unix_chaninfo ** const channelInfoPP, channelInfoP->peerAddrLen = peerAddrLen; channelInfoP->peerAddr = peerAddr; - *channelInfoPP = channelInfoP; - *errorP = NULL; } + *channelInfoPP = channelInfoP; } @@ -493,13 +504,13 @@ makeChannelFromFd(int const fd, 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; @@ -507,6 +518,7 @@ makeChannelFromFd(int const fd, if (!*errorP) { ChannelCreate(&channelVtbl, socketUnixP, &channelP); + if (channelP == NULL) xmlrpc_asprintf(errorP, "Unable to allocate memory for " "channel descriptor."); @@ -617,9 +629,13 @@ waitForConnection(struct socketUnix * const listenSocketP, 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 + time after we start running. (That means this behavior isn't useful for most purposes). + We furthermore return before the requested condition holds if someone sends + a byte through the listening socket's interrupt pipe (or has sent one + previously since the most recent time the pipe was drained). + Return *interruptedP == true if we return before there is a connection ready to accept. -----------------------------------------------------------------------------*/ @@ -665,35 +681,42 @@ createChannelForAccept(int const acceptedFd, 'peerAddr' is the address of the client, from accept(). -----------------------------------------------------------------------------*/ - struct socketUnix * acceptedSocketP; + struct abyss_unix_chaninfo * channelInfoP; - 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; + makeChannelInfo(&channelInfoP, peerAddr, sizeof(peerAddr), errorP); + if (!*errorP) { + struct socketUnix * acceptedSocketP; - ChannelCreate(&channelVtbl, acceptedSocketP, &channelP); - if (!channelP) - xmlrpc_asprintf(errorP, - "Failed to create TChannel object."); - else { - *errorP = NULL; - *channelPP = channelP; - *channelInfoPP = channelInfoP; + MALLOCVAR(acceptedSocketP); + + if (!acceptedSocketP) + xmlrpc_asprintf(errorP, "Unable to allocate memory"); + else { + acceptedSocketP->fd = acceptedFd; + acceptedSocketP->userSuppliedFd = FALSE; + + initInterruptPipe(&acceptedSocketP->interruptPipe, 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) + termInterruptPipe(&acceptedSocketP->interruptPipe); } if (*errorP) - free(channelInfoP); + free(acceptedSocketP); } if (*errorP) - free(acceptedSocketP); + free(channelInfoP); } } diff --git a/libs/xmlrpc-c/lib/abyss/src/socket_win.c b/libs/xmlrpc-c/lib/abyss/src/socket_win.c index d3f683a..a1a07df 100644 --- a/libs/xmlrpc-c/lib/abyss/src/socket_win.c +++ b/libs/xmlrpc-c/lib/abyss/src/socket_win.c @@ -1,997 +1,892 @@ -/*============================================================================= - socket_win.c -=============================================================================== - This is the implementation of TChanSwitch and TChannel - for a Winsock socket. -=============================================================================*/ - -#include -#include -#include -#include -#include - -#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 */ - HANDLE interruptEvent; -}; - -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); - - CloseHandle(socketWinP->interruptEvent); - - 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 (WSAGetLastError() != WSAEINTR) - 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. (But we could probably do it the same way - chanSwitchInterrupt() works -- no one has needed it enough yet to do that - work). ------------------------------------------------------------------------------*/ - -} - - - -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. WSA error = %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; - socketWinP->interruptEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - - ChannelCreate(&channelVtbl, socketWinP, &channelP); - - if (channelP == NULL) - xmlrpc_asprintf(errorP, "Unable to allocate memory for " - "channel descriptor."); - else { - *channelPP = channelP; - *errorP = NULL; - } - if (*errorP) { - CloseHandle(socketWinP->interruptEvent); - 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(peerAddr); - - 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); - - CloseHandle(socketWinP->interruptEvent); - - 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 void -createChannelForAccept(int const acceptedWinsock, - struct sockaddr const peerAddr, - TChannel ** const channelPP, - void ** const channelInfoPP, - const char ** const errorP) { - - struct abyss_win_chaninfo * channelInfoP; - makeChannelInfo(&channelInfoP, peerAddr, sizeof(peerAddr), errorP); - if (!*errorP) { - struct socketWin * acceptedSocketP; - - MALLOCVAR(acceptedSocketP); - - if (!acceptedSocketP) - xmlrpc_asprintf(errorP, "Unable to allocate memory"); - else { - TChannel * channelP; - - acceptedSocketP->winsock = acceptedWinsock; - acceptedSocketP->userSuppliedWinsock = FALSE; - acceptedSocketP->interruptEvent = - CreateEvent(NULL, FALSE, FALSE, NULL); - - ChannelCreate(&channelVtbl, acceptedSocketP, &channelP); - if (!channelP) - xmlrpc_asprintf(errorP, - "Failed to create TChannel object."); - else { - *errorP = NULL; - *channelPP = channelP; - *channelInfoPP = channelInfoP; - } - if (*errorP) { - CloseHandle(acceptedSocketP->interruptEvent); - 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 socketWin * const listenSocketP = chanSwitchP->implP; - HANDLE acceptEvent = WSACreateEvent(); - bool interrupted; - TChannel * channelP; - - interrupted = FALSE; /* Haven't been interrupted yet */ - channelP = NULL; /* No connection yet */ - *errorP = NULL; /* No error yet */ - - WSAEventSelect(listenSocketP->winsock, acceptEvent, - FD_ACCEPT | FD_CLOSE | FD_READ); - - while (!channelP && !*errorP && !interrupted) { - HANDLE interrupts[2] = {acceptEvent, listenSocketP->interruptEvent}; - int rc; - struct sockaddr peerAddr; - socklen_t size = sizeof(peerAddr); - - rc = WaitForMultipleObjects(2, interrupts, FALSE, INFINITE); - if (WAIT_OBJECT_0 + 1 == rc) { - interrupted = TRUE; - continue; - }; - - rc = accept(listenSocketP->winsock, &peerAddr, &size); - - if (rc >= 0) { - int const acceptedWinsock = rc; - - createChannelForAccept(acceptedWinsock, peerAddr, - &channelP, channelInfoPP, errorP); - - if (*errorP) - closesocket(acceptedWinsock); - } else { - int const lastError = WSAGetLastError(); - - if (lastError == WSAEINTR) - interrupted = TRUE; - else - xmlrpc_asprintf(errorP, - "accept() failed, WSA error = %d (%s)", - lastError, getWSAError(lastError)); - } - } - *channelPP = channelP; - CloseHandle(acceptEvent); -} - - - -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. ------------------------------------------------------------------------------*/ - struct socketWin * const listenSocketP = chanSwitchP->implP; - - SetEvent(listenSocketP->interruptEvent); -} - - - -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; - int one = 1; - - ZeroMemory(&name, sizeof(name)); - name.sin_family = AF_INET; - name.sin_port = htons(portNumber); - if (addrP) - name.sin_addr = *addrP; - - setsockopt(winsock, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(int)); - 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; - socketWinP->interruptEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - - setSocketOptions(socketWinP->winsock, errorP); - if (!*errorP) { - bindSocketToPort(socketWinP->winsock, NULL, portNumber, - errorP); - if (!*errorP) - ChanSwitchCreate(&chanSwitchVtbl, socketWinP, - chanSwitchPP); - } - - if (*errorP) { - CloseHandle(socketWinP->interruptEvent); - 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; - socketWinP->interruptEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - - 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) { - CloseHandle(socketWinP->interruptEvent); - free(socketWinP); - } - } - } -} +/*============================================================================= + socket_win.c +=============================================================================== + This is the implementation of TChanSwitch and TChannel + for a Winsock socket. +=============================================================================*/ + +#include +#include +#include +#include +#include + +#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; + +/* list shamelessly copied from apache apr errorcodes.c - Grmt 2011-06-16 */ + +SOCKERR sSockErr[] = { + WSAEINTR, "Interrupted system call", + WSAEBADF, "Bad file number", + WSAEACCES, "Permission denied", + WSAEFAULT, "Bad address", + WSAEINVAL, "Invalid argument", + WSAEMFILE, "Too many open sockets", + WSAEWOULDBLOCK, "Operation would block", + WSAEINPROGRESS, "Operation now in progress", + WSAEALREADY, "Operation already in progress", + WSAENOTSOCK, "Socket operation on non-socket", + WSAEDESTADDRREQ, "Destination address required", + WSAEMSGSIZE, "Message too long", + WSAEPROTOTYPE, "Protocol wrong type for socket", + WSAENOPROTOOPT, "Bad protocol option", + WSAEPROTONOSUPPORT, "Protocol not supported", + WSAESOCKTNOSUPPORT, "Socket type not supported", + WSAEOPNOTSUPP, "Operation not supported on socket", + WSAEPFNOSUPPORT, "Protocol family not supported", + WSAEAFNOSUPPORT, "Address family not supported", + WSAEADDRINUSE, "Address already in use", + WSAEADDRNOTAVAIL, "Can't assign requested address", + WSAENETDOWN, "Network is down", + WSAENETUNREACH, "Network is unreachable", + WSAENETRESET, "Net connection reset", + WSAECONNABORTED, "Software caused connection abort", + WSAECONNRESET, "Connection reset by peer", + WSAENOBUFS, "No buffer space available", + WSAEISCONN, "Socket is already connected", + WSAENOTCONN, "Socket is not connected", + WSAESHUTDOWN, "Can't send after socket shutdown", + WSAETOOMANYREFS, "Too many references, can't splice", + WSAETIMEDOUT, "Connection timed out", + WSAECONNREFUSED, "Connection refused", + WSAELOOP, "Too many levels of symbolic links", + WSAENAMETOOLONG, "File name too long", + WSAEHOSTDOWN, "Host is down", + WSAEHOSTUNREACH, "No route to host", + WSAENOTEMPTY, "Directory not empty", + WSAEPROCLIM, "Too many processes", + WSAEUSERS, "Too many users", + WSAEDQUOT, "Disc quota exceeded", + WSAESTALE, "Stale NFS file handle", + WSAEREMOTE, "Too many levels of remote in path", + WSASYSNOTREADY, "Network system is unavailable", + WSAVERNOTSUPPORTED, "Winsock version out of range", + WSANOTINITIALISED, "WSAStartup not yet called", + WSAEDISCON, "Graceful shutdown in progress", + WSAHOST_NOT_FOUND, "Host not found", + WSANO_DATA, "No host data of that type was found", + 0, NULL +}; + + +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 */ + HANDLE interruptEvent; +}; + +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); + + CloseHandle(socketWinP->interruptEvent); + + free(socketWinP); + channelP->implP = 0; + +} + + + +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; + int to_count = 0; + int lastError = 0; + + for (bytesLeft = len, error = FALSE; bytesLeft > 0 && !error;) { + size_t const maxSend = 4096 * 2; /* with respect to resource allocation this might be a better value than 2^31 */ + + int rc = send(socketWinP->winsock, buffer + len - bytesLeft, MIN(maxSend, bytesLeft), 0); + if (rc > 0) { /* 0 means connection closed; < 0 means severe error */ + to_count = 0; + bytesLeft -= rc; + } + else if (!rc) { + error = TRUE; + fprintf(stderr, "Abyss: send() failed: connection closed"); + } + else { + error = TRUE; + lastError = WSAGetLastError(); + if (lastError == WSAEWOULDBLOCK || lastError == ERROR_IO_PENDING) { + SleepEx(20, TRUE); /* give socket another chance after xx millisec) */ + if (++to_count < 300) { + error = FALSE; + } + // fprintf(stderr, "Abyss: send() failed with errno %d (%s) cnt %d, will retry\n", lastError, getWSAError(lastError), to_count); + } + if (error) fprintf(stderr, "Abyss: send() failed with errno %d (%s)\n", lastError, getWSAError(lastError)); + } + } + + *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 retries = 300; + + for (*failedP = TRUE; *failedP && retries; retries--) { + int rc = recv(socketWinP->winsock, buffer, bufferSize, 0); + int lastError = WSAGetLastError(); + + if (rc < 0) { + if (lastError == WSAEWOULDBLOCK || lastError == ERROR_IO_PENDING) { + fprintf(stderr, "Abyss: recv() failed with errno %d (%s) cnt %d, will retry\n", lastError, getWSAError(lastError), retries); + SleepEx(30, TRUE); /* give socket another chance after xx millisec)*/ + *failedP = FALSE; + } else { + fprintf(stderr, "Abyss: recv() failed with errno %d (%s)\n", lastError, getWSAError(lastError)); + break; + } + } 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 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 (WSAGetLastError() != WSAEINTR) + 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. (But we could probably do it the same way + chanSwitchInterrupt() works -- no one has needed it enough yet to do that + work). +-----------------------------------------------------------------------------*/ + +} + + + +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. WSA error = %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; + socketWinP->interruptEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + + ChannelCreate(&channelVtbl, socketWinP, &channelP); + + if (channelP == NULL) + xmlrpc_asprintf(errorP, "Unable to allocate memory for " + "channel descriptor."); + else { + *channelPP = channelP; + *errorP = NULL; + } + if (*errorP) { + CloseHandle(socketWinP->interruptEvent); + 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(peerAddr); + + 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); + + CloseHandle(socketWinP->interruptEvent); + + 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 void +createChannelForAccept(int const acceptedWinsock, + struct sockaddr const peerAddr, + TChannel ** const channelPP, + void ** const channelInfoPP, + const char ** const errorP) { + + struct abyss_win_chaninfo * channelInfoP; + makeChannelInfo(&channelInfoP, peerAddr, sizeof(peerAddr), errorP); + if (!*errorP) { + struct socketWin * acceptedSocketP; + + MALLOCVAR(acceptedSocketP); + + if (!acceptedSocketP) + xmlrpc_asprintf(errorP, "Unable to allocate memory"); + else { + TChannel * channelP; + + acceptedSocketP->winsock = acceptedWinsock; + acceptedSocketP->userSuppliedWinsock = FALSE; + acceptedSocketP->interruptEvent = + CreateEvent(NULL, FALSE, FALSE, NULL); + + ChannelCreate(&channelVtbl, acceptedSocketP, &channelP); + if (!channelP) + xmlrpc_asprintf(errorP, + "Failed to create TChannel object."); + else { + *errorP = NULL; + *channelPP = channelP; + *channelInfoPP = channelInfoP; + } + if (*errorP) { + CloseHandle(acceptedSocketP->interruptEvent); + 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 socketWin * const listenSocketP = chanSwitchP->implP; + HANDLE acceptEvent = WSACreateEvent(); + bool interrupted; + TChannel * channelP; + + interrupted = FALSE; /* Haven't been interrupted yet */ + channelP = NULL; /* No connection yet */ + *errorP = NULL; /* No error yet */ + + WSAEventSelect(listenSocketP->winsock, acceptEvent, + FD_ACCEPT | FD_CLOSE | FD_READ); + + while (!channelP && !*errorP && !interrupted) { + HANDLE interrupts[2] = {acceptEvent, listenSocketP->interruptEvent}; + int rc; + struct sockaddr peerAddr; + socklen_t size = sizeof(peerAddr); + + rc = WaitForMultipleObjects(2, interrupts, FALSE, INFINITE); + if (WAIT_OBJECT_0 + 1 == rc) { + interrupted = TRUE; + continue; + }; + + rc = accept(listenSocketP->winsock, &peerAddr, &size); + + if (rc >= 0) { + int const acceptedWinsock = rc; + + createChannelForAccept(acceptedWinsock, peerAddr, + &channelP, channelInfoPP, errorP); + + if (*errorP) + closesocket(acceptedWinsock); + } else { + int const lastError = WSAGetLastError(); + + if (lastError == WSAEINTR) + interrupted = TRUE; + else + xmlrpc_asprintf(errorP, + "accept() failed, WSA error = %d (%s)", + lastError, getWSAError(lastError)); + } + } + *channelPP = channelP; + CloseHandle(acceptEvent); +} + + + +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. +-----------------------------------------------------------------------------*/ + struct socketWin * const listenSocketP = chanSwitchP->implP; + + SetEvent(listenSocketP->interruptEvent); +} + + + +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; + int one = 1; + + ZeroMemory(&name, sizeof(name)); + name.sin_family = AF_INET; + name.sin_port = htons(portNumber); + if (addrP) + name.sin_addr = *addrP; + + setsockopt(winsock, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(int)); + 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; + socketWinP->interruptEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + + setSocketOptions(socketWinP->winsock, errorP); + if (!*errorP) { + bindSocketToPort(socketWinP->winsock, NULL, portNumber, + errorP); + if (!*errorP) + ChanSwitchCreate(&chanSwitchVtbl, socketWinP, + chanSwitchPP); + } + + if (*errorP) { + CloseHandle(socketWinP->interruptEvent); + 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; + socketWinP->interruptEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + + 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) { + CloseHandle(socketWinP->interruptEvent); + free(socketWinP); + } + } + } +} diff --git a/libs/xmlrpc-c/lib/abyss/src/thread.c b/libs/xmlrpc-c/lib/abyss/src/thread.c deleted file mode 100644 index b3d49c7..0000000 --- a/libs/xmlrpc-c/lib/abyss/src/thread.c +++ /dev/null @@ -1,228 +0,0 @@ -/******************************************************************************* -** -** thread.c -** -** This file is part of the ABYSS Web server project. -** -** Copyright (C) 2000 by Moez Mahfoudh . -** 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. -** -*******************************************************************************/ - -#ifdef ABYSS_WIN32 -#include -#endif - -#include "xmlrpc-c/abyss.h" - -#include "xmlrpc_config.h" - -/* 16K is the minimum size of stack on Win32 */ -#define THREAD_STACK_SIZE (240*1024) - -/********************************************************************* -** Thread -*********************************************************************/ - -abyss_bool ThreadCreate(TThread * const t ATTR_UNUSED, - TThreadProc const func, - void * const arg ) -{ -#ifdef ABYSS_WIN32 - DWORD z; - *t =(TThread)_beginthreadex( NULL, THREAD_STACK_SIZE, func, - arg, CREATE_SUSPENDED, &z ); - return (*t!=NULL); -#else -# ifdef _UNIX -# ifdef _THREAD - { - pthread_attr_t attr; - pthread_attr_init( &attr ); - pthread_attr_setstacksize( &attr, THREAD_STACK_SIZE ); - if( pthread_create( t,&attr,(PTHREAD_START_ROUTINE)func,arg)==0) - { - pthread_attr_destroy( &attr ); - return (pthread_detach(*t)==0); - } - pthread_attr_destroy( &attr ); - return FALSE; - } -# else - switch (fork()) - { - case 0: - (*func)(arg); - exit(0); - case (-1): - return FALSE; - }; - - return TRUE; -# endif /* _THREAD */ -# else - (*func)(arg); - return TRUE; -# endif /*_UNIX */ -#endif /* ABYSS_WIN32 */ -} - -abyss_bool -ThreadRun(TThread * const t ATTR_UNUSED) { -#ifdef ABYSS_WIN32 - return (ResumeThread(*t)!=0xFFFFFFFF); -#else - return TRUE; -#endif /* ABYSS_WIN32 */ -} - - - -abyss_bool -ThreadStop(TThread * const t ATTR_UNUSED) { -#ifdef ABYSS_WIN32 - return (SuspendThread(*t)!=0xFFFFFFFF); -#else - return TRUE; -#endif /* ABYSS_WIN32 */ -} - - - -abyss_bool -ThreadKill(TThread * const t ATTR_UNUSED) { -#ifdef ABYSS_WIN32 - return (TerminateThread(*t,0)!=0); -#else - /*return (pthread_kill(*t)==0);*/ - return TRUE; -#endif /* ABYSS_WIN32 */ -} - - - -void ThreadWait(uint32_t ms) -{ -#ifdef ABYSS_WIN32 - Sleep(ms); -#else - usleep(ms*1000); -#endif /* ABYSS_WIN32 */ -} - - - -void -ThreadExit(TThread * const t ATTR_UNUSED, - int const ret_value ATTR_UNUSED) { -#ifdef ABYSS_WIN32 - _endthreadex(ret_value); -#elif defined(_THREAD) - pthread_exit(&ret_value); -#else - ; -#endif /* ABYSS_WIN32 */ -} - - - -void -ThreadClose(TThread * const t ATTR_UNUSED) { -#ifdef ABYSS_WIN32 - CloseHandle(*t); -#endif /* ABYSS_WIN32 */ -} - - - -/********************************************************************* -** Mutex -*********************************************************************/ - - - -abyss_bool -MutexCreate(TMutex * const m ATTR_UNUSED) { -#if defined(ABYSS_WIN32) - return ((*m=CreateMutex(NULL,FALSE,NULL))!=NULL); -#elif defined(_THREAD) - return (pthread_mutex_init(m, NULL)==0); -#else - return TRUE; -#endif -} - - - -abyss_bool -MutexLock(TMutex * const m ATTR_UNUSED) { -#if defined(ABYSS_WIN32) - return (WaitForSingleObject(*m,INFINITE)!=WAIT_TIMEOUT); -#elif defined(_THREAD) - return (pthread_mutex_lock(m)==0); -#else - return TRUE; -#endif -} - - - -abyss_bool -MutexUnlock(TMutex * const m ATTR_UNUSED) { -#if defined(ABYSS_WIN32) - return ReleaseMutex(*m); -#elif defined(_THREAD) - return (pthread_mutex_unlock(m)==0); -#else - return TRUE; -#endif -} - - - -abyss_bool -MutexTryLock(TMutex * const m ATTR_UNUSED) { -#if defined(ABYSS_WIN32) - return (WaitForSingleObject(*m,0)!=WAIT_TIMEOUT); -#elif defined(_THREAD) - return (pthread_mutex_trylock(m)==0); -#else - return TRUE; -#endif -} - - - -void -MutexFree(TMutex * const m ATTR_UNUSED) { -#if defined(ABYSS_WIN32) - CloseHandle(*m); -#elif defined(_THREAD) - pthread_mutex_destroy(m); -#else - ; -#endif -} diff --git a/libs/xmlrpc-c/lib/abyss/src/thread.h b/libs/xmlrpc-c/lib/abyss/src/thread.h index c214f4b..c9f2b9e 100644 --- a/libs/xmlrpc-c/lib/abyss/src/thread.h +++ b/libs/xmlrpc-c/lib/abyss/src/thread.h @@ -21,6 +21,7 @@ ThreadCreate(TThread ** const threadPP, TThreadProc * const func, TThreadDoneFn * const threadDone, bool const useSigchld, + size_t const stackSize, const char ** const errorP); bool @@ -36,7 +37,8 @@ void ThreadWaitAndRelease(TThread * const threadP); void -ThreadExit(int const retValue); +ThreadExit(TThread * const threadP, + int const retValue); void ThreadRelease(TThread * const threadP); diff --git a/libs/xmlrpc-c/lib/abyss/src/thread_fork.c b/libs/xmlrpc-c/lib/abyss/src/thread_fork.c index 973e153..d96bf59 100644 --- a/libs/xmlrpc-c/lib/abyss/src/thread_fork.c +++ b/libs/xmlrpc-c/lib/abyss/src/thread_fork.c @@ -157,6 +157,7 @@ ThreadCreate(TThread ** const threadPP, TThreadProc * const func, TThreadDoneFn * const threadDone, bool const useSigchld, + size_t const stackSize, const char ** const errorP) { TThread * threadP; @@ -189,6 +190,9 @@ ThreadCreate(TThread ** const threadPP, else if (rc == 0) { /* This is the child */ (*func)(userHandle); + /* Note that thread cleanup (threadDone) is done by the _parent_, + upon seeing our exit. + */ exit(0); } else { /* This is the parent */ @@ -249,7 +253,8 @@ ThreadWaitAndRelease(TThread * const threadP) { void -ThreadExit(int const retValue) { +ThreadExit(TThread * const threadP ATTR_UNUSED, + 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 @@ -259,6 +264,10 @@ ThreadExit(int const retValue) { sees we've gone. */ + /* Note that thread cleanup (threadDone) is done by the _parent_, + upon seeing our exit. + */ + exit(retValue); } diff --git a/libs/xmlrpc-c/lib/abyss/src/thread_pthread.c b/libs/xmlrpc-c/lib/abyss/src/thread_pthread.c index 5cca825..7c6b2a7 100644 --- a/libs/xmlrpc-c/lib/abyss/src/thread_pthread.c +++ b/libs/xmlrpc-c/lib/abyss/src/thread_pthread.c @@ -7,6 +7,7 @@ #include "bool.h" #include "mallocvar.h" +#include "xmlrpc-c/util_int.h" #include "xmlrpc-c/string_int.h" #include "pthreadx.h" @@ -23,12 +24,12 @@ struct abyss_thread { TThreadDoneFn * threadDone; }; -/* We used to have THREAD_STACK_SIZE = 16K, which was said to be the +/* We used to have MIN_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) +#define MIN_STACK_SIZE (128*1024L) typedef void * (pthreadStartRoutine)(void *); @@ -49,51 +50,63 @@ pthreadStart(void * const arg) { pthread_cleanup_pop(executeTrue); + /* Note that func() may not return; it may just exit the thread, + by calling ThreadExit(), in which case code here doesn't run. + */ + threadP->threadDone(threadP->userHandle); + return NULL; } + void ThreadCreate(TThread ** const threadPP, void * const userHandle, TThreadProc * const func, TThreadDoneFn * const threadDone, bool const useSigchld ATTR_UNUSED, + size_t const stackSize, const char ** const errorP) { - TThread * threadP; - - MALLOCVAR(threadP); - if (threadP == NULL) - xmlrpc_asprintf(errorP, - "Can't allocate memory for thread descriptor."); + if ((size_t)(int)stackSize != stackSize) + xmlrpc_asprintf(errorP, "Stack size %lu is too big", + (unsigned long)stackSize); else { - pthread_attr_t attr; - int rc; + 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_init(&attr); - pthread_attr_setstacksize(&attr, THREAD_STACK_SIZE); + pthread_attr_setstacksize(&attr, MAX(MIN_STACK_SIZE, stackSize)); - 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)); + 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); + pthread_attr_destroy(&attr); - if (*errorP) - free(threadP); + if (*errorP) + free(threadP); + } } } @@ -134,7 +147,8 @@ ThreadWaitAndRelease(TThread * const threadP) { void -ThreadExit(int const retValue) { +ThreadExit(TThread * const threadP ATTR_UNUSED, + int const retValue) { pthread_exit((void*)&retValue); diff --git a/libs/xmlrpc-c/lib/abyss/src/thread_windows.c b/libs/xmlrpc-c/lib/abyss/src/thread_windows.c index dae5bb5..f173f1b 100644 --- a/libs/xmlrpc-c/lib/abyss/src/thread_windows.c +++ b/libs/xmlrpc-c/lib/abyss/src/thread_windows.c @@ -15,6 +15,7 @@ #include "bool.h" #include "int.h" +#include "xmlrpc-c/util_int.h" #include "mallocvar.h" #include "xmlrpc-c/string_int.h" @@ -24,7 +25,6 @@ #include "thread.h" - struct abyss_thread { HANDLE handle; void * userHandle; @@ -32,7 +32,7 @@ struct abyss_thread { TThreadDoneFn * threadDone; }; -#define THREAD_STACK_SIZE (16*1024L) +#define MIN_THREAD_STACK_SIZE (16*1024L) typedef uint32_t (WINAPI WinThreadProc)(void *); @@ -60,6 +60,7 @@ ThreadCreate(TThread ** const threadPP, TThreadProc * const func, TThreadDoneFn * const threadDone, bool const useSigchld, + size_t const stackSize, const char ** const errorP) { TThread * threadP; @@ -76,12 +77,13 @@ ThreadCreate(TThread ** const threadPP, threadP->func = func; threadP->threadDone = threadDone; - threadP->handle = (HANDLE)_beginthreadex(NULL, - THREAD_STACK_SIZE, - threadRun, - threadP, - CREATE_SUSPENDED, - &z); + threadP->handle = (HANDLE) + _beginthreadex(NULL, + MAX(stackSize, MIN_THREAD_STACK_SIZE), + threadRun, + threadP, + CREATE_SUSPENDED, + &z); if (threadP->handle == NULL) xmlrpc_asprintf(errorP, "_beginthreadex() failed."); @@ -121,13 +123,17 @@ ThreadKill(TThread * const threadP) { void ThreadWaitAndRelease(TThread * const threadP) { + WaitForSingleObject(threadP->handle, INFINITE); ThreadRelease(threadP); } void -ThreadExit(int const retValue) { +ThreadExit(TThread * const threadP, + int const retValue) { + + threadP->threadDone(threadP->userHandle); _endthreadex(retValue); } @@ -138,6 +144,7 @@ void ThreadRelease(TThread * const threadP) { CloseHandle(threadP->handle); + free(threadP); } @@ -190,8 +197,6 @@ MutexCreate(TMutex ** const mutexPP) { *mutexPP = mutexP; - TraceMsg( "Created Mutex %s\n", (succeeded ? "ok" : "FAILED") ); - return succeeded; } diff --git a/libs/xmlrpc-c/lib/abyss/version.txt b/libs/xmlrpc-c/lib/abyss/version.txt deleted file mode 100644 index 13874ba..0000000 --- a/libs/xmlrpc-c/lib/abyss/version.txt +++ /dev/null @@ -1 +0,0 @@ -0.3 (03/23/2000) \ No newline at end of file diff --git a/libs/xmlrpc-c/lib/curl_transport/Makefile b/libs/xmlrpc-c/lib/curl_transport/Makefile index c9e144f..a257749 100644 --- a/libs/xmlrpc-c/lib/curl_transport/Makefile +++ b/libs/xmlrpc-c/lib/curl_transport/Makefile @@ -10,30 +10,34 @@ include $(BLDDIR)/config.mk default: all +MODS := xmlrpc_curl_transport curltransaction curlmulti lock_pthread + .PHONY: all -all: xmlrpc_curl_transport.o xmlrpc_curl_transport.osh +all: $(MODS:%=%.o) $(MODS:%=%.osh) # Rules for the above dependencies are in common.mk, # courtesy of TARGET_MODS. -TARGET_MODS = xmlrpc_curl_transport +TARGET_MODS = $(MODS) OMIT_CURL_TRANSPORT_RULE=Y 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 CURL_INCLUDES := $(shell curl-config --cflags) # We expect that curl-config --cflags just gives us -I options, because # we need just the -I options for 'make dep'. Plus, it's scary to think # of what any other compiler flag would do to our compile. -CFLAGS = $(CFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD) - INCLUDES = \ -I$(BLDDIR) \ -I$(BLDDIR)/include \ - -I$(SRCDIR)/include \ - -I$(SRCDIR)/lib/util/include \ + -Isrcdir/include \ + -Isrcdir/lib/util/include \ $(CURL_INCLUDES) .PHONY: clean @@ -54,8 +58,8 @@ install: .PHONY: dep dep: dep-common -include Makefile.depend +include depend.mk -# Need this dependency for those who don't use Makefile.depend. +# Need this dependency for those who don't use depend.mk. # Without it, version.h doesn't get created. xmlrpc_curl_transport.o xmlrpc_curl_transport.osh: version.h diff --git a/libs/xmlrpc-c/lib/curl_transport/Makefile.depend b/libs/xmlrpc-c/lib/curl_transport/Makefile.depend deleted file mode 100644 index e69de29..0000000 diff --git a/libs/xmlrpc-c/lib/curl_transport/curlmulti.c b/libs/xmlrpc-c/lib/curl_transport/curlmulti.c new file mode 100644 index 0000000..8f985de --- /dev/null +++ b/libs/xmlrpc-c/lib/curl_transport/curlmulti.c @@ -0,0 +1,313 @@ +/*============================================================================= + curlMulti +=============================================================================== + 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. +=============================================================================*/ + +#define _XOPEN_SOURCE 600 /* Make sure strdup() is in */ + +#include "xmlrpc_config.h" + +#include +#if HAVE_SYS_SELECT_H +#include +#endif + +#include +#include +#include +#include + +#include "mallocvar.h" +#include "xmlrpc-c/util.h" +#include "xmlrpc-c/string_int.h" + +#include "curlversion.h" +#include "lock.h" +#include "lock_pthread.h" + +#include "curlmulti.h" + + + +static void +interpretCurlMultiError(const char ** const descriptionP, + CURLMcode const code) { + +#if HAVE_CURL_STRERROR + *descriptionP = strdup(curl_multi_strerror(code)); +#else + xmlrpc_asprintf(descriptionP, "Curl error code (CURLMcode) %d", code); +#endif +} + + + +struct curlMulti { + 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 * +curlMulti_create(void) { + + curlMulti * retval; + curlMulti * curlMultiP; + + MALLOCVAR(curlMultiP); + + if (curlMultiP == NULL) + retval = NULL; + else { + curlMultiP->lockP = curlLock_create_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; +} + + + +void +curlMulti_destroy(curlMulti * const curlMultiP) { + + curl_multi_cleanup(curlMultiP->curlMultiP); + + curlMultiP->lockP->destroy(curlMultiP->lockP); + + free(curlMultiP); +} + + + +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->acquire(curlMultiP->lockP); + + rc = curl_multi_perform(curlMultiP->curlMultiP, runningHandlesP); + + curlMultiP->lockP->release(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); + } + } +} + + + +void +curlMulti_addHandle(xmlrpc_env * const envP, + curlMulti * const curlMultiP, + CURL * const curlSessionP) { + + CURLMcode rc; + + curlMultiP->lockP->acquire(curlMultiP->lockP); + + rc = curl_multi_add_handle(curlMultiP->curlMultiP, curlSessionP); + + curlMultiP->lockP->release(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); + } +} + + +void +curlMulti_removeHandle(curlMulti * const curlMultiP, + CURL * const curlSessionP) { + + curlMultiP->lockP->acquire(curlMultiP->lockP); + + curl_multi_remove_handle(curlMultiP->curlMultiP, curlSessionP); + + curlMultiP->lockP->release(curlMultiP->lockP); +} + + + +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->acquire(curlMultiP->lockP); + + privateCurlMsgP = curl_multi_info_read(curlMultiP->curlMultiP, + &remainingMsgCount); + + if (privateCurlMsgP == NULL) + *endOfMessagesP = true; + else { + *endOfMessagesP = false; + *curlMsgP = *privateCurlMsgP; + } + curlMultiP->lockP->release(curlMultiP->lockP); +} + + + +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->acquire(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->release(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); + } +} + + + +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; +} + + + diff --git a/libs/xmlrpc-c/lib/curl_transport/curlmulti.h b/libs/xmlrpc-c/lib/curl_transport/curlmulti.h new file mode 100644 index 0000000..265ed0c --- /dev/null +++ b/libs/xmlrpc-c/lib/curl_transport/curlmulti.h @@ -0,0 +1,51 @@ +#ifndef CURLMULTI_H_INCLUDED +#define CURLMULTI_H_INCLUDED + +#include "bool.h" +#include "xmlrpc-c/util.h" + +#include "curltransaction.h" + +typedef struct curlMulti curlMulti; + +curlMulti * +curlMulti_create(void); + +void +curlMulti_destroy(curlMulti * const curlMultiP); + +void +curlMulti_perform(xmlrpc_env * const envP, + curlMulti * const curlMultiP, + bool * const immediateWorkToDoP, + int * const runningHandlesP); + +void +curlMulti_addHandle(xmlrpc_env * const envP, + curlMulti * const curlMultiP, + CURL * const curlSessionP); + +void +curlMulti_removeHandle(curlMulti * const curlMultiP, + CURL * const curlSessionP); + +void +curlMulti_getMessage(curlMulti * const curlMultiP, + bool * const endOfMessagesP, + CURLMsg * const curlMsgP); + +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); + +void +curlMulti_updateFdSet(curlMulti * const curlMultiP, + fd_set const readFdSet, + fd_set const writeFdSet, + fd_set const exceptFdSet); + +#endif diff --git a/libs/xmlrpc-c/lib/curl_transport/curltransaction.c b/libs/xmlrpc-c/lib/curl_transport/curltransaction.c new file mode 100644 index 0000000..0d3d65f --- /dev/null +++ b/libs/xmlrpc-c/lib/curl_transport/curltransaction.c @@ -0,0 +1,753 @@ +/*============================================================================= + curlTransaction +=============================================================================*/ + +#define _XOPEN_SOURCE 600 /* Make sure strdup() is in */ + +#include +#include +#include + +#include "mallocvar.h" + +#include "xmlrpc-c/util.h" +#include "xmlrpc-c/string_int.h" +#include "xmlrpc-c/client.h" +#include "xmlrpc-c/client_int.h" +#include "version.h" + +#include +#include +#include + +#include "curlversion.h" + +#include "curltransaction.h" + + +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. + */ + curlt_finishFn * finish; + curlt_progressFn * progress; + void * userContextP; + /* Meaningful to our client; opaque to us */ + 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 +addHeader(xmlrpc_env * const envP, + struct curl_slist ** const headerListP, + const char * const headerText) { + + struct curl_slist * newHeaderList; + newHeaderList = curl_slist_append(*headerListP, headerText); + if (newHeaderList == NULL) + xmlrpc_faultf(envP, + "Could not add header '%s'. " + "curl_slist_append() failed.", headerText); + else + *headerListP = newHeaderList; +} + + + +static void +addContentTypeHeader(xmlrpc_env * const envP, + struct curl_slist ** const headerListP) { + + addHeader(envP, headerListP, "Content-Type: text/xml"); +} + + + +static const char * +xmlrpcUserAgentPart(bool const reportIt) { + + const char * retval; + + if (reportIt) { + curl_version_info_data * const curlInfoP = + curl_version_info(CURLVERSION_NOW); + char curlVersion[32]; + + snprintf(curlVersion, sizeof(curlVersion), "%u.%u.%u", + (curlInfoP->version_num >> 16) && 0xff, + (curlInfoP->version_num >> 8) && 0xff, + (curlInfoP->version_num >> 0) && 0xff + ); + + xmlrpc_asprintf(&retval, + "Xmlrpc-c/%s Curl/%s", + XMLRPC_C_VERSION, curlVersion); + } else + xmlrpc_asprintf(&retval, "%s", ""); + + return retval; +} + + + +static void +addUserAgentHeader(xmlrpc_env * const envP, + struct curl_slist ** const headerListP, + bool const reportXmlrpc, + const char * const userAgent) { +/*---------------------------------------------------------------------------- + Add a User-Agent HTTP header to the Curl header list *headerListP, + if appropriate. + + 'reportXmlrpc' means we want to tell the client what XML-RPC agent + is being used -- Xmlrpc-c and layers below. + + 'userAgent' is a string describing the layers above Xmlrpc-c. We + assume it is in the proper format to be included in a User-Agent + header. (We should probably fix that some day -- take ownership + of that format). +-----------------------------------------------------------------------------*/ + if (reportXmlrpc || userAgent) { + /* Add the header */ + + /* 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. + */ + + const char * const xmlrpcPart = xmlrpcUserAgentPart(reportXmlrpc); + + if (xmlrpc_strnomem(xmlrpcPart)) + xmlrpc_faultf(envP, "Couldn't allocate memory for " + "User-Agent header"); + else { + const char * const userPart = userAgent ? userAgent : ""; + const char * const space = userAgent && reportXmlrpc ? " " : ""; + + const char * userAgentHeader; + + xmlrpc_asprintf(&userAgentHeader, + "User-Agent: %s%s%s", + userPart, space, xmlrpcPart); + + if (xmlrpc_strnomem(userAgentHeader)) + xmlrpc_faultf(envP, "Couldn't allocate memory for " + "User-Agent header"); + else { + addHeader(envP, headerListP, userAgentHeader); + + xmlrpc_strfree(userAgentHeader); + } + xmlrpc_strfree(xmlrpcPart); + } + } +} + + + +static void +addAuthorizationHeader(xmlrpc_env * const envP, + struct curl_slist ** const headerListP, + const char * const hdrValue) { + + const char * authorizationHeader; + + xmlrpc_asprintf(&authorizationHeader, "Authorization: %s", hdrValue); + + if (xmlrpc_strnomem(authorizationHeader)) + xmlrpc_faultf(envP, "Couldn't allocate memory for " + "Authorization header"); + else { + addHeader(envP, headerListP, authorizationHeader); + + xmlrpc_strfree(authorizationHeader); + } +} + + + +/* + In HTTP 1.1, the client can send the header "Expect: 100-continue", which + tells the server that the client isn't going to send the body until the + server tells it to by sending a "continue" response (HTTP response code 100). + The server is obligated to send that response. + + However, many servers are broken and don't send the Continue response. + + Early libcurl did not send the Expect: header, thus worked fine with such + broken servers. But as of ca. 2007, libcurl sends the Expect:, and waits + for the response, when the body is large. It gives up after 3 seconds and + sends the body anyway. + + To accomodate the broken servers and for backward compatibility, we always + force libcurl not to send the Expect and consequently not to wait for the + response, using the hackish (but according to libcurl design) method of + including an entry in our explicit header list that is an Expect: header + with an empty argument. This causes libcurl not to send any Expect: header. + This is since 1.19; we may find there are also servers and/or libcurl levels + that can't work with that. + + We may find a case where the Expect/Continue protocol is desirable. If we + do, we should add a transport option to request the function and let libcurl + do its thing when the user requests it. + + The purpose of Expect/Continue is to save the client the trouble of + generating and/or sending the body when the server is just going to reject + the transaction based on the headers -- like maybe because the body is + too big. +*/ + + +static void +addExpectHeader(xmlrpc_env * const envP, + struct curl_slist ** const headerListP) { + + addHeader(envP, headerListP, "Expect:"); + /* Don't send Expect header. See explanation above. */ +} + + + +static void +createCurlHeaderList(xmlrpc_env * const envP, + const char * const authHdrValue, + bool const dontAdvertise, + 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, !dontAdvertise, userAgent); + if (!envP->fault_occurred) { + if (authHdrValue) + addAuthorizationHeader(envP, &headerList, authHdrValue); + } + if (!envP->fault_occurred) + addExpectHeader(envP, &headerList); + } + if (envP->fault_occurred) + curl_slist_free_all(headerList); + + *headerListP = headerList; +} + + + +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, + double const dlnow, + double const ultotal, + double const ulnow) { +/*---------------------------------------------------------------------------- + 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. 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 pass the call through to the curlTransaction's progress + function (the one that the creator of the curlTransaction registered). + + This function is not as important as it once was for interrupting purposes. + 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. +-----------------------------------------------------------------------------*/ + curlTransaction * const curlTransactionP = contextP; + + bool abort; + + /* We require anyone setting us up as the Curl progress function to + supply a progress function: + */ + assert(curlTransactionP); + assert(curlTransactionP->progress); + + curlTransactionP->progress(curlTransactionP->userContextP, + dltotal, dlnow, ultotal, ulnow, + &abort); + + return abort; +} + + + +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 +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 ); + + assert(XMLRPC_HTTPAUTH_BASIC == CURLAUTH_BASIC ); + assert(XMLRPC_HTTPAUTH_DIGEST == CURLAUTH_DIGEST ); + assert(XMLRPC_HTTPAUTH_GSSNEGOTIATE == CURLAUTH_GSSNEGOTIATE); + assert(XMLRPC_HTTPAUTH_NTLM == CURLAUTH_NTLM ); + + assert(XMLRPC_HTTPPROXY_HTTP == CURLPROXY_HTTP ); + assert(XMLRPC_HTTPPROXY_SOCKS5 == CURLPROXY_SOCKS5 ); +} + + + +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, + bool const dontAdvertise, + const char * const userAgent, + 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. + + *serverInfoP tells what sort of authentication to set up. This is + an embarassment, as the xmlrpc_server_info type is part of the + Xmlrpc-c interface. Some day, we need to replace this with a type + (probably identical) not tied to Xmlrpc-c. +-----------------------------------------------------------------------------*/ + CURL * const curlSessionP = curlTransactionP->curlSessionP; + + assertConstantsMatch(); + + /* 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. + */ + + /* It is out policy to do a libcurl call only where necessary, I.e. not + to set what is the default anyhow. The reduction in calls may save + some time, but mostly, it will save us encountering rare bugs or + suffering from backward incompatibilities in future libcurl. I.e. we + don't exercise any more of libcurl than we have to. + */ + + curl_easy_setopt(curlSessionP, CURLOPT_PRIVATE, curlTransactionP); + + 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 (curlTransactionP->progress) { + curl_easy_setopt(curlSessionP, CURLOPT_NOPROGRESS, 0); + curl_easy_setopt(curlSessionP, CURLOPT_PROGRESSFUNCTION, + curlProgress); + curl_easy_setopt(curlSessionP, CURLOPT_PROGRESSDATA, + curlTransactionP); + } 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->proxy) + curl_easy_setopt(curlSessionP, CURLOPT_PROXY, curlSetupP->proxy); + if (curlSetupP->proxyAuth != CURLAUTH_BASIC) + /* Note that the Xmlrpc-c default and the Curl default are + different. Xmlrpc-c is none, while Curl is basic. One reason + for this is that it makes our extensible parameter list scheme, + wherein zero always means default, easier. + */ + curl_easy_setopt(curlSessionP, CURLOPT_PROXYAUTH, + curlSetupP->proxyAuth); + if (curlSetupP->proxyPort) + curl_easy_setopt(curlSessionP, CURLOPT_PROXYPORT, + curlSetupP->proxyPort); + if (curlSetupP->proxyUserPwd) + curl_easy_setopt(curlSessionP, CURLOPT_PROXYUSERPWD, + curlSetupP->proxyUserPwd); + if (curlSetupP->proxyType) + curl_easy_setopt(curlSessionP, CURLOPT_PROXYTYPE, + curlSetupP->proxyType); + + if (curlSetupP->verbose) + curl_easy_setopt(curlSessionP, CURLOPT_VERBOSE, 1l); + + 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, + dontAdvertise, userAgent, + &headerList); + if (!envP->fault_occurred) { + curl_easy_setopt( + curlSessionP, CURLOPT_HTTPHEADER, headerList); + curlTransactionP->headerList = headerList; + } + if (authHdrValue) + xmlrpc_strfree(authHdrValue); + } + } + } +} + + + +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, + bool const dontAdvertise, + const char * const userAgent, + const struct curlSetup * const curlSetupStuffP, + void * const userContextP, + curlt_finishFn * const finish, + curlt_progressFn * const progress, + curlTransaction ** const curlTransactionPP) { + + curlTransaction * curlTransactionP; + + MALLOCVAR(curlTransactionP); + if (curlTransactionP == NULL) + xmlrpc_faultf(envP, "No memory to create Curl transaction."); + else { + curlTransactionP->finish = finish; + curlTransactionP->curlSessionP = curlSessionP; + curlTransactionP->userContextP = userContextP; + curlTransactionP->progress = progress; + + 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, dontAdvertise, userAgent, + curlSetupStuffP); + + if (envP->fault_occurred) + xmlrpc_strfree(curlTransactionP->serverUrl); + } + if (envP->fault_occurred) + free(curlTransactionP); + } + *curlTransactionPP = curlTransactionP; +} + + + +void +curlTransaction_destroy(curlTransaction * const curlTransactionP) { + + curl_slist_free_all(curlTransactionP->headerList); + xmlrpc_strfree(curlTransactionP->serverUrl); + + free(curlTransactionP); +} + + + +static void +interpretCurlEasyError(const char ** const descriptionP, + CURLcode const code) { + +#if HAVE_CURL_STRERROR + *descriptionP = strdup(curl_easy_strerror(code)); +#else + xmlrpc_asprintf(descriptionP, "Curl error code (CURLcode) %d", code); +#endif +} + + + +void +curlTransaction_getError(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, explaining: %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); + } + } +} + + + +void +curlTransaction_finish(xmlrpc_env * const envP, + curlTransaction * const curlTransactionP, + CURLcode const result) { + + curlTransactionP->result = result; + + if (curlTransactionP->finish) + curlTransactionP->finish(envP, curlTransactionP->userContextP); +} + + + +CURL * +curlTransaction_curlSession(curlTransaction * const curlTransactionP) { + + return curlTransactionP->curlSessionP; + +} diff --git a/libs/xmlrpc-c/lib/curl_transport/curltransaction.h b/libs/xmlrpc-c/lib/curl_transport/curltransaction.h new file mode 100644 index 0000000..4edc365 --- /dev/null +++ b/libs/xmlrpc-c/lib/curl_transport/curltransaction.h @@ -0,0 +1,120 @@ +#ifndef CURLTRANSACTION_H_INCLUDED +#define CURLTRANSACTION_H_INCLUDED + +#include "bool.h" +#include "xmlrpc-c/util.h" +#include "xmlrpc-c/client.h" +#include + +typedef struct curlTransaction curlTransaction; + +typedef void curlt_finishFn(xmlrpc_env * const, void * const); +typedef void curlt_progressFn( + void * const, double const, double const, double const, double const, + bool * const); + +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. + */ + + 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 + that the Curl recognizes for setting its CURLOPT_INTERFACE + option (also the --interface option of the Curl program). + E.g. "9.1.72.189" or "giraffe-data.com" or "eth0". + + It isn't necessarily valid, but it does have a terminating NUL. + + NULL means we have no preference. + */ + bool sslVerifyPeer; + /* In an SSL connection, we should authenticate the server's SSL + certificate -- refuse to talk to him if it isn't authentic. + This is equivalent to Curl's CURLOPT_SSL_VERIFY_PEER option. + */ + bool sslVerifyHost; + /* In an SSL connection, we should verify that the server's + certificate (independently of whether the certificate is + authentic) indicates the host name that is in the URL we + are using for the server. + */ + + 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; + + const char * proxy; + unsigned int proxyPort; + unsigned int proxyAuth; + /* e.g. CURLAUTH_BASIC, CURLAUTH_NTLM, ... */ + const char * proxyUserPwd; + unsigned int proxyType; + /* see enum curl_proxytype: CURLPROXY_HTTP, CURLPROXY_SOCKS4, ... */ + + unsigned int timeout; + /* 0 = no Curl timeout. This is in milliseconds. */ + + bool verbose; +}; + + +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, + bool const dontAdvertise, + const char * const userAgent, + const struct curlSetup * const curlSetupStuffP, + void * const userContextP, + curlt_finishFn * const finish, + curlt_progressFn * const progress, + curlTransaction ** const curlTransactionPP); + +void +curlTransaction_destroy(curlTransaction * const curlTransactionP); + +void +curlTransaction_finish(xmlrpc_env * const envP, + curlTransaction * const curlTransactionP, + CURLcode const result); + +void +curlTransaction_getError(curlTransaction * const curlTransactionP, + xmlrpc_env * const envP); + +CURL * +curlTransaction_curlSession(curlTransaction * const curlTransactionP); + +#endif diff --git a/libs/xmlrpc-c/lib/curl_transport/curlversion.h b/libs/xmlrpc-c/lib/curl_transport/curlversion.h new file mode 100644 index 0000000..71c5a68 --- /dev/null +++ b/libs/xmlrpc-c/lib/curl_transport/curlversion.h @@ -0,0 +1,20 @@ +#ifndef CURLVERSION_H_INCLUDED +#define CURLVERSION_H_INCLUDED + +#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 + +#endif diff --git a/libs/xmlrpc-c/lib/curl_transport/lock.h b/libs/xmlrpc-c/lib/curl_transport/lock.h new file mode 100644 index 0000000..bb7ce42 --- /dev/null +++ b/libs/xmlrpc-c/lib/curl_transport/lock.h @@ -0,0 +1,24 @@ +#ifndef CURL_LOCK_H_INCLUDED +#define CURL_LOCK_H_INCLUDED + +#include + +typedef struct lock lock; + +typedef void lockAcquireFn(lock *); +typedef void lockReleaseFn(lock *); +typedef void lockDestroyFn(lock *); + +struct lock { + /* To finish the job of making an abstract lock class that can use locks + other than pthread mutexes, we need to replace 'theLock' with a + "void * implementationP" and make curlLock_create_pthread() malloc + the mutex. + */ + pthread_mutex_t theLock; + lockAcquireFn * acquire; + lockReleaseFn * release; + lockDestroyFn * destroy; +}; + +#endif diff --git a/libs/xmlrpc-c/lib/curl_transport/lock_pthread.c b/libs/xmlrpc-c/lib/curl_transport/lock_pthread.c new file mode 100644 index 0000000..24b029e --- /dev/null +++ b/libs/xmlrpc-c/lib/curl_transport/lock_pthread.c @@ -0,0 +1,49 @@ +#include + +#include "mallocvar.h" +#include "pthreadx.h" + +#include "lock.h" + +#include "lock_pthread.h" + +static lockAcquireFn acquire; + +static void +acquire(struct lock * const lockP) { + pthread_mutex_lock(&lockP->theLock); +} + + + +static lockReleaseFn release; + +static void +release(struct lock * const lockP) { + pthread_mutex_unlock(&lockP->theLock); +} + + + +static lockDestroyFn destroy; + +static void +destroy(struct lock * const lockP) { + pthread_mutex_destroy(&lockP->theLock); + free(lockP); +} + + + +struct lock * +curlLock_create_pthread(void) { + struct lock * lockP; + MALLOCVAR(lockP); + if (lockP) { + pthread_mutex_init(&lockP->theLock, NULL); + lockP->acquire = &acquire; + lockP->release = &release; + lockP->destroy = &destroy; + } + return lockP; +} diff --git a/libs/xmlrpc-c/lib/curl_transport/lock_pthread.h b/libs/xmlrpc-c/lib/curl_transport/lock_pthread.h new file mode 100644 index 0000000..49ffa51 --- /dev/null +++ b/libs/xmlrpc-c/lib/curl_transport/lock_pthread.h @@ -0,0 +1,9 @@ +#ifndef CURL_LOCK_PTHREAD_H_INCLUDED +#define CURL_LOCK_PTHREAD_H_INCLUDED + +#include "lock.h" + +lock * +curlLock_create_pthread(void); + +#endif diff --git a/libs/xmlrpc-c/lib/curl_transport/xmlrpc_curl_transport.c b/libs/xmlrpc-c/lib/curl_transport/xmlrpc_curl_transport.c index 29104b9..fe705b9 100644 --- a/libs/xmlrpc-c/lib/curl_transport/xmlrpc_curl_transport.c +++ b/libs/xmlrpc-c/lib/curl_transport/xmlrpc_curl_transport.c @@ -52,6 +52,8 @@ such subordinate libraries as OpenSSL and Winsock. -----------------------------------------------------------------------------*/ +#define _XOPEN_SOURCE 600 /* Make sure strdup() is in */ + #include "xmlrpc_config.h" #include @@ -59,7 +61,7 @@ #include #include #include -#if !MSVCRT +#if HAVE_SYS_SELECT_H #include #endif #include @@ -75,18 +77,24 @@ #include "girstring.h" #include "pthreadx.h" +#include "xmlrpc-c/util.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 #include #include #include +#include "lock.h" +#include "lock_pthread.h" +#include "curltransaction.h" +#include "curlmulti.h" +#include "curlversion.h" + #if MSVCRT #if defined(_DEBUG) # include @@ -98,92 +106,8 @@ #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. - */ - - 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 - that the Curl recognizes for setting its CURLOPT_INTERFACE - option (also the --interface option of the Curl program). - E.g. "9.1.72.189" or "giraffe-data.com" or "eth0". - - It isn't necessarily valid, but it does have a terminating NUL. - - NULL means we have no preference. - */ - xmlrpc_bool sslVerifyPeer; - /* In an SSL connection, we should authenticate the server's SSL - certificate -- refuse to talk to him if it isn't authentic. - This is equivalent to Curl's CURLOPT_SSL_VERIFY_PEER option. - */ - xmlrpc_bool sslVerifyHost; - /* In an SSL connection, we should verify that the server's - certificate (independently of whether the certificate is - authentic) indicates the host name that is in the URL we - are using for the server. - */ - - 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 int @@ -239,939 +163,248 @@ addMilliseconds(xmlrpc_timespec const addend, -/*============================================================================ - 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; +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). + */ + bool dontAdvertise; + /* Don't identify to the server the XML-RPC engine we are using. If + false, include a User-Agent HTTP header in all requests that + identifies the Xmlrpc-c and Curl libraries. -static void -lock_pthread(struct lock * const lockP) { - pthread_mutex_lock(&lockP->theLock); -} + See also 'userAgent'. -static void -unlock_pthread(struct lock * const lockP) { - pthread_mutex_unlock(&lockP->theLock); -} + This is constant. + */ + const char * userAgent; + /* Information to include in a User-Agent HTTP header, reflecting + facilities outside of Xmlrpc-c. -static void -destroyLock_pthread(struct lock * const lockP) { - pthread_mutex_destroy(&lockP->theLock); - free(lockP); -} + Null means none. + The full User-Agent header value is this information (if + 'userAgent' is non-null) followed by identification of Xmlrpc-c + and Curl (if 'dontAdvertise' is false). If 'userAgent' is null + and 'dontAdvertise' is true, we put no User-Agent header at all + in the request. -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; -} + 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. + This is constant. + */ +}; -/*============================================================================= - curlTransaction -=============================================================================*/ -typedef void finishCurlTransactionFn(xmlrpc_env * const, curlTransaction * const); -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. - */ +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. + */ 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. + /* The Curl session to use for the Curl transaction to perform + the RPC. */ - 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). + 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. */ - 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. + xmlrpc_transport_progress progress; + /* Routine to call periodically to report the progress of transporting + the call and response. NULL if none. */ - 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 */ + struct xmlrpc_call_info * callInfoP; + /* User's identifier for this RPC */ }; - static void -interpretCurlEasyError(const char ** const descriptionP, - CURLcode const code) { - -#if HAVE_CURL_STRERROR - *descriptionP = strdup(curl_easy_strerror(code)); -#else - xmlrpc_asprintf(descriptionP, "Curl error code (CURLcode) %d", code); -#endif +lockSyncCurlSession(struct xmlrpc_client_transport * const transportP) { + transportP->syncCurlSessionLockP->acquire( + transportP->syncCurlSessionLockP); } static void -interpretCurlMultiError(const char ** const descriptionP, - CURLMcode const code) { - -#if HAVE_CURL_STRERROR - *descriptionP = strdup(curl_multi_strerror(code)); -#else - xmlrpc_asprintf(descriptionP, "Curl error code (CURLMcode) %d", code); -#endif +unlockSyncCurlSession(struct xmlrpc_client_transport * const transportP) { + transportP->syncCurlSessionLockP->release( + transportP->syncCurlSessionLockP); } static void -addHeader(xmlrpc_env * const envP, - struct curl_slist ** const headerListP, - const char * const headerText) { - - struct curl_slist * newHeaderList; - newHeaderList = curl_slist_append(*headerListP, headerText); - if (newHeaderList == NULL) - xmlrpc_faultf(envP, - "Could not add header '%s'. " - "curl_slist_append() failed.", headerText); - else - *headerListP = newHeaderList; -} - - +initWindowsStuff(xmlrpc_env * const envP ATTR_UNUSED) { -static void -addContentTypeHeader(xmlrpc_env * const envP, - struct curl_slist ** const headerListP) { +#if defined (WIN32) + /* This is CRITICAL so that cURL-Win32 works properly! */ - addHeader(envP, headerListP, "Content-Type: text/xml"); -} - - - -static void -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. - */ + /* 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); - curl_version_info_data * const curlInfoP = - curl_version_info(CURLVERSION_NOW); - char curlVersion[32]; - const char * userAgentHeader; - - snprintf(curlVersion, sizeof(curlVersion), "%u.%u.%u", - (curlInfoP->version_num >> 16) && 0xff, - (curlInfoP->version_num >> 8) && 0xff, - (curlInfoP->version_num >> 0) && 0xff - ); - - xmlrpc_asprintf(&userAgentHeader, - "User-Agent: %s Xmlrpc-c/%s Curl/%s", - userAgent, XMLRPC_C_VERSION, curlVersion); - - if (userAgentHeader == xmlrpc_strsol) - xmlrpc_faultf(envP, "Couldn't allocate memory for " - "User-Agent header"); - else { - addHeader(envP, headerListP, userAgentHeader); - - xmlrpc_strfree(userAgentHeader); + 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 -addAuthorizationHeader(xmlrpc_env * const envP, - struct curl_slist ** const headerListP, - const char * const hdrValue) { +termWindowsStuff(void) { - 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); - } +#if defined (WIN32) + WSACleanup(); +#endif } -static void -createCurlHeaderList(xmlrpc_env * const envP, - const char * const authHdrValue, - const char * const userAgent, - struct curl_slist ** const headerListP) { +static bool +curlHasNosignal(void) { - struct curl_slist * headerList; + bool retval; - headerList = NULL; /* initial value - empty list */ +#if HAVE_CURL_NOSIGNAL + curl_version_info_data * const curlInfoP = + curl_version_info(CURLVERSION_NOW); - 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; + retval = (curlInfoP->version_num >= 0x070A00); /* 7.10.0 */ +#else + retval = false; +#endif + return retval; } -static void -assertConstantsMatch(void) { +static xmlrpc_timespec +pselectTimeout(xmlrpc_timeoutType const timeoutType, + xmlrpc_timespec const timeoutDt) { /*---------------------------------------------------------------------------- - 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. + 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'. -----------------------------------------------------------------------------*/ - 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); -} - + unsigned int const million = 1000000; + unsigned int selectTimeoutMillisec; + xmlrpc_timespec retval; + /* 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; -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; + xmlrpc_gettimeofday(&nowTime); + timeLeft = timeDiffMillisec(timeoutDt, nowTime); - size_t retval; - xmlrpc_env env; + selectTimeoutMillisec = MIN(3000, MAX(0, timeLeft)); + } break; + } + retval.tv_sec = selectTimeoutMillisec / 1000; + retval.tv_nsec = (uint32_t)((selectTimeoutMillisec % 1000) * million); - 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); +processCurlMessages(xmlrpc_env * const envP, + curlMulti * const curlMultiP) { + + bool endOfMessages; - 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); -} + endOfMessages = false; /* initial assumption */ + while (!endOfMessages && !envP->fault_occurred) { + CURLMsg curlMsg; -static void -setCurlTimeout(CURL * const curlSessionP ATTR_UNUSED, - unsigned int const timeout ATTR_UNUSED) { + curlMulti_getMessage(curlMultiP, &endOfMessages, &curlMsg); -#if HAVE_CURL_NOSIGNAL - unsigned int const timeoutMs = (timeout + 999)/1000; + if (!endOfMessages) { + if (curlMsg.msg == CURLMSG_DONE) { + curlTransaction * curlTransactionP; - curl_easy_setopt(curlSessionP, CURLOPT_NOSIGNAL, 1); + curl_easy_getinfo(curlMsg.easy_handle, CURLINFO_PRIVATE, + (void *)&curlTransactionP); - 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); - } - } - } + curlTransaction_finish(envP, + curlTransactionP, curlMsg.data.result); + } + } + } } @@ -1237,411 +470,141 @@ waitForWork(xmlrpc_env * const envP, 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. - */ -}; +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. -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 */ -}; + 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); -static void -lockSyncCurlSession(struct xmlrpc_client_transport * const transportP) { - transportP->syncCurlSessionLockP->lock(transportP->syncCurlSessionLockP); + sigfillset(&allSignals); + + sigprocmask(SIG_BLOCK, &allSignals, &callerBlockSet); + + if (*interruptP == 0) + waitForWork(envP, curlMultiP, timeoutType, deadline, &callerBlockSet); + + sigprocmask(SIG_SETMASK, &callerBlockSet, NULL); +#endif } static void -unlockSyncCurlSession(struct xmlrpc_client_transport * const transportP) { - transportP->syncCurlSessionLockP->unlock(transportP->syncCurlSessionLockP); -} +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 */ -static void -initWindowsStuff(xmlrpc_env * const envP ATTR_UNUSED) { + while (immediateWorkToDo && !envP->fault_occurred) { + curlMulti_perform(envP, curlMultiP, + &immediateWorkToDo, &runningHandles); + } -#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(); + /* 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; } -#endif } static void -termWindowsStuff(void) { - -#if defined (WIN32) - WSACleanup(); -#endif -} +finishCurlMulti(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; -static bool -curlHasNosignal(void) { + rpcStillRunning = true; /* initial assumption */ + timedOut = false; + + while (rpcStillRunning && !timedOut && !envP->fault_occurred) { - bool retval; + if (interruptP) { + waitForWorkInt(envP, curlMultiP, timeoutType, deadline, + interruptP); + } else + waitForWork(envP, curlMultiP, timeoutType, deadline, NULL); -#if HAVE_CURL_NOSIGNAL - curl_version_info_data * const curlInfoP = - curl_version_info(CURLVERSION_NOW); + if (!envP->fault_occurred) { + xmlrpc_timespec nowTime; - retval = (curlInfoP->version_num >= 0x070A00); /* 7.10.0 */ -#else - retval = false; -#endif - return retval; + /* 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)); + } + } } @@ -1657,7 +620,8 @@ getTimeoutParm(xmlrpc_env * const envP, else { if (curlHasNosignal()) { /* libcurl takes a 'long' in milliseconds for the timeout value */ - if ((curlXportParmsP->timeout + 999) / 1000 > LONG_MAX) + if ((unsigned)(long)(curlXportParmsP->timeout) != + curlXportParmsP->timeout) xmlrpc_faultf(envP, "Timeout value %u is too large.", curlXportParmsP->timeout); else @@ -1673,6 +637,19 @@ getTimeoutParm(xmlrpc_env * const envP, static void +setVerbose(bool * const verboseP) { + + const char * const xmlrpcTraceCurl = getenv("XMLRPC_TRACE_CURL"); + + if (xmlrpcTraceCurl) + *verboseP = true; + else + *verboseP = false; +} + + + +static void getXportParms(xmlrpc_env * const envP, const struct xmlrpc_curl_xportparms * const curlXportParmsP, size_t const parmSize, @@ -1710,6 +687,11 @@ getXportParms(xmlrpc_env * const envP, else transportP->userAgent = strdup(curlXportParmsP->user_agent); + if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(dont_advertise)) + transportP->dontAdvertise = false; + else + transportP->dontAdvertise = curlXportParmsP->dont_advertise; + if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(network_interface)) curlSetupP->networkInterface = NULL; else if (curlXportParmsP->network_interface == NULL) @@ -1764,7 +746,7 @@ getXportParms(xmlrpc_env * const envP, else curlSetupP->sslKeyType = strdup(curlXportParmsP->sslkeytype); - if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(sslkeypasswd)) + if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(sslkeypasswd)) curlSetupP->sslKeyPasswd = NULL; else if (curlXportParmsP->sslkeypasswd == NULL) curlSetupP->sslKeyPasswd = NULL; @@ -1823,6 +805,35 @@ getXportParms(xmlrpc_env * const envP, else curlSetupP->sslCipherList = strdup(curlXportParmsP->ssl_cipher_list); + if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(proxy)) + curlSetupP->proxy = NULL; + else if (curlXportParmsP->proxy == NULL) + curlSetupP->proxy = NULL; + else + curlSetupP->proxy = strdup(curlXportParmsP->proxy); + + if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(proxy_port)) + curlSetupP->proxyPort = 8080; + else + curlSetupP->proxyPort = curlXportParmsP->proxy_port; + + if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(proxy_auth)) + curlSetupP->proxyAuth = CURLAUTH_BASIC; + else + curlSetupP->proxyAuth = curlXportParmsP->proxy_auth; + + if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(proxy_userpwd)) + curlSetupP->proxyUserPwd = NULL; + else if (curlXportParmsP->proxy_userpwd == NULL) + curlSetupP->proxyUserPwd = NULL; + else + curlSetupP->proxyUserPwd = strdup(curlXportParmsP->proxy_userpwd); + + if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(proxy_type)) + curlSetupP->proxyType = CURLPROXY_HTTP; + else + curlSetupP->proxyType = curlXportParmsP->proxy_type; + getTimeoutParm(envP, curlXportParmsP, parmSize, &curlSetupP->timeout); } @@ -1861,6 +872,10 @@ freeXportParms(const struct xmlrpc_client_transport * const transportP) { xmlrpc_strfree(curlSetupP->networkInterface); if (transportP->userAgent) xmlrpc_strfree(transportP->userAgent); + if (curlSetupP->proxy) + xmlrpc_strfree(curlSetupP->proxy); + if (curlSetupP->proxyUserPwd) + xmlrpc_strfree(curlSetupP->proxyUserPwd); } @@ -1921,7 +936,7 @@ static void makeSyncCurlSession(xmlrpc_env * const envP, struct xmlrpc_client_transport * const transportP) { - transportP->syncCurlSessionLockP = createLock_pthread(); + transportP->syncCurlSessionLockP = curlLock_create_pthread(); if (transportP->syncCurlSessionLockP == NULL) xmlrpc_faultf(envP, "Unable to create lock for " "synchronous Curl session."); @@ -1976,12 +991,12 @@ create(xmlrpc_env * const envP, struct xmlrpc_client_transport * transportP; - assertConstantsMatch(); - MALLOCVAR(transportP); if (transportP == NULL) xmlrpc_faultf(envP, "Unable to allocate transport descriptor."); else { + setVerbose(&transportP->curlSetupStuff.verbose); + transportP->interruptP = NULL; transportP->asyncCurlMultiP = curlMulti_create(); @@ -2044,6 +1059,14 @@ static void destroy(struct xmlrpc_client_transport * const clientTransportP) { /*---------------------------------------------------------------------------- This does the 'destroy' operation for a Curl client transport. + + An RPC is a reference to a client XML transport, so you may not + destroy a transport while RPCs are running. To ensure no + asynchronous RPCs are running, you must successfully execute the + transport 'finishAsync' method, with no interruptions or timeouts + allowed. To speed that up, you can set the transport's interrupt + flag to 1 first, which will make all outstanding RPCs fail + immediately. -----------------------------------------------------------------------------*/ XMLRPC_ASSERT(clientTransportP != NULL); @@ -2070,6 +1093,64 @@ destroy(struct xmlrpc_client_transport * const clientTransportP) { static void +performCurlTransaction(xmlrpc_env * const envP, + curlTransaction * const curlTransactionP, + curlMulti * const curlMultiP, + int * const interruptP) { + + curlMulti_addHandle(envP, curlMultiP, + curlTransaction_curlSession(curlTransactionP)); + + /* 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}; + + finishCurlMulti(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? + */ + curlTransaction_getError(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, + curlTransaction_curlSession(curlTransactionP)); + } +} + + + +static void +startRpc(xmlrpc_env * const envP, + rpc * const rpcP) { + + curlMulti_addHandle(envP, + rpcP->transportP->asyncCurlMultiP, + curlTransaction_curlSession(rpcP->curlTransactionP)); +} + + + +static curlt_finishFn finishRpcCurlTransaction; +static curlt_progressFn curlTransactionProgress; + + + +static void createRpc(xmlrpc_env * const envP, struct xmlrpc_client_transport * const clientTransportP, CURL * const curlSessionP, @@ -2077,6 +1158,7 @@ createRpc(xmlrpc_env * const envP, xmlrpc_mem_block * const callXmlP, xmlrpc_mem_block * const responseXmlP, xmlrpc_transport_asynch_complete complete, + xmlrpc_transport_progress progress, struct xmlrpc_call_info * const callInfoP, rpc ** const rpcPP) { @@ -2087,18 +1169,22 @@ createRpc(xmlrpc_env * const envP, xmlrpc_faultf(envP, "Couldn't allocate memory for rpc object"); else { rpcP->transportP = clientTransportP; + rpcP->curlSessionP = curlSessionP; rpcP->callInfoP = callInfoP; rpcP->complete = complete; + rpcP->progress = progress; rpcP->responseXmlP = responseXmlP; curlTransaction_create(envP, curlSessionP, serverP, callXmlP, responseXmlP, + clientTransportP->dontAdvertise, clientTransportP->userAgent, &clientTransportP->curlSetupStuff, rpcP, - clientTransportP->interruptP, + complete ? &finishRpcCurlTransaction : NULL, + progress ? &curlTransactionProgress : NULL, &rpcP->curlTransactionP); if (!envP->fault_occurred) { if (envP->fault_occurred) @@ -2136,11 +1222,11 @@ performRpc(xmlrpc_env * const envP, -static finishCurlTransactionFn finishRpcCurlTransaction; +static curlt_finishFn finishRpcCurlTransaction; static void -finishRpcCurlTransaction(xmlrpc_env * const envP ATTR_UNUSED, - curlTransaction * const curlTransactionP) { +finishRpcCurlTransaction(xmlrpc_env * const envP ATTR_UNUSED, + void * const userContextP) { /*---------------------------------------------------------------------------- Handle the event that a Curl transaction for an asynchronous RPC has completed on the Curl session identified by 'curlSessionP'. @@ -2150,24 +1236,26 @@ finishRpcCurlTransaction(xmlrpc_env * const envP ATTR_UNUSED, 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; + rpc * const rpcP = userContextP; + curlTransaction * const curlTransactionP = rpcP->curlTransactionP; struct xmlrpc_client_transport * const transportP = rpcP->transportP; + curlMulti_removeHandle(transportP->asyncCurlMultiP, + curlTransaction_curlSession(curlTransactionP)); + { xmlrpc_env env; xmlrpc_env_init(&env); - getCurlTransactionError(curlTransactionP, &env); + curlTransaction_getError(curlTransactionP, &env); rpcP->complete(rpcP->callInfoP, rpcP->responseXmlP, env); xmlrpc_env_clean(&env); } - curlMulti_removeHandle(transportP->asyncCurlMultiP, curlTransactionP); - - curl_easy_cleanup(curlTransactionP->curlSessionP); + curl_easy_cleanup(rpcP->curlSessionP); XMLRPC_MEMBLOCK_FREE(char, rpcP->responseXmlP); @@ -2176,14 +1264,49 @@ finishRpcCurlTransaction(xmlrpc_env * const envP ATTR_UNUSED, +static curlt_progressFn curlTransactionProgress; + static void -startRpc(xmlrpc_env * const envP, - rpc * const rpcP) { +curlTransactionProgress(void * const context, + double const dlTotal, + double const dlNow, + double const ulTotal, + double const ulNow, + bool * const abortP) { +/*---------------------------------------------------------------------------- + This is equivalent to a Curl "progress function" (the curlTransaction + object just passes through the call from libcurl). + + The curlTransaction calls this once a second telling us how much + data has transferred. If the transport user has set up a progress + function, we call that with this progress information. That + function might e.g. display a progress bar. + + Additionally, the curlTransaction gives us the opportunity to tell it + to abort the transaction, which we do if the user has set his + "interrupt" flag (which he registered with the transport when he + created it). +-----------------------------------------------------------------------------*/ + rpc * const rpcP = context; + struct xmlrpc_client_transport * const transportP = rpcP->transportP; + + struct xmlrpc_progress_data progressData; - startCurlTransaction(envP, - rpcP->curlTransactionP, - rpcP->transportP->asyncCurlMultiP, - &finishRpcCurlTransaction); + assert(rpcP); + assert(transportP); + assert(rpcP->progress); + + progressData.response.total = dlTotal; + progressData.response.now = dlNow; + progressData.call.total = ulTotal; + progressData.call.now = ulNow; + + rpcP->progress(rpcP->callInfoP, progressData); + + if (transportP->interruptP) + *abortP = *transportP->interruptP; + else + *abortP = false; } @@ -2194,6 +1317,7 @@ sendRequest(xmlrpc_env * const envP, const xmlrpc_server_info * const serverP, xmlrpc_mem_block * const callXmlP, xmlrpc_transport_asynch_complete complete, + xmlrpc_transport_progress progress, struct xmlrpc_call_info * const callInfoP) { /*---------------------------------------------------------------------------- Initiate an XML-RPC rpc asynchronously. Don't wait for it to go to @@ -2216,7 +1340,7 @@ sendRequest(xmlrpc_env * const envP, "curl_easy_init() failed."); else { createRpc(envP, clientTransportP, curlSessionP, serverP, - callXmlP, responseXmlP, complete, callInfoP, + callXmlP, responseXmlP, complete, progress, callInfoP, &rpcP); if (!envP->fault_occurred) { @@ -2282,19 +1406,19 @@ finishAsynch( addMilliseconds(waitStartTime, timeout, &waitTimeoutTime); } - curlMulti_finish(&env, clientTransportP->asyncCurlMultiP, - timeoutType, waitTimeoutTime, - clientTransportP->interruptP); + finishCurlMulti(&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 + problem back up to the user, but for now we just do this Hail Mary response. - Note that a failure of curlMult_finish() does not mean that + Note that a failure of finish_curlMulti() 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 @@ -2339,7 +1463,7 @@ call(xmlrpc_env * const envP, createRpc(envP, clientTransportP, clientTransportP->syncCurlSessionP, serverP, callXmlP, responseXmlP, - NULL, NULL, + NULL, NULL, NULL, &rpcP); if (!envP->fault_occurred) { diff --git a/libs/xmlrpc-c/lib/curl_transport/xmlrpc_curl_transport.h b/libs/xmlrpc-c/lib/curl_transport/xmlrpc_curl_transport.h deleted file mode 100644 index 1425add..0000000 --- a/libs/xmlrpc-c/lib/curl_transport/xmlrpc_curl_transport.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef XMLRPC_CURL_TRANSPORT_H -#define XMLRPC_CURL_TRANSPORT_H - -#include "xmlrpc-c/transport.h" - -extern struct xmlrpc_client_transport_ops xmlrpc_curl_transport_ops; - -#endif diff --git a/libs/xmlrpc-c/lib/expat/.cvsignore b/libs/xmlrpc-c/lib/expat/.cvsignore deleted file mode 100644 index f3c7a7c..0000000 --- a/libs/xmlrpc-c/lib/expat/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -Makefile diff --git a/libs/xmlrpc-c/lib/expat/Makefile b/libs/xmlrpc-c/lib/expat/Makefile new file mode 100644 index 0000000..8feab79 --- /dev/null +++ b/libs/xmlrpc-c/lib/expat/Makefile @@ -0,0 +1,39 @@ +ifeq ($(SRCDIR),) + updir = $(shell echo $(dir $(1)) | sed 's/.$$//') + LIBDIR := $(call updir,$(CURDIR)) + SRCDIR := $(call updir,$(LIBDIR)) + BLDDIR := $(SRCDIR) +endif +SUBDIR := lib/expat + +include $(BLDDIR)/config.mk + +# Build up SUBDIRS: +SUBDIRS = gennmtab xmlparse xmltok + +default: all + +.PHONY: all clean distclean tags distdir intall check dep + +all: $(SUBDIRS:%=%/all) + +clean: $(SUBDIRS:%=%/clean) clean-common + +distclean: $(SUBDIRS:%=%/distclean) distclean-common + +tags: $(SUBDIRS:%=%/tags) TAGS + +DISTFILES = + +distdir: distdir-common + +install: $(SUBDIRS:%=%/install) + +check: + +dep: $(SUBDIRS:%=%/dep) + +include $(SRCDIR)/common.mk + + + diff --git a/libs/xmlrpc-c/lib/expat/Makefile.in b/libs/xmlrpc-c/lib/expat/Makefile.in deleted file mode 100644 index 121de36..0000000 --- a/libs/xmlrpc-c/lib/expat/Makefile.in +++ /dev/null @@ -1,314 +0,0 @@ -# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - - -SHELL = @SHELL@ - -srcdir = @srcdir@ -top_srcdir = @top_srcdir@ -VPATH = @srcdir@ -prefix = @prefix@ -exec_prefix = @exec_prefix@ - -bindir = @bindir@ -sbindir = @sbindir@ -libexecdir = @libexecdir@ -datadir = @datadir@ -sysconfdir = @sysconfdir@ -sharedstatedir = @sharedstatedir@ -localstatedir = @localstatedir@ -libdir = @libdir@ -infodir = @infodir@ -mandir = @mandir@ -includedir = @includedir@ -oldincludedir = /usr/include - -DESTDIR = - -pkgdatadir = $(datadir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ - -top_builddir = ../.. - -ACLOCAL = @ACLOCAL@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ - -INSTALL = @INSTALL@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -transform = @program_transform_name@ - -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -host_alias = @host_alias@ -host_triplet = @host@ -ABYSS_SUBDIR = @ABYSS_SUBDIR@ -AS = @AS@ -ASYNCH_CLIENT = @ASYNCH_CLIENT@ -AUTH_CLIENT = @AUTH_CLIENT@ -AVAILABLE_MODULES = @AVAILABLE_MODULES@ -CC = @CC@ -CC_WARN_FLAGS = @CC_WARN_FLAGS@ -CLIENTTEST = @CLIENTTEST@ -CONFIGURE_DATE = @CONFIGURE_DATE@ -CPPTEST = @CPPTEST@ -CPP_WARN_FLAGS = @CPP_WARN_FLAGS@ -CXX = @CXX@ -DLLTOOL = @DLLTOOL@ -EFRPCTEST = @EFRPCTEST@ -EFRPCTEST_WRAPPER = @EFRPCTEST_WRAPPER@ -INTEROP_CGI = @INTEROP_CGI@ -INTEROP_CLIENT_SUBDIR = @INTEROP_CLIENT_SUBDIR@ -LIBTOOL = @LIBTOOL@ -LIBWWW_CFLAGS = @LIBWWW_CFLAGS@ -LIBWWW_CONFIG = @LIBWWW_CONFIG@ -LIBWWW_LDADD = @LIBWWW_LDADD@ -LIBWWW_LIBDIR = @LIBWWW_LIBDIR@ -LIBWWW_RPATH = @LIBWWW_RPATH@ -LIBWWW_WL_RPATH = @LIBWWW_WL_RPATH@ -LIBXMLRPC_ABYSS_SERVER_LA = @LIBXMLRPC_ABYSS_SERVER_LA@ -LIBXMLRPC_CGI_LA = @LIBXMLRPC_CGI_LA@ -LIBXMLRPC_CLIENT_LA = @LIBXMLRPC_CLIENT_LA@ -LIBXMLRPC_CPP_A = @LIBXMLRPC_CPP_A@ -LN_S = @LN_S@ -MAKEINFO = @MAKEINFO@ -MEERKAT_APP_LIST = @MEERKAT_APP_LIST@ -OBJDUMP = @OBJDUMP@ -PACKAGE = @PACKAGE@ -QUERY_MEERKAT = @QUERY_MEERKAT@ -RANLIB = @RANLIB@ -SAMPLE_CGI_CGI = @SAMPLE_CGI_CGI@ -SERVER = @SERVER@ -SERVERTEST = @SERVERTEST@ -SYNCH_CLIENT = @SYNCH_CLIENT@ -VALIDATEE = @VALIDATEE@ -VERSION = @VERSION@ -VERSION_INFO = @VERSION_INFO@ -XMLRPCCPP_H = @XMLRPCCPP_H@ -XMLRPC_ABYSS_H = @XMLRPC_ABYSS_H@ -XMLRPC_CGI_H = @XMLRPC_CGI_H@ -XMLRPC_CLIENT_H = @XMLRPC_CLIENT_H@ -XML_RPC_API2CPP_SUBDIR = @XML_RPC_API2CPP_SUBDIR@ - -SUBDIRS = gennmtab xmltok xmlparse xmlwf sample -EXTRA_DIST = expat.html expat.dsw -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs -CONFIG_HEADER = ../../xmlrpc_config.h -CONFIG_CLEAN_FILES = -DIST_COMMON = Makefile.in - -DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) - -TAR = gtar -GZIP_ENV = --best -all: all-redirect -.SUFFIXES: - -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - cd $(top_builddir) \ - && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status - - -# This directory's subdirectories are mostly independent; you can cd -# into them and run `make' without going through this Makefile. -# To change the values of `make' variables: instead of editing Makefiles, -# (1) if the variable is set in `config.status', edit `config.status' -# (which will cause the Makefiles to be regenerated when you run `make'); -# (2) otherwise, pass the desired values on the `make' command line. - -@SET_MAKE@ - -all-recursive install-data-recursive install-exec-recursive \ -installdirs-recursive install-recursive uninstall-recursive \ -check-recursive installcheck-recursive info-recursive dvi-recursive: - @set fnord $(MAKEFLAGS); amf=$$2; \ - dot_seen=no; \ - target=`echo $@ | sed s/-recursive//`; \ - list='$(SUBDIRS)'; for subdir in $$list; do \ - echo "Making $$target in $$subdir"; \ - if test "$$subdir" = "."; then \ - dot_seen=yes; \ - local_target="$$target-am"; \ - else \ - local_target="$$target"; \ - fi; \ - (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ - || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ - done; \ - if test "$$dot_seen" = "no"; then \ - $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ - fi; test -z "$$fail" - -mostlyclean-recursive clean-recursive distclean-recursive \ -maintainer-clean-recursive: - @set fnord $(MAKEFLAGS); amf=$$2; \ - dot_seen=no; \ - rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \ - rev="$$subdir $$rev"; \ - test "$$subdir" = "." && dot_seen=yes; \ - done; \ - test "$$dot_seen" = "no" && rev=". $$rev"; \ - target=`echo $@ | sed s/-recursive//`; \ - for subdir in $$rev; do \ - echo "Making $$target in $$subdir"; \ - if test "$$subdir" = "."; then \ - local_target="$$target-am"; \ - else \ - local_target="$$target"; \ - fi; \ - (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ - || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ - done && test -z "$$fail" -tags-recursive: - list='$(SUBDIRS)'; for subdir in $$list; do \ - test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ - done - -tags: TAGS - -ID: $(HEADERS) $(SOURCES) $(LISP) - list='$(SOURCES) $(HEADERS)'; \ - unique=`for i in $$list; do echo $$i; done | \ - awk ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ - here=`pwd` && cd $(srcdir) \ - && mkid -f$$here/ID $$unique $(LISP) - -TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) - tags=; \ - here=`pwd`; \ - list='$(SUBDIRS)'; for subdir in $$list; do \ - if test "$$subdir" = .; then :; else \ - test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ - fi; \ - done; \ - list='$(SOURCES) $(HEADERS)'; \ - unique=`for i in $$list; do echo $$i; done | \ - awk ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ - test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ - || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) - -mostlyclean-tags: - -clean-tags: - -distclean-tags: - -rm -f TAGS ID - -maintainer-clean-tags: - -distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) - -subdir = lib/expat - -distdir: $(DISTFILES) - @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 - for subdir in $(SUBDIRS); do \ - if test "$$subdir" = .; then :; else \ - test -d $(distdir)/$$subdir \ - || mkdir $(distdir)/$$subdir \ - || exit 1; \ - chmod 777 $(distdir)/$$subdir; \ - (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir=../$(top_distdir) distdir=../$(distdir)/$$subdir distdir) \ - || exit 1; \ - fi; \ - done -info-am: -info: info-recursive -dvi-am: -dvi: dvi-recursive -check-am: all-am -check: check-recursive -installcheck-am: -installcheck: installcheck-recursive -install-exec-am: -install-exec: install-exec-recursive - -install-data-am: -install-data: install-data-recursive - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am -install: install-recursive -uninstall-am: -uninstall: uninstall-recursive -all-am: Makefile -all-redirect: all-recursive -install-strip: - $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install -installdirs: installdirs-recursive -installdirs-am: - - -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -rm -f Makefile $(CONFIG_CLEAN_FILES) - -rm -f config.cache config.log stamp-h stamp-h[0-9]* - -maintainer-clean-generic: -mostlyclean-am: mostlyclean-tags mostlyclean-generic - -mostlyclean: mostlyclean-recursive - -clean-am: clean-tags clean-generic mostlyclean-am - -clean: clean-recursive - -distclean-am: distclean-tags distclean-generic clean-am - -rm -f libtool - -distclean: distclean-recursive - -maintainer-clean-am: maintainer-clean-tags maintainer-clean-generic \ - distclean-am - @echo "This command is intended for maintainers to use;" - @echo "it deletes files that may require special tools to rebuild." - -maintainer-clean: maintainer-clean-recursive - -.PHONY: install-data-recursive uninstall-data-recursive \ -install-exec-recursive uninstall-exec-recursive installdirs-recursive \ -uninstalldirs-recursive all-recursive check-recursive \ -installcheck-recursive info-recursive dvi-recursive \ -mostlyclean-recursive distclean-recursive clean-recursive \ -maintainer-clean-recursive tags tags-recursive mostlyclean-tags \ -distclean-tags clean-tags maintainer-clean-tags distdir info-am info \ -dvi-am dvi check check-am installcheck-am installcheck install-exec-am \ -install-exec install-data-am install-data install-am install \ -uninstall-am uninstall all-redirect all-am all installdirs-am \ -installdirs mostlyclean-generic distclean-generic clean-generic \ -maintainer-clean-generic clean mostlyclean distclean maintainer-clean - - -# 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: - -dep: diff --git a/libs/xmlrpc-c/lib/expat/expat.dsw b/libs/xmlrpc-c/lib/expat/expat.dsw deleted file mode 100644 index efc3322..0000000 --- a/libs/xmlrpc-c/lib/expat/expat.dsw +++ /dev/null @@ -1,74 +0,0 @@ -Microsoft Developer Studio Workspace File, Format Version 6.00 -# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! - -############################################################################### - -Project: "gennmtab"=.\gennmtab\gennmtab.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Project: "xmlparse"=.\xmlparse\xmlparse.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ - Begin Project Dependency - Project_Dep_Name xmltok - End Project Dependency -}}} - -############################################################################### - -Project: "xmltok"=.\xmltok\xmltok.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ - Begin Project Dependency - Project_Dep_Name gennmtab - End Project Dependency -}}} - -############################################################################### - -Project: "xmlwf"=.\xmlwf\xmlwf.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ - Begin Project Dependency - Project_Dep_Name xmlparse - End Project Dependency -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### - diff --git a/libs/xmlrpc-c/lib/expat/gennmtab/.cvsignore b/libs/xmlrpc-c/lib/expat/gennmtab/.cvsignore deleted file mode 100644 index b1f2027..0000000 --- a/libs/xmlrpc-c/lib/expat/gennmtab/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -gennmtab diff --git a/libs/xmlrpc-c/lib/expat/gennmtab/Makefile b/libs/xmlrpc-c/lib/expat/gennmtab/Makefile index 32e76b7..ebb100f 100644 --- a/libs/xmlrpc-c/lib/expat/gennmtab/Makefile +++ b/libs/xmlrpc-c/lib/expat/gennmtab/Makefile @@ -9,11 +9,9 @@ SUBDIR := lib/expat/gennmtab include $(BLDDIR)/config.mk -CFLAGS = $(CFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD) - LDFLAGS = $(LADD) -INCLUDES = -I$(BLDDIR) -I$(SRCDIR)/lib/util/include +INCLUDES = -I$(BLDDIR) -Isrcdir/lib/util/include default: all @@ -42,9 +40,9 @@ install: dep: dep-common gennmtab.o:%.o:%.c - $(BUILDTOOL_CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) + $(BUILDTOOL_CC) -c $< -o $@ $(CFLAGS_ALL) $(INCLUDES) gennmtab:%:%.o $(BUILDTOOL_CCLD) -o $@ $(LDFLAGS) $^ -include Makefile.depend +include depend.mk diff --git a/libs/xmlrpc-c/lib/expat/gennmtab/Makefile.depend b/libs/xmlrpc-c/lib/expat/gennmtab/Makefile.depend deleted file mode 100644 index e69de29..0000000 diff --git a/libs/xmlrpc-c/lib/expat/gennmtab/gennmtab.dsp b/libs/xmlrpc-c/lib/expat/gennmtab/gennmtab.dsp deleted file mode 100644 index 917dc44..0000000 --- a/libs/xmlrpc-c/lib/expat/gennmtab/gennmtab.dsp +++ /dev/null @@ -1,110 +0,0 @@ -# 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 -# PROP Scc_ProjName "gennmtab" -# PROP Scc_LocalPath "." -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 /MD /W3 /GX /O2 /I "..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /FD /c -# 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_Cmds=..\..\..\Bin\gennmtab.exe >..\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 /MDd /W3 /Gm /GX /ZI /Od /I "..\..\.." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /FD /c -# 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_Cmds=..\..\..\Bin\gennmtabD.exe >..\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=.\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 diff --git a/libs/xmlrpc-c/lib/expat/sample/.cvsignore b/libs/xmlrpc-c/lib/expat/sample/.cvsignore deleted file mode 100644 index f3c7a7c..0000000 --- a/libs/xmlrpc-c/lib/expat/sample/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -Makefile diff --git a/libs/xmlrpc-c/lib/expat/sample/Makefile.in b/libs/xmlrpc-c/lib/expat/sample/Makefile.in deleted file mode 100644 index b6e338d..0000000 --- a/libs/xmlrpc-c/lib/expat/sample/Makefile.in +++ /dev/null @@ -1,208 +0,0 @@ -# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - - -SHELL = @SHELL@ - -srcdir = @srcdir@ -top_srcdir = @top_srcdir@ -VPATH = @srcdir@ -prefix = @prefix@ -exec_prefix = @exec_prefix@ - -bindir = @bindir@ -sbindir = @sbindir@ -libexecdir = @libexecdir@ -datadir = @datadir@ -sysconfdir = @sysconfdir@ -sharedstatedir = @sharedstatedir@ -localstatedir = @localstatedir@ -libdir = @libdir@ -infodir = @infodir@ -mandir = @mandir@ -includedir = @includedir@ -oldincludedir = /usr/include - -DESTDIR = - -pkgdatadir = $(datadir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ - -top_builddir = ../../.. - -ACLOCAL = @ACLOCAL@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ - -INSTALL = @INSTALL@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -transform = @program_transform_name@ - -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -host_alias = @host_alias@ -host_triplet = @host@ -ABYSS_SUBDIR = @ABYSS_SUBDIR@ -AS = @AS@ -ASYNCH_CLIENT = @ASYNCH_CLIENT@ -AUTH_CLIENT = @AUTH_CLIENT@ -AVAILABLE_MODULES = @AVAILABLE_MODULES@ -CC = @CC@ -CC_WARN_FLAGS = @CC_WARN_FLAGS@ -CLIENTTEST = @CLIENTTEST@ -CONFIGURE_DATE = @CONFIGURE_DATE@ -CPPTEST = @CPPTEST@ -CPP_WARN_FLAGS = @CPP_WARN_FLAGS@ -CXX = @CXX@ -DLLTOOL = @DLLTOOL@ -EFRPCTEST = @EFRPCTEST@ -EFRPCTEST_WRAPPER = @EFRPCTEST_WRAPPER@ -INTEROP_CGI = @INTEROP_CGI@ -INTEROP_CLIENT_SUBDIR = @INTEROP_CLIENT_SUBDIR@ -LIBTOOL = @LIBTOOL@ -LIBWWW_CFLAGS = @LIBWWW_CFLAGS@ -LIBWWW_CONFIG = @LIBWWW_CONFIG@ -LIBWWW_LDADD = @LIBWWW_LDADD@ -LIBWWW_LIBDIR = @LIBWWW_LIBDIR@ -LIBWWW_RPATH = @LIBWWW_RPATH@ -LIBWWW_WL_RPATH = @LIBWWW_WL_RPATH@ -LIBXMLRPC_ABYSS_SERVER_LA = @LIBXMLRPC_ABYSS_SERVER_LA@ -LIBXMLRPC_CGI_LA = @LIBXMLRPC_CGI_LA@ -LIBXMLRPC_CLIENT_LA = @LIBXMLRPC_CLIENT_LA@ -LIBXMLRPC_CPP_A = @LIBXMLRPC_CPP_A@ -LN_S = @LN_S@ -MAKEINFO = @MAKEINFO@ -MEERKAT_APP_LIST = @MEERKAT_APP_LIST@ -OBJDUMP = @OBJDUMP@ -PACKAGE = @PACKAGE@ -QUERY_MEERKAT = @QUERY_MEERKAT@ -RANLIB = @RANLIB@ -SAMPLE_CGI_CGI = @SAMPLE_CGI_CGI@ -SERVER = @SERVER@ -SERVERTEST = @SERVERTEST@ -SYNCH_CLIENT = @SYNCH_CLIENT@ -VALIDATEE = @VALIDATEE@ -VERSION = @VERSION@ -VERSION_INFO = @VERSION_INFO@ -XMLRPCCPP_H = @XMLRPCCPP_H@ -XMLRPC_ABYSS_H = @XMLRPC_ABYSS_H@ -XMLRPC_CGI_H = @XMLRPC_CGI_H@ -XMLRPC_CLIENT_H = @XMLRPC_CLIENT_H@ -XML_RPC_API2CPP_SUBDIR = @XML_RPC_API2CPP_SUBDIR@ - -EXTRA_DIST = build.bat elements.c -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs -CONFIG_HEADER = ../../../xmlrpc_config.h -CONFIG_CLEAN_FILES = -DIST_COMMON = Makefile.in - - -DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) - -TAR = gtar -GZIP_ENV = --best -all: all-redirect -.SUFFIXES: - -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - cd $(top_builddir) \ - && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status - -tags: TAGS -TAGS: - - -distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) - -subdir = lib/expat/sample - -distdir: $(DISTFILES) - @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 -info-am: -info: info-am -dvi-am: -dvi: dvi-am -check-am: all-am -check: check-am -installcheck-am: -installcheck: installcheck-am -install-exec-am: -install-exec: install-exec-am - -install-data-am: -install-data: install-data-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am -install: install-am -uninstall-am: -uninstall: uninstall-am -all-am: Makefile -all-redirect: all-am -install-strip: - $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install -installdirs: - - -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -rm -f Makefile $(CONFIG_CLEAN_FILES) - -rm -f config.cache config.log stamp-h stamp-h[0-9]* - -maintainer-clean-generic: -mostlyclean-am: mostlyclean-generic - -mostlyclean: mostlyclean-am - -clean-am: clean-generic mostlyclean-am - -clean: clean-am - -distclean-am: distclean-generic clean-am - -rm -f libtool - -distclean: distclean-am - -maintainer-clean-am: maintainer-clean-generic distclean-am - @echo "This command is intended for maintainers to use;" - @echo "it deletes files that may require special tools to rebuild." - -maintainer-clean: maintainer-clean-am - -.PHONY: tags distdir info-am info dvi-am dvi check check-am \ -installcheck-am installcheck install-exec-am install-exec \ -install-data-am install-data install-am install uninstall-am uninstall \ -all-redirect all-am all installdirs mostlyclean-generic \ -distclean-generic clean-generic maintainer-clean-generic clean \ -mostlyclean distclean maintainer-clean - - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/libs/xmlrpc-c/lib/expat/sample/build.bat b/libs/xmlrpc-c/lib/expat/sample/build.bat deleted file mode 100644 index 8cf3048..0000000 --- a/libs/xmlrpc-c/lib/expat/sample/build.bat +++ /dev/null @@ -1,4 +0,0 @@ -@echo off -set LIB=..\xmlparse\Release;..\lib;%LIB% -cl /nologo /DXMLTOKAPI=__declspec(dllimport) /DXMLPARSEAPI=__declspec(dllimport) /I..\xmlparse /Fe..\bin\elements elements.c xmlparse.lib -@echo Run it using: ..\bin\elements ^<..\expat.html diff --git a/libs/xmlrpc-c/lib/expat/sample/elements.c b/libs/xmlrpc-c/lib/expat/sample/elements.c deleted file mode 100644 index 42745c4..0000000 --- a/libs/xmlrpc-c/lib/expat/sample/elements.c +++ /dev/null @@ -1,46 +0,0 @@ -/* This is simple demonstration of how to use expat. This program -reads an XML document from standard input and writes a line with the -name of each element to standard output indenting child elements by -one tab stop more than their parent element. */ - -#include -#include "xmlparse.h" - -void startElement(void *userData, const char *name, const char **atts) -{ - int i; - int *depthPtr = userData; - for (i = 0; i < *depthPtr; i++) - putchar('\t'); - puts(name); - *depthPtr += 1; -} - -void endElement(void *userData, const char *name) -{ - int *depthPtr = userData; - *depthPtr -= 1; -} - -int main() -{ - char buf[BUFSIZ]; - XML_Parser parser = XML_ParserCreate(NULL); - int done; - int depth = 0; - XML_SetUserData(parser, &depth); - XML_SetElementHandler(parser, startElement, endElement); - do { - size_t len = fread(buf, 1, sizeof(buf), stdin); - done = len < sizeof(buf); - if (!XML_Parse(parser, buf, len, done)) { - fprintf(stderr, - "%s at line %d\n", - XML_ErrorString(XML_GetErrorCode(parser)), - XML_GetCurrentLineNumber(parser)); - return 1; - } - } while (!done); - XML_ParserFree(parser); - return 0; -} diff --git a/libs/xmlrpc-c/lib/expat/xmlparse/.cvsignore b/libs/xmlrpc-c/lib/expat/xmlparse/.cvsignore deleted file mode 100644 index f3c7a7c..0000000 --- a/libs/xmlrpc-c/lib/expat/xmlparse/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -Makefile diff --git a/libs/xmlrpc-c/lib/expat/xmlparse/Makefile b/libs/xmlrpc-c/lib/expat/xmlparse/Makefile new file mode 100644 index 0000000..71a17c0 --- /dev/null +++ b/libs/xmlrpc-c/lib/expat/xmlparse/Makefile @@ -0,0 +1,93 @@ +############################################################################### +# This directory builds libxmlrpc_xmlparse, an XML 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/xmlparse + +XMLTOKDIR = srcdir/lib/expat/xmltok +UTILDIR = srcdir/lib/util + +default: all + +include $(BLDDIR)/config.mk + +TARGET_LIBRARY_NAMES := libxmlrpc_xmlparse + +STATIC_LIBRARIES_TO_INSTALL = libxmlrpc_xmlparse.a + +SHARED_LIBS_TO_BUILD := libxmlrpc_xmlparse +SHARED_LIBS_TO_INSTALL := libxmlrpc_xmlparse + +TARGET_MODS = xmlparse + +OMIT_XMLPARSE_LIB_RULE=Y +MAJ=3 + # Major number of shared libraries in this directory + +include $(SRCDIR)/common.mk + +INCLUDES = \ + -I$(BLDDIR) \ + -I$(XMLTOKDIR) \ + -I$(UTILDIR)/include \ + -Isrcdir/include \ + +# LIBDEP is the shared libraries on which libxmlrpc_abyss depends. +# The runtime loader should load these libraries when it loads libxmlrpc_abyss. + +LIBDEP = $(LIBXMLRPC_XMLTOK) $(LIBXMLRPC_UTIL) + +XMLPARSE_SHLIB = $(call shlibfn,libxmlrpc_xmlparse) +#XMLPARSE_SHLIB is e.g. libxmlrpc_xmlparse.so.3.1 +XMLPARSE_SHLIBLE = $(call shliblefn,libxmlrpc_xmlparse) +#XMLPARSE_SHLIBLE is e.g. libxmlrpc_xmlparse.so + +.PHONY: all +all: libxmlrpc_xmlparse.a $(TARGET_SHARED_LIBRARIES) $(TARGET_SHARED_LE_LIBS) + +# Rule for this is in common.mk, courtesy of TARGET_LIBRARY_NAMES: +$(XMLPARSE_SHLIB): $(TARGET_MODS:%=%.osh) $(LIBDEP) +$(XMLPARSE_SHLIB): LIBOBJECTS = $(TARGET_MODS:%=%.osh) $(LIBDEP) + +# Rule for this is in common.mk, courtesy of TARGET_STATIC_LIBRARIES: + +libxmlrpc_xmlparse.a: $(TARGET_MODS:%=%.o) +libxmlrpc_xmlparse.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 + +# This 'common.mk' dependency makes sure the symlinks get built before +# this make file is used for anything. + +$(SRCDIR)/common.mk: srcdir + +include depend.mk diff --git a/libs/xmlrpc-c/lib/expat/xmlparse/Makefile.in b/libs/xmlrpc-c/lib/expat/xmlparse/Makefile.in deleted file mode 100644 index 3e715af..0000000 --- a/libs/xmlrpc-c/lib/expat/xmlparse/Makefile.in +++ /dev/null @@ -1,344 +0,0 @@ -# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - - -SHELL = @SHELL@ - -srcdir = @srcdir@ -top_srcdir = @top_srcdir@ -VPATH = @srcdir@ -prefix = @prefix@ -exec_prefix = @exec_prefix@ - -bindir = @bindir@ -sbindir = @sbindir@ -libexecdir = @libexecdir@ -datadir = @datadir@ -sysconfdir = @sysconfdir@ -sharedstatedir = @sharedstatedir@ -localstatedir = @localstatedir@ -libdir = @libdir@ -infodir = @infodir@ -mandir = @mandir@ -includedir = @includedir@ -oldincludedir = /usr/include - -DESTDIR = - -pkgdatadir = $(datadir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ - -top_builddir = ../../.. - -ACLOCAL = @ACLOCAL@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ - -INSTALL = @INSTALL@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -transform = @program_transform_name@ - -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -host_alias = @host_alias@ -host_triplet = @host@ -ABYSS_SUBDIR = @ABYSS_SUBDIR@ -AS = @AS@ -ASYNCH_CLIENT = @ASYNCH_CLIENT@ -AUTH_CLIENT = @AUTH_CLIENT@ -AVAILABLE_MODULES = @AVAILABLE_MODULES@ -CC = @CC@ -CC_WARN_FLAGS = @CC_WARN_FLAGS@ -CLIENTTEST = @CLIENTTEST@ -CONFIGURE_DATE = @CONFIGURE_DATE@ -CPPTEST = @CPPTEST@ -CPP_WARN_FLAGS = @CPP_WARN_FLAGS@ -CXX = @CXX@ -DLLTOOL = @DLLTOOL@ -EFRPCTEST = @EFRPCTEST@ -EFRPCTEST_WRAPPER = @EFRPCTEST_WRAPPER@ -INTEROP_CGI = @INTEROP_CGI@ -INTEROP_CLIENT_SUBDIR = @INTEROP_CLIENT_SUBDIR@ -LIBTOOL = @LIBTOOL@ -LIBWWW_CFLAGS = @LIBWWW_CFLAGS@ -LIBWWW_CONFIG = @LIBWWW_CONFIG@ -LIBWWW_LDADD = @LIBWWW_LDADD@ -LIBWWW_LIBDIR = @LIBWWW_LIBDIR@ -LIBWWW_RPATH = @LIBWWW_RPATH@ -LIBWWW_WL_RPATH = @LIBWWW_WL_RPATH@ -LIBXMLRPC_ABYSS_SERVER_LA = @LIBXMLRPC_ABYSS_SERVER_LA@ -LIBXMLRPC_CGI_LA = @LIBXMLRPC_CGI_LA@ -LIBXMLRPC_CLIENT_LA = @LIBXMLRPC_CLIENT_LA@ -LIBXMLRPC_CPP_A = @LIBXMLRPC_CPP_A@ -LN_S = @LN_S@ -MAKEINFO = @MAKEINFO@ -MEERKAT_APP_LIST = @MEERKAT_APP_LIST@ -OBJDUMP = @OBJDUMP@ -PACKAGE = @PACKAGE@ -QUERY_MEERKAT = @QUERY_MEERKAT@ -RANLIB = @RANLIB@ -SAMPLE_CGI_CGI = @SAMPLE_CGI_CGI@ -SERVER = @SERVER@ -SERVERTEST = @SERVERTEST@ -SYNCH_CLIENT = @SYNCH_CLIENT@ -VALIDATEE = @VALIDATEE@ -VERSION = @VERSION@ -VERSION_INFO = @VERSION_INFO@ -XMLRPCCPP_H = @XMLRPCCPP_H@ -XMLRPC_ABYSS_H = @XMLRPC_ABYSS_H@ -XMLRPC_CGI_H = @XMLRPC_CGI_H@ -XMLRPC_CLIENT_H = @XMLRPC_CLIENT_H@ -XML_RPC_API2CPP_SUBDIR = @XML_RPC_API2CPP_SUBDIR@ - -INCLUDES = -I$(srcdir)/../xmltok - -lib_LTLIBRARIES = libxmlrpc_xmlparse.la - -libxmlrpc_xmlparse_la_SOURCES = xmlparse.c xmlparse.h -libxmlrpc_xmlparse_la_LDFLAGS = @VERSION_INFO@ - -EXTRA_DIST = xmlparse.dsp -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs -CONFIG_HEADER = ../../../xmlrpc_config.h -CONFIG_CLEAN_FILES = -LTLIBRARIES = $(lib_LTLIBRARIES) - - -DEFS = @DEFS@ -I. -I$(srcdir) -I../../.. -CPPFLAGS = @CPPFLAGS@ -LDFLAGS = @LDFLAGS@ -LIBS = @LIBS@ -libxmlrpc_xmlparse_la_LIBADD = -libxmlrpc_xmlparse_la_OBJECTS = xmlparse.lo -COMPILER_CFLAGS = @COMPILER_CFLAGS@ -CFLAGS = @CFLAGS@ $(COMPILER_CFLAGS) -COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -CCLD = $(CC) -LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ -DIST_COMMON = Makefile.in - - -DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) - -TAR = gtar -GZIP_ENV = --best -SOURCES = $(libxmlrpc_xmlparse_la_SOURCES) -OBJECTS = $(libxmlrpc_xmlparse_la_OBJECTS) - -all: all-redirect -.SUFFIXES: -.SUFFIXES: .S .c .lo .o .s - -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - cd $(top_builddir) \ - && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status - - -mostlyclean-libLTLIBRARIES: - -clean-libLTLIBRARIES: - -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) - -distclean-libLTLIBRARIES: - -maintainer-clean-libLTLIBRARIES: - -install-libLTLIBRARIES: $(lib_LTLIBRARIES) - @$(NORMAL_INSTALL) - $(mkinstalldirs) $(DESTDIR)$(libdir) - @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ - if test -f $$p; then \ - echo "$(LIBTOOL) --mode=install $(INSTALL) $$p $(DESTDIR)$(libdir)/$$p"; \ - $(LIBTOOL) --mode=install $(INSTALL) $$p $(DESTDIR)$(libdir)/$$p; \ - else :; fi; \ - done - -uninstall-libLTLIBRARIES: - @$(NORMAL_UNINSTALL) - list='$(lib_LTLIBRARIES)'; for p in $$list; do \ - $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/$$p; \ - done - -.c.o: - $(COMPILE) -c $< - -.s.o: - $(COMPILE) -c $< - -.S.o: - $(COMPILE) -c $< - -mostlyclean-compile: - -rm -f *.o core *.core - -clean-compile: - -distclean-compile: - -rm -f *.tab.c - -maintainer-clean-compile: - -.c.lo: - $(LIBTOOL) --mode=compile $(COMPILE) -c $< - -.s.lo: - $(LIBTOOL) --mode=compile $(COMPILE) -c $< - -.S.lo: - $(LIBTOOL) --mode=compile $(COMPILE) -c $< - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs - -distclean-libtool: - -maintainer-clean-libtool: - -libxmlrpc_xmlparse.la: $(libxmlrpc_xmlparse_la_OBJECTS) $(libxmlrpc_xmlparse_la_DEPENDENCIES) - $(LINK) -rpath $(libdir) $(libxmlrpc_xmlparse_la_LDFLAGS) $(libxmlrpc_xmlparse_la_OBJECTS) $(libxmlrpc_xmlparse_la_LIBADD) $(LIBS) - -tags: TAGS - -ID: $(HEADERS) $(SOURCES) $(LISP) - list='$(SOURCES) $(HEADERS)'; \ - unique=`for i in $$list; do echo $$i; done | \ - awk ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ - here=`pwd` && cd $(srcdir) \ - && mkid -f$$here/ID $$unique $(LISP) - -TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) - tags=; \ - here=`pwd`; \ - list='$(SOURCES) $(HEADERS)'; \ - unique=`for i in $$list; do echo $$i; done | \ - awk ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ - test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ - || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) - -mostlyclean-tags: - -clean-tags: - -distclean-tags: - -rm -f TAGS ID - -maintainer-clean-tags: - -distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) - -subdir = lib/expat/xmlparse - -distdir: $(DISTFILES) - @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 -xmlparse.lo xmlparse.o : xmlparse.c ../xmltok/xmldef.h xmlparse.h \ - ../xmltok/xmltok.h ../xmltok/xmlrole.h - -info-am: -info: info-am -dvi-am: -dvi: dvi-am -check-am: all-am -check: check-am -installcheck-am: -installcheck: installcheck-am -install-exec-am: install-libLTLIBRARIES -install-exec: install-exec-am - -install-data-am: -install-data: install-data-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am -install: install-am -uninstall-am: uninstall-libLTLIBRARIES -uninstall: uninstall-am -all-am: Makefile $(LTLIBRARIES) -all-redirect: all-am -install-strip: - $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install -installdirs: - $(mkinstalldirs) $(DESTDIR)$(libdir) - - -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -rm -f Makefile $(CONFIG_CLEAN_FILES) - -rm -f config.cache config.log stamp-h stamp-h[0-9]* - -maintainer-clean-generic: -mostlyclean-am: mostlyclean-libLTLIBRARIES mostlyclean-compile \ - mostlyclean-libtool mostlyclean-tags \ - mostlyclean-generic - -mostlyclean: mostlyclean-am - -clean-am: clean-libLTLIBRARIES clean-compile clean-libtool clean-tags \ - clean-generic mostlyclean-am - -clean: clean-am - -distclean-am: distclean-libLTLIBRARIES distclean-compile \ - distclean-libtool distclean-tags distclean-generic \ - clean-am - -rm -f libtool - -distclean: distclean-am - -maintainer-clean-am: maintainer-clean-libLTLIBRARIES \ - maintainer-clean-compile maintainer-clean-libtool \ - maintainer-clean-tags maintainer-clean-generic \ - distclean-am - @echo "This command is intended for maintainers to use;" - @echo "it deletes files that may require special tools to rebuild." - -maintainer-clean: maintainer-clean-am - -.PHONY: mostlyclean-libLTLIBRARIES distclean-libLTLIBRARIES \ -clean-libLTLIBRARIES maintainer-clean-libLTLIBRARIES \ -uninstall-libLTLIBRARIES install-libLTLIBRARIES mostlyclean-compile \ -distclean-compile clean-compile maintainer-clean-compile \ -mostlyclean-libtool distclean-libtool clean-libtool \ -maintainer-clean-libtool tags mostlyclean-tags distclean-tags \ -clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \ -check-am installcheck-am installcheck install-exec-am install-exec \ -install-data-am install-data install-am install uninstall-am uninstall \ -all-redirect all-am all installdirs mostlyclean-generic \ -distclean-generic clean-generic maintainer-clean-generic clean \ -mostlyclean distclean maintainer-clean - - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/libs/xmlrpc-c/lib/expat/xmlparse/xmlparse.c b/libs/xmlrpc-c/lib/expat/xmlparse/xmlparse.c index fc1c9f3..5b647f1 100644 --- a/libs/xmlrpc-c/lib/expat/xmlparse/xmlparse.c +++ b/libs/xmlrpc-c/lib/expat/xmlparse/xmlparse.c @@ -139,7 +139,7 @@ typedef struct tag { typedef struct { const XML_Char *name; const XML_Char *textPtr; - int textLen; + size_t textLen; const XML_Char *systemId; const XML_Char *base; const XML_Char *publicId; @@ -473,7 +473,7 @@ int poolGrow(STRING_POOL *pool) } } if (pool->blocks && pool->start == pool->blocks->s) { - int blockSize = (pool->end - pool->start)*2; + size_t const blockSize = (pool->end - pool->start)*2; pool->blocks = realloc(pool->blocks, offsetof(BLOCK, s) + blockSize * sizeof(XML_Char)); if (!pool->blocks) @@ -484,12 +484,11 @@ int poolGrow(STRING_POOL *pool) pool->end = pool->start + blockSize; } else { + size_t const poolLen = pool->end - pool->start; + size_t const blockSize = + poolLen < INIT_BLOCK_SIZE ? INIT_BLOCK_SIZE : poolLen * 2; 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; @@ -1123,16 +1122,14 @@ normalizeLines(XML_Char *s) static void reportDefault(XML_Parser const xmlParserP, const ENCODING * const enc, - const char * const startArg, + const char * const start, const char * const end) { Parser * const parser = (Parser *)xmlParserP; - const char * s; - - s = startArg; + if (MUST_CONVERT(enc, start)) { + const char * s; - if (MUST_CONVERT(enc, s)) { const char **eventPP; const char **eventEndPP; @@ -1144,16 +1141,23 @@ reportDefault(XML_Parser const xmlParserP, eventPP = &(openInternalEntities->internalEventPtr); eventEndPP = &(openInternalEntities->internalEventEndPtr); } + s = start; do { ICHAR *dataPtr = (ICHAR *)dataBuf; XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd); *eventEndPP = s; - defaultHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf); + { + size_t const len = dataPtr - (ICHAR *)dataBuf; + assert((size_t)(int)len == len); /* parser requirement */ + defaultHandler(handlerArg, dataBuf, (int)len); + } *eventPP = s; } while (s != end); - } else - defaultHandler(handlerArg, (XML_Char *)s, - (XML_Char *)end - (XML_Char *)s); + } else { + size_t const len = (XML_Char *)end - (XML_Char *)start; + assert((size_t)(int)len == len); /* parser requirement */ + defaultHandler(handlerArg, (XML_Char *)start, len); + } } @@ -2151,16 +2155,21 @@ doCdataSection(XML_Parser const xmlParserP, ICHAR *dataPtr = (ICHAR *)dataBuf; XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd); *eventEndPP = next; - characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf); + { + size_t const len = dataPtr - (ICHAR *)dataBuf; + assert((size_t)(int)len == len); /* parser requirement */ + characterDataHandler(handlerArg, dataBuf, (int)len); + } if (s == next) break; *eventPP = s; } } - else - characterDataHandler(handlerArg, - (XML_Char *)s, - (XML_Char *)next - (XML_Char *)s); + else { + size_t const len = (XML_Char *)next - (XML_Char *)s; + assert((size_t)(int)len == len); /* parser requirement */ + characterDataHandler(handlerArg, (XML_Char *)s, (int)len); + } } else if (defaultHandler) reportDefault(xmlParserP, enc, s, next); @@ -2459,7 +2468,7 @@ doStartTagNoAtts(XML_Parser const xmlParserP, if (fromPtr == rawNameEnd) break; else { - int const bufSize = (tag->bufEnd - tag->buf) << 1; + size_t const bufSize = (tag->bufEnd - tag->buf) << 1; tag->buf = realloc(tag->buf, bufSize); if (!tag->buf) { *errorCodeP = XML_ERROR_NO_MEMORY; @@ -2777,12 +2786,16 @@ processContentToken(XML_Parser const xmlParserP, 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); + { + size_t const len = dataPtr - (ICHAR *)dataBuf; + assert((size_t)(int)len == len); /* parser reqt */ + characterDataHandler(handlerArg, dataBuf, (int)len); + } + } else { + size_t const len = (XML_Char *)end - (XML_Char *)s; + assert((size_t)(int)len == len); /* parser reqt */ + characterDataHandler(handlerArg, (XML_Char *)s, (int)len); + } } else if (defaultHandler) reportDefault(xmlParserP, enc, s, end); @@ -2807,16 +2820,20 @@ processContentToken(XML_Parser const xmlParserP, XmlConvert(enc, &from, *nextP, &dataPtr, (ICHAR *)dataBufEnd); *eventEndPP = from; - characterDataHandler(handlerArg, dataBuf, - dataPtr - (ICHAR *)dataBuf); + { + size_t const len = dataPtr - (ICHAR *)dataBuf; + assert((size_t)(int)len == len); /* parser reqt */ + characterDataHandler(handlerArg, dataBuf, (int)len); + } if (from == *nextP) break; *eventPP = from; } - } else - characterDataHandler(handlerArg, - (XML_Char *)s, - (XML_Char *)*nextP - (XML_Char *)s); + } else { + size_t const len = (XML_Char *)*nextP - (XML_Char *)s; + assert((size_t)(int)len == len); /* parser reqt */ + characterDataHandler(handlerArg, (XML_Char *)s, len); + } } else if (defaultHandler) reportDefault(xmlParserP, enc, s, *nextP); break; @@ -4369,7 +4386,7 @@ parseFinalLen0(Parser * const parser, static void parseNoBuffer(Parser * const parser, const char * const s, - int const len, + size_t const len, bool const isFinal, int * const succeededP) { @@ -4377,8 +4394,8 @@ parseNoBuffer(Parser * const parser, positionPtr = s; if (isFinal) { - processor(parser, s, parseEndPtr = s + len, 0, - &errorCode, &errorString); + parseEndPtr = s + len; + processor(parser, s, parseEndPtr, 0, &errorCode, &errorString); if (errorCode == XML_ERROR_NONE) *succeededP = true; else { @@ -4427,7 +4444,7 @@ parseNoBuffer(Parser * const parser, int xmlrpc_XML_Parse(XML_Parser const xmlParserP, const char * const s, - int const len, + size_t const len, int const isFinal) { Parser * const parser = (Parser *) xmlParserP; @@ -4487,40 +4504,49 @@ xmlrpc_XML_ParseBuffer(XML_Parser const xmlParserP, } } + + void * -xmlrpc_XML_GetBuffer(XML_Parser parser, int len) -{ - if (len > bufferLim - bufferEnd) { - /* FIXME avoid integer overflow */ - int neededSize = len + (bufferEnd - bufferPtr); - if (neededSize <= bufferLim - buffer) { - memmove(buffer, bufferPtr, bufferEnd - bufferPtr); - bufferEnd = buffer + (bufferEnd - bufferPtr); - bufferPtr = buffer; - } - else { - char *newBuf; - int bufferSize = bufferLim - bufferPtr; - if (bufferSize == 0) - bufferSize = INIT_BUFFER_SIZE; - do { - bufferSize *= 2; - } while (bufferSize < neededSize); - newBuf = malloc(bufferSize); - if (newBuf == 0) { - errorCode = XML_ERROR_NO_MEMORY; - return 0; - } - bufferLim = newBuf + bufferSize; - if (bufferPtr) { - memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr); - free(buffer); - } - bufferEnd = newBuf + (bufferEnd - bufferPtr); - bufferPtr = buffer = newBuf; +xmlrpc_XML_GetBuffer(XML_Parser const xmlParserP, + size_t const len) { + + Parser * const parser = (Parser *)xmlParserP; + + assert(bufferLim >= bufferEnd); + + if (len > (size_t)(bufferLim - bufferEnd)) { + /* FIXME avoid integer overflow */ + size_t neededSize = len + (bufferEnd - bufferPtr); + assert(bufferLim >= buffer); + if (neededSize <= (size_t)(bufferLim - buffer)) { + memmove(buffer, bufferPtr, bufferEnd - bufferPtr); + bufferEnd = buffer + (bufferEnd - bufferPtr); + bufferPtr = buffer; + } else { + size_t bufferSize; + char * newBuf; + + bufferSize = bufferLim > bufferPtr ? + bufferLim - bufferPtr : INIT_BUFFER_SIZE; + + do { + bufferSize *= 2; + } while (bufferSize < neededSize); + newBuf = malloc(bufferSize); + if (newBuf == 0) { + errorCode = XML_ERROR_NO_MEMORY; + return 0; + } + bufferLim = newBuf + bufferSize; + if (bufferPtr) { + memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr); + free(buffer); + } + bufferEnd = newBuf + (bufferEnd - bufferPtr); + bufferPtr = buffer = newBuf; + } } - } - return bufferEnd; + return bufferEnd; } @@ -4547,19 +4573,40 @@ xmlrpc_XML_GetErrorString(XML_Parser const parser) { long -xmlrpc_XML_GetCurrentByteIndex(XML_Parser parser) -{ - if (eventPtr) - return parseEndByteIndex - (parseEndPtr - eventPtr); - return -1; +xmlrpc_XML_GetCurrentByteIndex(XML_Parser const parser) { + + long retval; + + if (eventPtr) { + size_t const bytesLeft = parseEndPtr - eventPtr; + + if ((size_t)(long)(bytesLeft) != bytesLeft) + retval = -1; + else + retval = parseEndByteIndex - (long)bytesLeft; + } else + retval = -1; + + return retval; } + + int -xmlrpc_XML_GetCurrentByteCount(XML_Parser parser) -{ - if (eventEndPtr && eventPtr) - return eventEndPtr - eventPtr; - return 0; +xmlrpc_XML_GetCurrentByteCount(XML_Parser const parser) { + + int retval; + + if (eventEndPtr && eventPtr) { + size_t const byteCount = eventEndPtr - eventPtr; + + assert((size_t)(int)byteCount == byteCount); + + retval = (int)byteCount; + } else + retval = 0; + + return retval; } diff --git a/libs/xmlrpc-c/lib/expat/xmlparse/xmlparse.dsp b/libs/xmlrpc-c/lib/expat/xmlparse/xmlparse.dsp deleted file mode 100644 index b95795a..0000000 --- a/libs/xmlrpc-c/lib/expat/xmlparse/xmlparse.dsp +++ /dev/null @@ -1,279 +0,0 @@ -# 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) Dynamic-Link Library" 0x0102 -# 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 "xmlparse - Win32 Release DLL" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE "xmlparse - Win32 Debug DLL" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE "xmlparse - Win32 MinSize DLL" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "xmlparse" -# PROP Scc_LocalPath ".." - -!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 -CPP=cl.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 "..\xmltok" /I "..\xmlwf" /I "..\..\.." /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "XML_DTD" /D "_MBCS" /D "_LIB" /YX /FD /c -RSC=rc.exe -# 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 - -!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 -CPP=cl.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 /MDd /W3 /Gm /GX /ZI /Od /I "..\xmltok" /I "..\xmlwf" /I "..\..\.." /D "WIN32" /D "_WINDOWS" /D "XML_DTD" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c -RSC=rc.exe -# 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 - -!ELSEIF "$(CFG)" == "xmlparse - Win32 Release DLL" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir ".\ReleaseDLL" -# PROP BASE Intermediate_Dir ".\ReleaseDLL" -# PROP BASE Target_Dir "." -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "ReleaseDLL\xmlparse" -# PROP Intermediate_Dir "ReleaseDLL\xmlparse" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "." -CPP=cl.exe -# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c -# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\xmltok" /I "..\xmlwf" /I "..\..\.." /D XMLTOKAPI=__declspec(dllimport) /D XMLPARSEAPI=__declspec(dllexport) /D "NDEBUG" /D "XML_NS" /D "WIN32" /D "_WINDOWS" /D "XML_DTD" /YX /FD /c -MTL=midl.exe -# ADD BASE MTL /nologo /D "NDEBUG" /win32 -# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -RSC=rc.exe -# 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:windows /dll /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 /base:"0x20000000" /subsystem:windows /dll /machine:I386 /link50compat -# SUBTRACT LINK32 /pdb:none - -!ELSEIF "$(CFG)" == "xmlparse - Win32 Debug DLL" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir ".\DebugDLL" -# PROP BASE Intermediate_Dir ".\DebugDLL" -# PROP BASE Target_Dir "." -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "DebugDLL\xmlparse" -# PROP Intermediate_Dir "DebugDLL\xmlparse" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "." -CPP=cl.exe -# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c -# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\xmltok" /I "..\xmlwf" /I "..\..\.." /D "_DEBUG" /D XMLTOKAPI=__declspec(dllimport) /D XMLPARSEAPI=__declspec(dllexport) /D "WIN32" /D "_WINDOWS" /D "XML_DTD" /YX /FD /c -MTL=midl.exe -# ADD BASE MTL /nologo /D "_DEBUG" /win32 -# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -RSC=rc.exe -# 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:windows /dll /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 /base:"0x20000000" /subsystem:windows /dll /debug /machine:I386 - -!ELSEIF "$(CFG)" == "xmlparse - Win32 MinSize DLL" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir ".\ReleaseMinSizeDLL" -# PROP BASE Intermediate_Dir ".\ReleaseMinSizeDLL" -# PROP BASE Ignore_Export_Lib 0 -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "ReleaseMinSizeDLL\xmlparse" -# PROP Intermediate_Dir "ReleaseMinSizeDLL\xmlparse" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -CPP=cl.exe -# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "..\xmltok" /I "..\xmlwf" /D XMLTOKAPI=__declspec(dllimport) /D XMLPARSEAPI=__declspec(dllexport) /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "XML_NS" /YX /FD /c -# ADD CPP /nologo /MD /W3 /GX /O1 /I "..\xmltok" /I "..\xmlwf" /I "..\..\.." /D "XML_MIN_SIZE" /D "XML_WINLIB" /D XMLPARSEAPI=__declspec(dllexport) /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /YX /FD /c -MTL=midl.exe -# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -RSC=rc.exe -# 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 /base:"0x20000000" /subsystem:windows /dll /machine:I386 -# SUBTRACT BASE LINK32 /profile -# 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 /base:"0x20000000" /entry:"DllMain" /subsystem:windows /dll /machine:I386 -# SUBTRACT LINK32 /profile /nodefaultlib - -!ENDIF - -# Begin Target - -# Name "xmlparse - Win32 Release" -# Name "xmlparse - Win32 Debug" -# Name "xmlparse - Win32 Release DLL" -# Name "xmlparse - Win32 Debug DLL" -# Name "xmlparse - Win32 MinSize DLL" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90" -# Begin Source File - -SOURCE=..\xmltok\dllmain.c - -!IF "$(CFG)" == "xmlparse - Win32 Release" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "xmlparse - Win32 Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "xmlparse - Win32 Release DLL" - -!ELSEIF "$(CFG)" == "xmlparse - Win32 Debug DLL" - -!ELSEIF "$(CFG)" == "xmlparse - Win32 MinSize DLL" - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\xmlparse.c -# End Source File -# Begin Source File - -SOURCE=..\xmltok\xmlrole.c - -!IF "$(CFG)" == "xmlparse - Win32 Release" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "xmlparse - Win32 Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "xmlparse - Win32 Release DLL" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "xmlparse - Win32 Debug DLL" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "xmlparse - Win32 MinSize DLL" - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=..\xmltok\xmltok.c - -!IF "$(CFG)" == "xmlparse - Win32 Release" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "xmlparse - Win32 Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "xmlparse - Win32 Release DLL" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "xmlparse - Win32 Debug DLL" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "xmlparse - Win32 MinSize DLL" - -!ENDIF - -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" -# Begin Source File - -SOURCE=.\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 diff --git a/libs/xmlrpc-c/lib/expat/xmlparse/xmlparse.h b/libs/xmlrpc-c/lib/expat/xmlparse/xmlparse.h index 2b8c701..7a65521 100644 --- a/libs/xmlrpc-c/lib/expat/xmlparse/xmlparse.h +++ b/libs/xmlrpc-c/lib/expat/xmlparse/xmlparse.h @@ -6,14 +6,12 @@ #ifndef XMLPARSE_H_INCLUDED #define XMLPARSE_H_INCLUDED +#include "xmlrpc-c/c_util.h" + #ifdef __cplusplus extern "C" { #endif -#ifndef XMLPARSEAPI -#define XMLPARSEAPI /* as nothing */ -#endif - typedef void *XML_Parser; #ifdef XML_UNICODE_WCHAR_T @@ -53,7 +51,7 @@ typedef char XML_LChar; /* Constructs a new parser; encoding is the encoding specified by the external protocol or null if there is none specified. */ -XML_Parser XMLPARSEAPI +XML_Parser XMLRPC_DLLEXPORT xmlrpc_XML_ParserCreate(const XML_Char * const encoding); /* Constructs a new parser and namespace processor. Element type names @@ -66,7 +64,7 @@ the namespace URI and the local part will be concatenated without any separator. When a namespace is not declared, the name and prefix will be passed through without expansion. */ -XML_Parser XMLPARSEAPI +XML_Parser XMLRPC_DLLEXPORT xmlrpc_XML_ParserCreateNS(const XML_Char * const encoding, XML_Char const namespaceSeparator); @@ -270,24 +268,24 @@ typedef int (*XML_UnknownEncodingHandler)(void *encodingHandlerData, const XML_Char *name, XML_Encoding *info); -void XMLPARSEAPI +void XMLRPC_DLLEXPORT xmlrpc_XML_SetElementHandler(XML_Parser parser, XML_StartElementHandler start, XML_EndElementHandler end); -void XMLPARSEAPI +void XMLRPC_DLLEXPORT xmlrpc_XML_SetCharacterDataHandler(XML_Parser parser, XML_CharacterDataHandler handler); -void XMLPARSEAPI +void XMLRPC_DLLEXPORT xmlrpc_XML_SetProcessingInstructionHandler( XML_Parser parser, XML_ProcessingInstructionHandler handler); -void XMLPARSEAPI +void XMLRPC_DLLEXPORT xmlrpc_XML_SetCommentHandler(XML_Parser parser, XML_CommentHandler handler); -void XMLPARSEAPI +void XMLRPC_DLLEXPORT xmlrpc_XML_SetCdataSectionHandler(XML_Parser parser, XML_StartCdataSectionHandler start, XML_EndCdataSectionHandler end); @@ -297,50 +295,50 @@ xmlrpc_XML_SetCdataSectionHandler(XML_Parser parser, handler. */ -void XMLPARSEAPI +void XMLRPC_DLLEXPORT 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 +void XMLRPC_DLLEXPORT xmlrpc_XML_SetDefaultHandlerExpand(XML_Parser parser, XML_DefaultHandler handler); -void XMLPARSEAPI +void XMLRPC_DLLEXPORT xmlrpc_XML_SetDoctypeDeclHandler(XML_Parser parser, XML_StartDoctypeDeclHandler start, XML_EndDoctypeDeclHandler end); -void XMLPARSEAPI +void XMLRPC_DLLEXPORT xmlrpc_XML_SetUnparsedEntityDeclHandler(XML_Parser parser, XML_UnparsedEntityDeclHandler handler); -void XMLPARSEAPI +void XMLRPC_DLLEXPORT xmlrpc_XML_SetNotationDeclHandler(XML_Parser parser, XML_NotationDeclHandler handler); -void XMLPARSEAPI +void XMLRPC_DLLEXPORT xmlrpc_XML_SetExternalParsedEntityDeclHandler( XML_Parser parser, XML_ExternalParsedEntityDeclHandler handler); -void XMLPARSEAPI +void XMLRPC_DLLEXPORT xmlrpc_XML_SetInternalParsedEntityDeclHandler( XML_Parser parser, XML_InternalParsedEntityDeclHandler handler); -void XMLPARSEAPI +void XMLRPC_DLLEXPORT xmlrpc_XML_SetNamespaceDeclHandler(XML_Parser parser, XML_StartNamespaceDeclHandler start, XML_EndNamespaceDeclHandler end); -void XMLPARSEAPI +void XMLRPC_DLLEXPORT xmlrpc_XML_SetNotStandaloneHandler(XML_Parser parser, XML_NotStandaloneHandler handler); -void XMLPARSEAPI +void XMLRPC_DLLEXPORT xmlrpc_XML_SetExternalEntityRefHandler(XML_Parser parser, XML_ExternalEntityRefHandler handler); @@ -348,10 +346,10 @@ xmlrpc_XML_SetExternalEntityRefHandler(XML_Parser parser, passed as the first argument to the external entity ref handler instead of the parser object. */ -void XMLPARSEAPI +void XMLRPC_DLLEXPORT xmlrpc_XML_SetExternalEntityRefHandlerArg(XML_Parser, void *arg); -void XMLPARSEAPI +void XMLRPC_DLLEXPORT xmlrpc_XML_SetUnknownEncodingHandler(XML_Parser parser, XML_UnknownEncodingHandler handler, void *encodingHandlerData); @@ -360,11 +358,11 @@ xmlrpc_XML_SetUnknownEncodingHandler(XML_Parser parser, processing instruction or character data. It causes the corresponding markup to be passed to the default handler. */ -void XMLPARSEAPI +void XMLRPC_DLLEXPORT xmlrpc_XML_DefaultCurrent(XML_Parser parser); /* This value is passed as the userData argument to callbacks. */ -void XMLPARSEAPI +void XMLRPC_DLLEXPORT xmlrpc_XML_SetUserData(XML_Parser parser, void *userData); /* Returns the last value set by XML_SetUserData or null. */ @@ -374,14 +372,14 @@ xmlrpc_XML_SetUserData(XML_Parser parser, void *userData); to XML_ParserCreate. It must not be called after XML_Parse or XML_ParseBuffer. */ -int XMLPARSEAPI +int XMLRPC_DLLEXPORT 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. */ -void XMLPARSEAPI +void XMLRPC_DLLEXPORT xmlrpc_XML_UseParserAsHandlerArg(XML_Parser parser); /* Sets the base to be used for resolving relative URIs in system @@ -391,10 +389,10 @@ xmlrpc_XML_UseParserAsHandlerArg(XML_Parser parser); and XML_UnparsedEntityDeclHandler. The base argument will be copied. Returns zero if out of memory, non-zero otherwise. */ -int XMLPARSEAPI +int XMLRPC_DLLEXPORT xmlrpc_XML_SetBase(XML_Parser parser, const XML_Char *base); -const XML_Char XMLPARSEAPI * +const XML_Char XMLRPC_DLLEXPORT * xmlrpc_XML_GetBase(XML_Parser parser); /* Returns the number of the attribute/value pairs passed in last call @@ -403,7 +401,7 @@ xmlrpc_XML_GetBase(XML_Parser parser); this correspondds to an index into the atts array passed to the XML_StartElementHandler. */ -int XMLPARSEAPI +int XMLRPC_DLLEXPORT xmlrpc_XML_GetSpecifiedAttributeCount(XML_Parser parser); /* Returns the index of the ID attribute passed in the last call to @@ -411,20 +409,24 @@ xmlrpc_XML_GetSpecifiedAttributeCount(XML_Parser parser); attribute/value pair counts as 2; thus this correspondds to an index into the atts array passed to the XML_StartElementHandler. */ -int XMLPARSEAPI +int XMLRPC_DLLEXPORT 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). */ -int XMLPARSEAPI -xmlrpc_XML_Parse(XML_Parser const parser, const char * const s, int const len, int const isFinal); +int XMLRPC_DLLEXPORT +xmlrpc_XML_Parse(XML_Parser const xmlParserP, + const char * const s, + size_t const len, + int const isFinal); -void XMLPARSEAPI * -xmlrpc_XML_GetBuffer(XML_Parser parser, int len); +void XMLRPC_DLLEXPORT * +xmlrpc_XML_GetBuffer(XML_Parser const xmlParserP, + size_t const len); -int XMLPARSEAPI +int XMLRPC_DLLEXPORT xmlrpc_XML_ParseBuffer(XML_Parser const parser, int const len, int const isFinal); /* Creates an XML_Parser object that can parse an external general @@ -443,7 +445,7 @@ xmlrpc_XML_ParseBuffer(XML_Parser const parser, int const len, int const isFinal from the parser argument. Returns 0 if out of memory. Otherwise returns a new XML_Parser object. */ -XML_Parser XMLPARSEAPI +XML_Parser XMLRPC_DLLEXPORT xmlrpc_XML_ExternalEntityParserCreate(XML_Parser parser, const XML_Char *context, const XML_Char *encoding); @@ -473,7 +475,7 @@ enum XML_ParamEntityParsing { XML_SetParamEntityParsing will return 0 if parsing of parameter entities is requested; otherwise it will return non-zero. */ -int XMLPARSEAPI +int XMLRPC_DLLEXPORT xmlrpc_XML_SetParamEntityParsing(XML_Parser parser, enum XML_ParamEntityParsing parsing); @@ -508,10 +510,10 @@ enum XML_Error { information about the error. */ -enum XML_Error XMLPARSEAPI +enum XML_Error XMLRPC_DLLEXPORT xmlrpc_XML_GetErrorCode(XML_Parser const parser); -const char * XMLPARSEAPI +XMLRPC_DLLEXPORT const char * xmlrpc_XML_GetErrorString(XML_Parser const parser); /* These functions return information about the current parse location. @@ -523,17 +525,17 @@ xmlrpc_XML_GetErrorString(XML_Parser const parser); of the sequence of characters that generated the event. */ -int XMLPARSEAPI +int XMLRPC_DLLEXPORT xmlrpc_XML_GetCurrentLineNumber(XML_Parser parser); -int XMLPARSEAPI +int XMLRPC_DLLEXPORT xmlrpc_XML_GetCurrentColumnNumber(XML_Parser parser); -long XMLPARSEAPI +long XMLRPC_DLLEXPORT 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 +int XMLRPC_DLLEXPORT xmlrpc_XML_GetCurrentByteCount(XML_Parser parser); /* For backwards compatibility with previous versions. */ @@ -542,11 +544,11 @@ xmlrpc_XML_GetCurrentByteCount(XML_Parser parser); #define XML_GetErrorByteIndex XML_GetCurrentByteIndex /* Frees memory used by the parser. */ -void XMLPARSEAPI +void XMLRPC_DLLEXPORT xmlrpc_XML_ParserFree(XML_Parser parser); /* Returns a string describing the error. */ -const XML_LChar XMLPARSEAPI * +const XML_LChar XMLRPC_DLLEXPORT * xmlrpc_XML_ErrorString(int const code); #ifdef __cplusplus diff --git a/libs/xmlrpc-c/lib/expat/xmltok/.cvsignore b/libs/xmlrpc-c/lib/expat/xmltok/.cvsignore deleted file mode 100644 index 38cd01c..0000000 --- a/libs/xmlrpc-c/lib/expat/xmltok/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -nametab.h diff --git a/libs/xmlrpc-c/lib/expat/xmltok/Makefile b/libs/xmlrpc-c/lib/expat/xmltok/Makefile index cfcb8dd..4cb9723 100644 --- a/libs/xmlrpc-c/lib/expat/xmltok/Makefile +++ b/libs/xmlrpc-c/lib/expat/xmltok/Makefile @@ -24,10 +24,10 @@ include $(BLDDIR)/config.mk # we started using the Gcc -Wundef option, that generates a warning, so # se set it explicitly to 0 here. -CFLAGS = $(CFLAGS_COMMON) -DXML_BYTE_ORDER=0 $(CFLAGS_PERSONAL) $(CADD) +CFLAGS_LOCAL = -DXML_BYTE_ORDER=0 # -I. is necessary when blddir != srcdir -INCLUDES = -I. -I$(BLDDIR) -I$(SRCDIR)/lib/util/include +INCLUDES = -I. -I$(BLDDIR) -Isrcdir/lib/util/include -Isrcdir/include default: all @@ -46,19 +46,20 @@ MAJ=3 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 + 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.a $(TARGET_SHARED_LIBS) $(TARGET_SHARED_LE_LIBS) +all: libxmlrpc_xmltok.a $(TARGET_SHARED_LIBRARIES) $(TARGET_SHARED_LE_LIBS) -# Rule for this is in common.mk, courtesy of TARGET_SHARED_LIBRARIES: +# Rule for this is in common.mk, courtesy of TARGET_LIBRARY_NAMES $(XMLTOK_SHLIB): $(TARGET_MODS:%=%.osh) $(XMLTOK_SHLIB): LIBOBJECTS = $(TARGET_MODS:%=%.osh) @@ -103,6 +104,6 @@ nametab.h: $(GENNMTAB) $(GENNMTAB): $(MAKE) -C $(dir $@) $(notdir $@) -xmltok.o xmltok.osh: nametab.h +xmltok.o xmltok.osh: nametab.h xmltok_impl.c -include Makefile.depend +include depend.mk diff --git a/libs/xmlrpc-c/lib/expat/xmltok/Makefile.depend b/libs/xmlrpc-c/lib/expat/xmltok/Makefile.depend deleted file mode 100644 index e69de29..0000000 diff --git a/libs/xmlrpc-c/lib/expat/xmltok/nametab.h b/libs/xmlrpc-c/lib/expat/xmltok/nametab.h deleted file mode 100644 index b05e62c..0000000 --- a/libs/xmlrpc-c/lib/expat/xmltok/nametab.h +++ /dev/null @@ -1,150 +0,0 @@ -static const unsigned namingBitmap[] = { -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, -0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, -0x00000000, 0x04000000, 0x87FFFFFE, 0x07FFFFFE, -0x00000000, 0x00000000, 0xFF7FFFFF, 0xFF7FFFFF, -0xFFFFFFFF, 0x7FF3FFFF, 0xFFFFFDFE, 0x7FFFFFFF, -0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE00F, 0xFC31FFFF, -0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF, -0xFFFFFFFF, 0xF80001FF, 0x00000003, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0xFFFFD740, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD, -0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF, -0xFFFF0003, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF, -0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE, -0x0000007F, 0x00000000, 0xFFFF0000, 0x000707FF, -0x00000000, 0x07FFFFFE, 0x000007FE, 0xFFFE0000, -0xFFFFFFFF, 0x7CFFFFFF, 0x002F7FFF, 0x00000060, -0xFFFFFFE0, 0x23FFFFFF, 0xFF000000, 0x00000003, -0xFFF99FE0, 0x03C5FDFF, 0xB0000000, 0x00030003, -0xFFF987E0, 0x036DFDFF, 0x5E000000, 0x001C0000, -0xFFFBAFE0, 0x23EDFDFF, 0x00000000, 0x00000001, -0xFFF99FE0, 0x23CDFDFF, 0xB0000000, 0x00000003, -0xD63DC7E0, 0x03BFC718, 0x00000000, 0x00000000, -0xFFFDDFE0, 0x03EFFDFF, 0x00000000, 0x00000003, -0xFFFDDFE0, 0x03EFFDFF, 0x40000000, 0x00000003, -0xFFFDDFE0, 0x03FFFDFF, 0x00000000, 0x00000003, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0xFFFFFFFE, 0x000D7FFF, 0x0000003F, 0x00000000, -0xFEF02596, 0x200D6CAE, 0x0000001F, 0x00000000, -0x00000000, 0x00000000, 0xFFFFFEFF, 0x000003FF, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0xFFFFFFFF, 0xFFFF003F, 0x007FFFFF, -0x0007DAED, 0x50000000, 0x82315001, 0x002C62AB, -0x40000000, 0xF580C900, 0x00000007, 0x02010800, -0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, -0x0FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x03FFFFFF, -0x3F3FFFFF, 0xFFFFFFFF, 0xAAFF3F3F, 0x3FFFFFFF, -0xFFFFFFFF, 0x5FDFFFFF, 0x0FCF1FDC, 0x1FDC1FFF, -0x00000000, 0x00004C40, 0x00000000, 0x00000000, -0x00000007, 0x00000000, 0x00000000, 0x00000000, -0x00000080, 0x000003FE, 0xFFFFFFFE, 0xFFFFFFFF, -0x001FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x07FFFFFF, -0xFFFFFFE0, 0x00001FFF, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, -0xFFFFFFFF, 0x0000003F, 0x00000000, 0x00000000, -0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, -0xFFFFFFFF, 0x0000000F, 0x00000000, 0x00000000, -0x00000000, 0x07FF6000, 0x87FFFFFE, 0x07FFFFFE, -0x00000000, 0x00800000, 0xFF7FFFFF, 0xFF7FFFFF, -0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF, -0xFFFFFFFF, 0xF80001FF, 0x00030003, 0x00000000, -0xFFFFFFFF, 0xFFFFFFFF, 0x0000003F, 0x00000003, -0xFFFFD7C0, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD, -0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF, -0xFFFF007B, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF, -0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE, -0xFFFE007F, 0xBBFFFFFB, 0xFFFF0016, 0x000707FF, -0x00000000, 0x07FFFFFE, 0x0007FFFF, 0xFFFF03FF, -0xFFFFFFFF, 0x7CFFFFFF, 0xFFEF7FFF, 0x03FF3DFF, -0xFFFFFFEE, 0xF3FFFFFF, 0xFF1E3FFF, 0x0000FFCF, -0xFFF99FEE, 0xD3C5FDFF, 0xB080399F, 0x0003FFCF, -0xFFF987E4, 0xD36DFDFF, 0x5E003987, 0x001FFFC0, -0xFFFBAFEE, 0xF3EDFDFF, 0x00003BBF, 0x0000FFC1, -0xFFF99FEE, 0xF3CDFDFF, 0xB0C0398F, 0x0000FFC3, -0xD63DC7EC, 0xC3BFC718, 0x00803DC7, 0x0000FF80, -0xFFFDDFEE, 0xC3EFFDFF, 0x00603DDF, 0x0000FFC3, -0xFFFDDFEC, 0xC3EFFDFF, 0x40603DDF, 0x0000FFC3, -0xFFFDDFEC, 0xC3FFFDFF, 0x00803DCF, 0x0000FFC3, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0xFFFFFFFE, 0x07FF7FFF, 0x03FF7FFF, 0x00000000, -0xFEF02596, 0x3BFF6CAE, 0x03FF3F5F, 0x00000000, -0x03000000, 0xC2A003FF, 0xFFFFFEFF, 0xFFFE03FF, -0xFEBF0FDF, 0x02FE3FFF, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x1FFF0000, 0x00000002, -0x000000A0, 0x003EFFFE, 0xFFFFFFFE, 0xFFFFFFFF, -0x661FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x77FFFFFF, -}; -static const unsigned char nmstrtPages[] = { -0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, -0x00, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, -0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13, -0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x15, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static const unsigned char namePages[] = { -0x19, 0x03, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x00, -0x00, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, -0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13, -0x26, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x27, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; diff --git a/libs/xmlrpc-c/lib/expat/xmltok/xmlrole.h b/libs/xmlrpc-c/lib/expat/xmltok/xmlrole.h index 3cccb83..523b3da 100644 --- a/libs/xmlrpc-c/lib/expat/xmltok/xmlrole.h +++ b/libs/xmlrpc-c/lib/expat/xmltok/xmlrole.h @@ -3,9 +3,10 @@ Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd See the file copying.txt for copying permission. */ -#ifndef XmlRole_INCLUDED -#define XmlRole_INCLUDED 1 +#ifndef XMLROLE_H_INCLUDED +#define XMLROLE_H_INCLUDED +#include "xmlrpc-c/c_util.h" #include "xmltok.h" #ifdef __cplusplus @@ -80,10 +81,10 @@ typedef struct prolog_state { int documentEntity; } PROLOG_STATE; -XMLTOKAPI void +XMLRPC_DLLEXPORT void xmlrpc_XmlPrologStateInit(PROLOG_STATE * const state); -XMLTOKAPI void +XMLRPC_DLLEXPORT void xmlrpc_XmlPrologStateInitExternalEntity(PROLOG_STATE * const state); #define XmlTokenRole(state, tok, ptr, end, enc) \ diff --git a/libs/xmlrpc-c/lib/expat/xmltok/xmltok.c b/libs/xmlrpc-c/lib/expat/xmltok/xmltok.c index 9eb8284..969ac23 100644 --- a/libs/xmlrpc-c/lib/expat/xmltok/xmltok.c +++ b/libs/xmlrpc-c/lib/expat/xmltok/xmltok.c @@ -4,6 +4,7 @@ See the file copying.txt for copying permission. */ #include "xmlrpc_config.h" +#include "bool.h" #include "xmldef.h" #include "xmltok.h" #include "nametab.h" @@ -357,31 +358,48 @@ static const struct normal_encoding internal_utf8_encoding = { STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_) }; -static -void latin1_toUtf8(const ENCODING *enc ATTR_UNUSED, - const char **fromP, const char *fromLim, - char **toP, const char *toLim) -{ - for (;;) { - unsigned char c; - if (*fromP == fromLim) - break; - c = (unsigned char)**fromP; - if (c & 0x80) { - if (toLim - *toP < 2) - break; - *(*toP)++ = ((c >> 6) | UTF8_cval2); - *(*toP)++ = ((c & 0x3f) | 0x80); - (*fromP)++; - } - else { - if (*toP == toLim) - break; - *(*toP)++ = *(*fromP)++; + + +static void +latin1_toUtf8(const ENCODING * const enc ATTR_UNUSED, + const char ** const fromP, + const char * const fromLim, + char ** const toP, + const char * const toLim) { +/*---------------------------------------------------------------------------- + Convert the Latin1 string that starts at *fromP and ends at 'fromLim' + to UTF8 in the buffer that starts at *toP and ends at 'toLim'. + + Go from left to right and stop when the output buffer is full. + + Note that the buffer can be full while still having a byte left in it + because a Latin1 character may require two bytes of the output buffer. + + Leave *fromP and *toP pointing after the last character converted. +-----------------------------------------------------------------------------*/ + bool bufferIsFull; + + for (bufferIsFull = false; *fromP != fromLim && !bufferIsFull;) { + unsigned char const c = (unsigned char)**fromP; + if (c & 0x80) { + if (toLim - *toP < 2) + bufferIsFull = true; + else { + *(*toP)++ = ((c >> 6) | UTF8_cval2); + *(*toP)++ = ((c & 0x3f) | 0x80); + ++(*fromP); + } + } else { + if (*toP == toLim) + bufferIsFull = true; + else + *(*toP)++ = *(*fromP)++; + } } - } } + + static void latin1_toUtf16(const ENCODING *enc ATTR_UNUSED, const char **fromP, const char *fromLim, diff --git a/libs/xmlrpc-c/lib/expat/xmltok/xmltok.dsp b/libs/xmlrpc-c/lib/expat/xmltok/xmltok.dsp deleted file mode 100644 index 58a70ef..0000000 --- a/libs/xmlrpc-c/lib/expat/xmltok/xmltok.dsp +++ /dev/null @@ -1,259 +0,0 @@ -# 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) Dynamic-Link Library" 0x0102 -# 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 "xmltok - Win32 Release DLL" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE "xmltok - Win32 Debug DLL" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "xmltok" -# PROP Scc_LocalPath ".." - -!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 "." -LINK32=link.exe -lib -MTL=midl.exe -CPP=cl.exe -# 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 XMLTOKAPI=__declspec(dllexport) /D "WIN32" /D "_WINDOWS" /D "XML_DTD" /D "_MBCS" /D "_LIB" /YX /FD /c -RSC=rc.exe -# 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 - -!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 "." -LINK32=link.exe -lib -MTL=midl.exe -CPP=cl.exe -# 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 /MDd /W3 /Gm /GX /ZI /Od /I "..\..\.." /D "_DEBUG" /D XMLTOKAPI=__declspec(dllexport) /D "WIN32" /D "_WINDOWS" /D "XML_DTD" /D "XML_NS" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c -RSC=rc.exe -# 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 - -!ELSEIF "$(CFG)" == "xmltok - Win32 Release DLL" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir ".\ReleaseDLL" -# PROP BASE Intermediate_Dir ".\ReleaseDLL" -# PROP BASE Target_Dir "." -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "ReleaseDLL\xmltok" -# PROP Intermediate_Dir "ReleaseDLL\xmltok" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "." -CPP=cl.exe -# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c -# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\.." /D "NDEBUG" /D "XML_NS" /D XMLTOKAPI=__declspec(dllexport) /D "WIN32" /D "_WINDOWS" /D "XML_DTD" /YX /FD /c -MTL=midl.exe -# ADD BASE MTL /nologo /D "NDEBUG" /win32 -# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -RSC=rc.exe -# 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:windows /dll /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 /entry:"DllMain" /subsystem:windows /dll /machine:I386 /out:"..\..\xmltok.dll" /link50compat -# SUBTRACT LINK32 /pdb:none - -!ELSEIF "$(CFG)" == "xmltok - Win32 Debug DLL" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir ".\DebugDLL" -# PROP BASE Intermediate_Dir ".\DebugDLL" -# PROP BASE Target_Dir "." -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "DebugDLL\xmltok" -# PROP Intermediate_Dir "DebugDLL\xmltok" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "." -CPP=cl.exe -# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c -# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\.." /D "_DEBUG" /D XMLTOKAPI=__declspec(dllexport) /D "WIN32" /D "_WINDOWS" /D "XML_DTD" /D "XML_NS" /YX /FD /c -MTL=midl.exe -# ADD BASE MTL /nologo /D "_DEBUG" /win32 -# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -RSC=rc.exe -# 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:windows /dll /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:windows /dll /debug /machine:I386 /out:"..\..\xmltokD.dll" - -!ENDIF - -# Begin Target - -# Name "xmltok - Win32 Release" -# Name "xmltok - Win32 Debug" -# Name "xmltok - Win32 Release DLL" -# Name "xmltok - Win32 Debug DLL" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90" -# Begin Source File - -SOURCE=.\dllmain.c - -!IF "$(CFG)" == "xmltok - Win32 Release" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "xmltok - Win32 Debug" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "xmltok - Win32 Release DLL" - -!ELSEIF "$(CFG)" == "xmltok - Win32 Debug DLL" - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=..\gennmtab\gennmtab.c - -!IF "$(CFG)" == "xmltok - Win32 Release" - -# PROP Ignore_Default_Tool 1 - -!ELSEIF "$(CFG)" == "xmltok - Win32 Debug" - -# PROP Ignore_Default_Tool 1 - -!ELSEIF "$(CFG)" == "xmltok - Win32 Release DLL" - -!ELSEIF "$(CFG)" == "xmltok - Win32 Debug DLL" - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\xmlrole.c -# End Source File -# Begin Source File - -SOURCE=.\xmltok.c -# End Source File -# Begin Source File - -SOURCE=.\xmltok_impl.c -# PROP BASE Exclude_From_Build 1 -# PROP Exclude_From_Build 1 -# End Source File -# Begin Source File - -SOURCE=.\xmltok_ns.c -# PROP Exclude_From_Build 1 -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" -# Begin Source File - -SOURCE=.\asciitab.h -# End Source File -# Begin Source File - -SOURCE=.\iasciitab.h -# End Source File -# Begin Source File - -SOURCE=.\latin1tab.h -# End Source File -# Begin Source File - -SOURCE=.\nametab.h -# End Source File -# Begin Source File - -SOURCE=.\utf8tab.h -# End Source File -# Begin Source File - -SOURCE=.\xmldef.h -# End Source File -# Begin Source File - -SOURCE=.\xmlrole.h -# End Source File -# Begin Source File - -SOURCE=.\xmltok.h -# End Source File -# Begin Source File - -SOURCE=.\xmltok_impl.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 diff --git a/libs/xmlrpc-c/lib/expat/xmltok/xmltok.h b/libs/xmlrpc-c/lib/expat/xmltok/xmltok.h index 453568f..e24a78c 100644 --- a/libs/xmlrpc-c/lib/expat/xmltok/xmltok.h +++ b/libs/xmlrpc-c/lib/expat/xmltok/xmltok.h @@ -3,17 +3,15 @@ Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd See the file copying.txt for copying permission. */ -#ifndef XmlTok_INCLUDED -#define XmlTok_INCLUDED 1 +#ifndef XMLTOK_H_INCLUDED +#define XMLTOK_H_INCLUDED + +#include "xmlrpc-c/c_util.h" #ifdef __cplusplus extern "C" { #endif -#ifndef XMLTOKAPI -#define XMLTOKAPI /* as nothing */ -#endif - /* The following token may be returned by XmlContentTok */ #define XML_TOK_TRAILING_RSQB -5 /* ] or ]] at the end of the scan; might be start of illegal ]]> sequence */ @@ -130,7 +128,7 @@ struct encoding { const char *, const char *); int (*nameMatchesAscii)(const ENCODING *, const char *, const char *, const char *); - int (*nameLength)(const ENCODING *, const char *); + size_t (*nameLength)(const ENCODING *, const char *); const char *(*skipS)(const ENCODING *, const char *); int (*getAtts)(const ENCODING *enc, const char *ptr, int attsMax, ATTRIBUTE *atts); @@ -242,7 +240,8 @@ typedef struct { const ENCODING **encPtr; } INIT_ENCODING; -XMLTOKAPI int +XMLRPC_DLLEXPORT +int xmlrpc_XmlParseXmlDecl(int const isGeneralTextEntity, const ENCODING * const enc, const char * const ptr, @@ -253,34 +252,42 @@ xmlrpc_XmlParseXmlDecl(int const isGeneralTextEntity, const ENCODING ** const namedEncodingPtr, int * const standalonePtr); -XMLTOKAPI const ENCODING * +XMLRPC_DLLEXPORT +const ENCODING * xmlrpc_XmlGetUtf8InternalEncoding(void); -XMLTOKAPI const ENCODING * +XMLRPC_DLLEXPORT +const ENCODING * xmlrpc_XmlGetUtf16InternalEncoding(void); -XMLTOKAPI int +XMLRPC_DLLEXPORT +int xmlrpc_XmlInitEncoding(INIT_ENCODING * const p, const ENCODING ** const encPtr, const char * const name); -XMLTOKAPI int +XMLRPC_DLLEXPORT +int xmlrpc_XmlUtf8Encode(int const c, char * const buf); -XMLTOKAPI int +XMLRPC_DLLEXPORT +int xmlrpc_XmlUtf16Encode(int const charNum, unsigned short * const buf); -XMLTOKAPI int +XMLRPC_DLLEXPORT +int xmlrpc_XmlSizeOfUnknownEncoding(void); -XMLTOKAPI ENCODING * +XMLRPC_DLLEXPORT +ENCODING * xmlrpc_XmlInitUnknownEncoding(void * const mem, int * const table, int (*convert)(void *userData, const char *p), void * const userData); +XMLRPC_DLLEXPORT int xmlrpc_XmlParseXmlDeclNS(int const isGeneralTextEntity, const ENCODING * const enc, @@ -292,17 +299,21 @@ xmlrpc_XmlParseXmlDeclNS(int const isGeneralTextEntity, const ENCODING ** const namedEncodingPtr, int * const standalonePtr); +XMLRPC_DLLEXPORT int xmlrpc_XmlInitEncodingNS(INIT_ENCODING * const p, const ENCODING ** const encPtr, const char * const name); +XMLRPC_DLLEXPORT const ENCODING * xmlrpc_XmlGetUtf8InternalEncodingNS(void); +XMLRPC_DLLEXPORT const ENCODING * xmlrpc_XmlGetUtf16InternalEncodingNS(void); +XMLRPC_DLLEXPORT ENCODING * xmlrpc_XmlInitUnknownEncodingNS(void * const mem, int * const table, diff --git a/libs/xmlrpc-c/lib/expat/xmltok/xmltok_impl.c b/libs/xmlrpc-c/lib/expat/xmltok/xmltok_impl.c index cc9bc59..2bbc8db 100644 --- a/libs/xmlrpc-c/lib/expat/xmltok/xmltok_impl.c +++ b/libs/xmlrpc-c/lib/expat/xmltok/xmltok_impl.c @@ -26,7 +26,7 @@ See the file copying.txt for copying permission. case BT_MALFORM: \ case BT_TRAIL: \ *(nextTokPtr) = (ptr); \ - return XML_TOK_INVALID; + return XML_TOK_INVALID #define CHECK_NAME_CASE(n, enc, ptr, end, nextTokPtr) \ case BT_LEAD ## n: \ @@ -99,7 +99,7 @@ int PREFIX(scanComment)(const ENCODING *enc, const char *ptr, const char *end, ptr += MINBPC(enc); while (ptr != end) { switch (BYTE_TYPE(enc, ptr)) { - INVALID_CASES(ptr, nextTokPtr) + INVALID_CASES(ptr, nextTokPtr); case BT_MINUS: if ((ptr += MINBPC(enc)) == end) return XML_TOK_PARTIAL; @@ -244,7 +244,7 @@ int PREFIX(scanPi)(const ENCODING *enc, const char *ptr, const char *end, ptr += MINBPC(enc); while (ptr != end) { switch (BYTE_TYPE(enc, ptr)) { - INVALID_CASES(ptr, nextTokPtr) + INVALID_CASES(ptr, nextTokPtr); case BT_QUEST: ptr += MINBPC(enc); if (ptr == end) @@ -345,7 +345,7 @@ int PREFIX(cdataSectionTok)(const ENCODING *enc, const char *ptr, const char *en case BT_LF: *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_DATA_NEWLINE; - INVALID_CASES(ptr, nextTokPtr) + INVALID_CASES(ptr, nextTokPtr); default: ptr += MINBPC(enc); break; @@ -598,7 +598,7 @@ int PREFIX(scanAtts)(const ENCODING *enc, const char *ptr, const char *end, if (t == open) break; switch (t) { - INVALID_CASES(ptr, nextTokPtr) + INVALID_CASES(ptr, nextTokPtr); case BT_AMP: { int tok = PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, &ptr); @@ -768,103 +768,179 @@ int PREFIX(scanLt)(const ENCODING *enc, const char *ptr, const char *end, return XML_TOK_PARTIAL; } -static -int PREFIX(contentTok)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - if (ptr == end) - return XML_TOK_NONE; - if (MINBPC(enc) > 1) { - size_t n = end - ptr; - if (n & (MINBPC(enc) - 1)) { - n &= ~(MINBPC(enc) - 1); - if (n == 0) - return XML_TOK_PARTIAL; - end = ptr + n; - } - } - switch (BYTE_TYPE(enc, ptr)) { - case BT_LT: - return PREFIX(scanLt)(enc, ptr + MINBPC(enc), end, nextTokPtr); - case BT_AMP: - return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); - case BT_CR: - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_TRAILING_CR; - if (BYTE_TYPE(enc, ptr) == BT_LF) - ptr += MINBPC(enc); - *nextTokPtr = ptr; - return XML_TOK_DATA_NEWLINE; - case BT_LF: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_DATA_NEWLINE; - case BT_RSQB: - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_TRAILING_RSQB; - if (!CHAR_MATCHES(enc, ptr, ASCII_RSQB)) - break; - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_TRAILING_RSQB; - if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) { - ptr -= MINBPC(enc); - break; - } - *nextTokPtr = ptr; - return XML_TOK_INVALID; - INVALID_CASES(ptr, nextTokPtr) - default: - ptr += MINBPC(enc); - break; - } - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { + + #define LEAD_CASE(n) \ case BT_LEAD ## n: \ - if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \ - *nextTokPtr = ptr; \ - return XML_TOK_DATA_CHARS; \ - } \ - ptr += n; \ - break; - LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) -#undef LEAD_CASE - case BT_RSQB: - if (ptr + MINBPC(enc) != end) { - if (!CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_RSQB)) { - ptr += MINBPC(enc); - break; - } - if (ptr + 2*MINBPC(enc) != end) { - if (!CHAR_MATCHES(enc, ptr + 2*MINBPC(enc), ASCII_GT)) { - ptr += MINBPC(enc); - break; - } - *nextTokPtr = ptr + 2*MINBPC(enc); - return XML_TOK_INVALID; - } - } - /* fall through */ - case BT_AMP: - case BT_LT: - case BT_NONXML: - case BT_MALFORM: - case BT_TRAIL: - case BT_CR: - case BT_LF: - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; - default: - ptr += MINBPC(enc); - break; + if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \ + *nextTokPtr = ptr; \ + return XML_TOK_DATA_CHARS; \ + } \ + ptr += n; \ + break + + + +static void +PREFIX(chopToWholeCharacters)(const char * const inputStart, + const char * const inputEnd, + const char ** const choppedEndP) { + + if (MINBPC(enc) > 1) { + size_t const length = inputEnd - inputStart; + if (length & (MINBPC(enc) - 1)) { + size_t const roundedLen = length & ~(MINBPC(enc) - 1); + *choppedEndP = inputStart + roundedLen; + } else + *choppedEndP = inputEnd; + } else + *choppedEndP = inputEnd; +} + + + +static void +PREFIX(processBtRsqb)(const ENCODING * const enc ATTR_UNUSED, + const char * const start, + const char * const end, + unsigned int * const countP, + bool * const invalidP) { + + if (start + MINBPC(enc) < end) { + if (!CHAR_MATCHES(enc, start + MINBPC(enc), ASCII_RSQB)) { + *countP = MINBPC(enc); + *invalidP = false; + } else { + if (start + 2*MINBPC(enc) < end) { + if (!CHAR_MATCHES(enc, start + 2*MINBPC(enc), ASCII_GT)) { + *countP = MINBPC(enc); + *invalidP = false; + } else { + *countP = 2 * MINBPC(enc); + *invalidP = true; + } + } else { + *countP = 0; + *invalidP = false; + } + } + } else { + *countP = 0; + *invalidP = false; } - } - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; } + + +static int +PREFIX(contentTok)(const ENCODING * const enc, + const char * const inputStart, + const char * const inputEnd, + const char ** const nextTokPtr) { +/*---------------------------------------------------------------------------- + Parse off a token from the string that starts at 'inputStart' and ends at + 'inputEnd'. Return the class of that token. + + Return *nextTokPtr pointing just after the parsed-off token in the string. + + Sometimes, there is no token we can parse, so our return value is a + disposition code indicating that situation and *nextTokPtr points to the + beginning of the string. +-----------------------------------------------------------------------------*/ + if (inputEnd == inputStart) { + *nextTokPtr = inputStart; + return XML_TOK_NONE; + } else { + const char * ptr; + const char * end; + /* The virtual end of the string; we look at only whole + characters; e.g. if there are 2 bytes per character and the + buffer is 9 bytes, we look at only the first 8 and 'end' points + after the 8th byte. + */ + PREFIX(chopToWholeCharacters)(inputStart, inputEnd, &end); + + if (end == inputStart) { + *nextTokPtr = inputStart; + return XML_TOK_PARTIAL; + } + ptr = inputStart; /* Start at the beginning */ + + switch (BYTE_TYPE(enc, ptr)) { + case BT_LT: + return PREFIX(scanLt)(enc, ptr + MINBPC(enc), end, nextTokPtr); + case BT_AMP: + return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); + case BT_CR: + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_TRAILING_CR; + if (BYTE_TYPE(enc, ptr) == BT_LF) + ptr += MINBPC(enc); + *nextTokPtr = ptr; + return XML_TOK_DATA_NEWLINE; + case BT_LF: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_DATA_NEWLINE; + case BT_RSQB: + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_TRAILING_RSQB; + if (!CHAR_MATCHES(enc, ptr, ASCII_RSQB)) + break; + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_TRAILING_RSQB; + if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) { + ptr -= MINBPC(enc); + break; + } + *nextTokPtr = ptr; + return XML_TOK_INVALID; + INVALID_CASES(ptr, nextTokPtr); + default: + ptr += MINBPC(enc); + break; + } + while (ptr < end) { + switch (BYTE_TYPE(enc, ptr)) { + LEAD_CASE(2); + LEAD_CASE(3); + LEAD_CASE(4); + case BT_RSQB: { + bool invalid; + unsigned int count; + PREFIX(processBtRsqb)(enc, ptr, end, &count, &invalid); + ptr += count; + if (invalid) { + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + } + /* fall through */ + case BT_AMP: + case BT_LT: + case BT_NONXML: + case BT_MALFORM: + case BT_TRAIL: + case BT_CR: + case BT_LF: + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + default: + ptr += MINBPC(enc); + break; + } + } + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + } +} + +#undef LEAD_CASE + + + /* ptr points to character following "%" */ static @@ -931,7 +1007,7 @@ int PREFIX(scanLit)(int open, const ENCODING *enc, while (ptr != end) { int t = BYTE_TYPE(enc, ptr); switch (t) { - INVALID_CASES(ptr, nextTokPtr) + INVALID_CASES(ptr, nextTokPtr); case BT_QUOT: case BT_APOS: ptr += MINBPC(enc); @@ -1305,7 +1381,7 @@ int PREFIX(ignoreSectionTok)(const ENCODING *enc, const char *ptr, const char *e } while (ptr != end) { switch (BYTE_TYPE(enc, ptr)) { - INVALID_CASES(ptr, nextTokPtr) + INVALID_CASES(ptr, nextTokPtr); case BT_LT: if ((ptr += MINBPC(enc)) == end) return XML_TOK_PARTIAL; @@ -1664,30 +1740,38 @@ int PREFIX(nameMatchesAscii)(const ENCODING * enc ATTR_UNUSED, return ptr1 == end1; } -static -int PREFIX(nameLength)(const ENCODING *enc, const char *ptr) -{ - const char *start = ptr; - for (;;) { - switch (BYTE_TYPE(enc, ptr)) { -#define LEAD_CASE(n) \ - case BT_LEAD ## n: ptr += n; break; - LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) -#undef LEAD_CASE - case BT_NONASCII: - case BT_NMSTRT: - case BT_COLON: - case BT_HEX: - case BT_DIGIT: - case BT_NAME: - case BT_MINUS: - ptr += MINBPC(enc); - break; - default: - return ptr - start; + + +#define LEAD_CASE(n) case BT_LEAD ## n: ptr += n; break + +static size_t +PREFIX(nameLength)(const ENCODING * const enc, + const char * const start) { + + const char * ptr; + + for (ptr = start;;) { + switch (BYTE_TYPE(enc, ptr)) { + LEAD_CASE(2); + LEAD_CASE(3); + LEAD_CASE(4); + case BT_NONASCII: + case BT_NMSTRT: + case BT_COLON: + case BT_HEX: + case BT_DIGIT: + case BT_NAME: + case BT_MINUS: + ptr += MINBPC(enc); + break; + default: + return ptr - start; + } } - } } +#undef LEAD_CASE + + static const char *PREFIX(skipS)(const ENCODING *enc, const char *ptr) @@ -1705,40 +1789,49 @@ const char *PREFIX(skipS)(const ENCODING *enc, const char *ptr) } } -static -void PREFIX(updatePosition)(const ENCODING *enc, - const char *ptr, - const char *end, - POSITION *pos) -{ - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { + + #define LEAD_CASE(n) \ case BT_LEAD ## n: \ ptr += n; \ - break; - LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) -#undef LEAD_CASE - case BT_LF: - pos->columnNumber = (unsigned)-1; - pos->lineNumber++; - ptr += MINBPC(enc); - break; - case BT_CR: - pos->lineNumber++; - ptr += MINBPC(enc); - if (ptr != end && BYTE_TYPE(enc, ptr) == BT_LF) - ptr += MINBPC(enc); - pos->columnNumber = (unsigned)-1; - break; - default: - ptr += MINBPC(enc); - break; + break + +static void +PREFIX(updatePosition)(const ENCODING * const enc, + const char * const start, + const char * const end, + POSITION * const posP) { + + const char * ptr; + + for (ptr = start; ptr < end;) { + switch (BYTE_TYPE(enc, ptr)) { + LEAD_CASE(2); + LEAD_CASE(3); + LEAD_CASE(4); + case BT_LF: + posP->columnNumber = (unsigned)-1; + ++posP->lineNumber; + ptr += MINBPC(enc); + break; + case BT_CR: + ++posP->lineNumber; + ptr += MINBPC(enc); + if (ptr != end && BYTE_TYPE(enc, ptr) == BT_LF) + ptr += MINBPC(enc); + posP->columnNumber = (unsigned)-1; + break; + default: + ptr += MINBPC(enc); + break; + } + ++posP->columnNumber; } - pos->columnNumber++; - } } +#undef LEAD_CASE + + #undef DO_LEAD_CASE #undef MULTIBYTE_CASES #undef INVALID_CASES diff --git a/libs/xmlrpc-c/lib/expat/xmlwf/.cvsignore b/libs/xmlrpc-c/lib/expat/xmlwf/.cvsignore deleted file mode 100644 index f3c7a7c..0000000 --- a/libs/xmlrpc-c/lib/expat/xmlwf/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -Makefile diff --git a/libs/xmlrpc-c/lib/expat/xmlwf/xmlfile.c b/libs/xmlrpc-c/lib/expat/xmlwf/xmlfile.c index 5b3b978..8675790 100644 --- a/libs/xmlrpc-c/lib/expat/xmlwf/xmlfile.c +++ b/libs/xmlrpc-c/lib/expat/xmlwf/xmlfile.c @@ -17,7 +17,7 @@ See the file copying.txt for copying permission. #include #endif -#ifdef _POSIX_SOURCE +#ifdef _XOPEN_SOURCE 600 #include #endif diff --git a/libs/xmlrpc-c/lib/libutil/Makefile b/libs/xmlrpc-c/lib/libutil/Makefile index 7c75a37..5e53b47 100644 --- a/libs/xmlrpc-c/lib/libutil/Makefile +++ b/libs/xmlrpc-c/lib/libutil/Makefile @@ -1,7 +1,9 @@ ############################################################################### # This directory builds libxmlrpc_util, which contains utility -# functions that are used by the Xmlprc-c # libraries, and also -# directly by Xmlrpc-c programs. +# functions that are used by the Xmlprc-c libraries, and also +# directly by Xmlrpc-c programs. Some of them are documented for use +# by Xmlrpc-c users, as facilities of the libxmlrpc library (which +# prerequires libxmlrpc_util). # # The functions in this library are characterized by being general purpose # programming functions, such as one might wish were in the standard C @@ -29,11 +31,13 @@ SHARED_LIBS_TO_INSTALL := libxmlrpc_util TARGET_MODS = \ asprintf \ + base64 \ error \ make_printable \ memblock \ select \ sleep \ + string_number \ time \ utf8 \ @@ -43,8 +47,6 @@ MAJ=3 include $(SRCDIR)/common.mk -CFLAGS = $(CFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD) - INCLUDES = -I$(BLDDIR) -Isrcdir \ -I$(BLDDIR)/include -Isrcdir/include -Isrcdir/lib/util/include @@ -53,17 +55,13 @@ UTIL_SHLIB = $(call shlibfn,libxmlrpc_util) 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) +all: libxmlrpc_util.a $(TARGET_SHARED_LIBRARIES) $(TARGET_SHARED_LE_LIBS) # Rule for this is in common.mk, courtesy of TARGET_LIBRARY_NAMES: $(UTIL_SHLIB): $(TARGET_MODS:%=%.osh) @@ -92,4 +90,4 @@ distclean: clean distclean-common .PHONY: dep dep: dep-common -include Makefile.depend +include depend.mk diff --git a/libs/xmlrpc-c/lib/libutil/asprintf.c b/libs/xmlrpc-c/lib/libutil/asprintf.c index 9e5a614..b525230 100644 --- a/libs/xmlrpc-c/lib/libutil/asprintf.c +++ b/libs/xmlrpc-c/lib/libutil/asprintf.c @@ -1,10 +1,61 @@ -//#define _GNU_SOURCE +#define _XOPEN_SOURCE 600 /* Make sure strdup() is in */ +#ifndef _GNU_SOURCE + #define _GNU_SOURCE /* But only when HAVE_ASPRINTF */ +#endif +#include + #include #include #include +#include #include "xmlrpc_config.h" /* For HAVE_ASPRINTF, __inline__ */ #include "xmlrpc-c/string_int.h" +#include "bool.h" + + + +static __inline__ void +newVsnprintf(char * const buffer, + size_t const bufferSize, + const char * const fmt, + va_list varargs, + size_t * const formattedSizeP) { +/*---------------------------------------------------------------------------- + This is vsnprintf() with the new behavior, where not fitting in the buffer + is not a failure. + + Unfortunately, we can't practically return the size of the formatted string + if the C library has old vsnprintf() and the formatted string doesn't fit + in the buffer, so in that case we just return something larger than the + buffer. +-----------------------------------------------------------------------------*/ + if (bufferSize > INT_MAX/2) { + /* There's a danger we won't be able to coerce the return value + of XMLRPC_VSNPRINTF to an integer (which we have to do because, + while for POSIX its return value is ssize_t, on Windows it is int), + or return double the buffer size. + */ + *formattedSizeP = 0; + } else { + int rc; + + rc = XMLRPC_VSNPRINTF(buffer, bufferSize, fmt, varargs); + + if (rc < 0) { + /* We have old vsnprintf() (or Windows) and the formatted value + doesn't fit in the buffer, but we don't know how big a buffer it + needs. + */ + *formattedSizeP = bufferSize * 2; + } else { + /* Either the string fits in the buffer or we have new vsnprintf() + which tells us how big the string is regardless. + */ + *formattedSizeP = rc; + } + } +} @@ -15,29 +66,24 @@ simpleVasprintf(char ** const retvalP, /*---------------------------------------------------------------------------- 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. - */ + size_t bufferSize; + bool outOfMemory; + + for (result = NULL, bufferSize = 4096, outOfMemory = false; + !result && !outOfMemory; + ) { + + result = malloc(bufferSize); + if (!result) + outOfMemory = true; + else { + size_t bytesNeeded; + newVsnprintf(result, bufferSize, fmt, varargs, &bytesNeeded); + if (bytesNeeded > bufferSize) { free(result); result = NULL; + bufferSize = bytesNeeded; } } } @@ -46,7 +92,28 @@ simpleVasprintf(char ** const retvalP, -const char * const xmlrpc_strsol = "[insufficient memory to build string]"; +static const char * const xmlrpc_strsol = + "[insufficient memory to build string]"; + + + +bool +xmlrpc_strnomem(const char * const string) { +/*---------------------------------------------------------------------------- + The string 'string' was generated by a function in this file because it + couldn't get enough memory to generate the string that it was supposed to + generate. I.e. a preceding call to a string function failed. +-----------------------------------------------------------------------------*/ + return string == xmlrpc_strsol; +} + + + +const char * +xmlrpc_strnomemval() { + + return xmlrpc_strsol; +} @@ -71,7 +138,7 @@ xmlrpc_vasprintf(const char ** const retvalP, -void GNU_PRINTF_ATTR(2,3) +void XMLRPC_PRINTF_ATTR(2,3) xmlrpc_asprintf(const char ** const retvalP, const char * const fmt, ...) { va_list varargs; /* mysterious structure used by variable arg facility */ @@ -86,12 +153,13 @@ xmlrpc_asprintf(const char ** const retvalP, const char * const fmt, ...) { const char * -xmlrpc_strdupnull(const char * const string) { +xmlrpc_strdupsol(const char * const string) { - if (string) - return strdup(string); - else - return NULL; + const char * retvalOrNull; + + retvalOrNull = strdup(string); + + return retvalOrNull ? retvalOrNull : xmlrpc_strsol; } @@ -105,6 +173,17 @@ xmlrpc_strfree(const char * const string) { +const char * +xmlrpc_strdupnull(const char * const string) { + + if (string) + return strdup(string); + else + return NULL; +} + + + void xmlrpc_strfreenull(const char * const string) { diff --git a/libs/xmlrpc-c/lib/libutil/base64.c b/libs/xmlrpc-c/lib/libutil/base64.c new file mode 100644 index 0000000..9376eee --- /dev/null +++ b/libs/xmlrpc-c/lib/libutil/base64.c @@ -0,0 +1,49 @@ +#include + +#include "int.h" +#include "xmlrpc-c/base64_int.h" + + + +void +xmlrpc_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','+','/' + }; + + unsigned int 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'; +} diff --git a/libs/xmlrpc-c/lib/libutil/error.c b/libs/xmlrpc-c/lib/libutil/error.c index fd964d0..ff3bbe1 100644 --- a/libs/xmlrpc-c/lib/libutil/error.c +++ b/libs/xmlrpc-c/lib/libutil/error.c @@ -1,5 +1,7 @@ /* Copyright information is at end of file */ +#define _XOPEN_SOURCE 600 /* Make sure strdup() is in */ + #include "xmlrpc_config.h" #include @@ -86,7 +88,7 @@ void xmlrpc_set_fault_formatted_v(xmlrpc_env * const envP, int const code, const char * const format, - va_list const args) { + va_list args) { const char * faultDescription; diff --git a/libs/xmlrpc-c/lib/libutil/make_printable.c b/libs/xmlrpc-c/lib/libutil/make_printable.c index fc94f78..444a733 100644 --- a/libs/xmlrpc-c/lib/libutil/make_printable.c +++ b/libs/xmlrpc-c/lib/libutil/make_printable.c @@ -1,4 +1,4 @@ -//#define _GNU_SOURCE +#define _XOPEN_SOURCE 600 /* Make sure strdup() is in */ #include #include diff --git a/libs/xmlrpc-c/lib/libutil/memblock.c b/libs/xmlrpc-c/lib/libutil/memblock.c index d79d4ca..f0119a8 100644 --- a/libs/xmlrpc-c/lib/libutil/memblock.c +++ b/libs/xmlrpc-c/lib/libutil/memblock.c @@ -6,6 +6,7 @@ #include #include +#include "mallocvar.h" #include "xmlrpc-c/util_int.h" #include "xmlrpc-c/util.h" @@ -19,30 +20,30 @@ xmlrpc_mem_block * -xmlrpc_mem_block_new(xmlrpc_env * const env, +xmlrpc_mem_block_new(xmlrpc_env * const envP, size_t const size) { - xmlrpc_mem_block* block; + 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_ASSERT_ENV_OK(envP); - xmlrpc_mem_block_init(env, block, size); - XMLRPC_FAIL_IF_FAULT(env); + MALLOCVAR(block); + + if (block == NULL) + xmlrpc_faultf(envP, "Can't allocate memory block"); + else { + xmlrpc_mem_block_init(envP, block, size); - cleanup: - if (env->fault_occurred) { - if (block) + if (envP->fault_occurred) { free(block); - return NULL; - } else { - return block; + block = NULL; + } } + return block; } + + /* Destroy an existing xmlrpc_mem_block, and everything it contains. */ void xmlrpc_mem_block_free(xmlrpc_mem_block * const blockP) { @@ -74,7 +75,7 @@ xmlrpc_mem_block_init(xmlrpc_env * const envP, blockP->_block = (void*) malloc(blockP->_allocated); if (!blockP->_block) xmlrpc_faultf(envP, "Can't allocate %u-byte memory block", - blockP->_allocated); + (unsigned)blockP->_allocated); } @@ -170,19 +171,15 @@ xmlrpc_mem_block_append(xmlrpc_env * const envP, const void * const data, size_t const len) { - int size; + size_t const originalSize = blockP->_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; + xmlrpc_mem_block_resize(envP, blockP, originalSize + len); + if (!envP->fault_occurred) { + memcpy(((unsigned char*) blockP->_block) + originalSize, data, len); + } } diff --git a/libs/xmlrpc-c/lib/libutil/select.c b/libs/xmlrpc-c/lib/libutil/select.c index 8999884..6a390d4 100644 --- a/libs/xmlrpc-c/lib/libutil/select.c +++ b/libs/xmlrpc-c/lib/libutil/select.c @@ -1,5 +1,7 @@ #define _XOPEN_SOURCE 600 /* Get pselect() in */ +#include "xmlrpc_config.h" + #ifdef WIN32 #include #else @@ -8,12 +10,12 @@ in this order appears to work on all. */ #include +#if HAVE_SYS_SELECT_H #include +#endif #endif #include -#include "xmlrpc_config.h" - #include "xmlrpc-c/select_int.h" diff --git a/libs/xmlrpc-c/lib/libutil/string_number.c b/libs/xmlrpc-c/lib/libutil/string_number.c new file mode 100644 index 0000000..1c284af --- /dev/null +++ b/libs/xmlrpc-c/lib/libutil/string_number.c @@ -0,0 +1,46 @@ +/*============================================================================ + string_number +============================================================================== + This file contains utilities for dealing with text string representation + of numbers. +============================================================================*/ +#include +#include +#include + +#include +#include +#include +#include "xmlrpc_config.h" +#include "int.h" + +#include + + + +void +xmlrpc_parse_int64(xmlrpc_env * const envP, + const char * const str, + xmlrpc_int64 * const i64P) { + + xmlrpc_int64 i64val; + + char * tail; + + errno = 0; + i64val = XMLRPC_STRTOLL(str, &tail, 10); + + if (errno == ERANGE) + xmlrpc_faultf(envP, "Number cannot be represented in 64 bits. " + "Must be in the range " + "[%" XMLRPC_PRId64 " - %" XMLRPC_PRId64 "]", + XMLRPC_INT64_MIN, XMLRPC_INT64_MAX); + else if (errno != 0) + xmlrpc_faultf(envP, "unexpected error: " + "strtoll() failed with errno %d (%s)", + errno, strerror(errno)); + else if (tail[0] != '\0') + xmlrpc_faultf(envP, "contains non-numerical junk: '%s'", tail); + else + *i64P = i64val; +} diff --git a/libs/xmlrpc-c/lib/libutil/utf8.c b/libs/xmlrpc-c/lib/libutil/utf8.c index d0de07e..77e436d 100644 --- a/libs/xmlrpc-c/lib/libutil/utf8.c +++ b/libs/xmlrpc-c/lib/libutil/utf8.c @@ -38,6 +38,7 @@ ** http://www.cl.cam.ac.uk/~mgk25/unicode.html */ +#include #include "int.h" #include "xmlrpc_config.h" @@ -51,31 +52,33 @@ ** 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 +static unsigned char utf8SeqLength[256] = { + + /* utf8SeqLength[B] is the number of bytes in a UTF-8 sequence that starts + with byte B. Except zero indicates an illegal initial byte. + + Fredrik Lundh's UTF-8 decoder Python 2.0 uses a similar table. But since + Python 2.0 has the icky CNRI license, I generated this table from scratch + and wrote my own decoder. + */ + + /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ + /* 0 */ 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, + /* 2 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /* 3 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /* 4 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /* 5 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /* 6 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /* 7 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /* 8 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 9 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* A */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* B */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* C */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + /* D */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + /* E */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + /* F */ 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 @@ -118,14 +121,129 @@ static uint32_t const utf8_min_char_for_length[] = { #if HAVE_UNICODE_WCHAR +static void +validateContinuation(xmlrpc_env * const envP, + char const c) { + + if (!IS_CONTINUATION(c)) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_INVALID_UTF8_ERROR, + "UTF-8 multibyte sequence contains character 0x%02x, " + "which does not indicate continuation.", c); +} + + + +static void +validateUtf16(xmlrpc_env * const envP, + wchar_t const wc) { + + if (wc > UCS2_MAX_LEGAL_CHARACTER) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_INVALID_UTF8_ERROR, + "UCS-2 characters > U+FFFD are illegal. String contains 0x%04x", + (unsigned)wc); + else if (UTF16_FIRST_SURROGATE <= wc && wc <= UTF16_LAST_SURROGATE) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_INVALID_UTF8_ERROR, + "UTF-16 surrogates may not appear in UTF-8 data. " + "String contains %04x", (unsigned)wc); +} + + + +/* Microsoft Visual C in debug mode produces code that complains about + returning an undefined value from xmlrpc_datetime_new_str(). It's a bogus + complaint, because this function is defined to return nothing meaningful + those cases. So we disable the check. +*/ +#pragma runtime_checks("u", off) + +static void +decodeMultibyte(xmlrpc_env * const envP, + const char * const utf8_seq, + size_t const length, + wchar_t * const wcP) { +/*---------------------------------------------------------------------------- + Decode the multibyte UTF-8 sequence which is 'length' characters + at 'utf8_data'. + + Return the character in UTF-16 format as *wcP. +-----------------------------------------------------------------------------*/ + wchar_t wc; + + assert(utf8_seq[0] & 0x80); /* High bit set: this is multibyte seq */ + + switch (length) { + case 2: + /* 110xxxxx 10xxxxxx */ + validateContinuation(envP, utf8_seq[1]); + + if (!envP->fault_occurred) + wc = ((((wchar_t) (utf8_seq[0] & 0x1F)) << 6) | + (((wchar_t) (utf8_seq[1] & 0x3F)))); + break; + + case 3: + /* 1110xxxx 10xxxxxx 10xxxxxx */ + validateContinuation(envP, utf8_seq[1]); + if (!envP->fault_occurred) { + validateContinuation(envP, utf8_seq[2]); + if (!envP->fault_occurred) + wc = ((((wchar_t) (utf8_seq[0] & 0x0F)) << 12) | + (((wchar_t) (utf8_seq[1] & 0x3F)) << 6) | + (((wchar_t) (utf8_seq[2] & 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 0x%02x)", + utf8_seq[0]); + break; + + default: + xmlrpc_faultf(envP, + "Internal error: Impossible UTF-8 sequence length %u", + (unsigned)length); + } + + if (!envP->fault_occurred) + validateUtf16(envP, wc); + + if (!envP->fault_occurred) + if ((uint32_t)wc < utf8_min_char_for_length[length]) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_INVALID_UTF8_ERROR, + "Overlong UTF-8 sequence not allowed"); + + *wcP = wc; +} + +#pragma runtime_checks("u", restore) + + + 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) { +decodeUtf8(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) + Decode to UCS-2 (or validate 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 @@ -134,132 +252,60 @@ decode_utf8(xmlrpc_env * const envP, 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; + size_t utf8Cursor; + size_t outPos; XMLRPC_ASSERT_ENV_OK(envP); XMLRPC_ASSERT_PTR_OK(utf8_data); - XMLRPC_ASSERT((!ioBuff && !outBuffLenP) || - (ioBuff && outBuffLenP)); + XMLRPC_ASSERT((!ioBuff && !outBuffLenP) || (ioBuff && outBuffLenP)); + + for (utf8Cursor = 0, outPos = 0; + utf8Cursor < utf8_len && !envP->fault_occurred; + ) { - /* Suppress GCC warning about possibly undefined variable. */ - wc = 0; + char const init = utf8_data[utf8Cursor]; + /* Initial byte of the UTF-8 sequence */ + + wchar_t wc; - 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++; + ++utf8Cursor; } 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. - */ + size_t const length = utf8SeqLength[(unsigned char) init]; + + if (length == 0) 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"); + "Unrecognized UTF-8 initial byte value 0x%02x", init); + else { + /* Make sure we have enough bytes to convert. */ + if (utf8Cursor + length > utf8_len) { + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_INVALID_UTF8_ERROR, + "Invalid UTF-8 sequence indicates a %u-byte sequence " + "when only %u bytes are left in the string", + (unsigned)length, (unsigned)(utf8_len - utf8Cursor)); + } else { + decodeMultibyte(envP, &utf8_data[utf8Cursor], length, &wc); + + /* Advance to the end of the sequence. */ + utf8Cursor += length; + } } - - /* 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; + + if (!envP->fault_occurred) { + /* If we have a buffer, write our character to it. */ + if (ioBuff) + ioBuff[outPos++] = 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); + if (outBuffLenP) + *outBuffLenP = envP->fault_occurred ? 0 : outPos; } @@ -286,9 +332,9 @@ xmlrpc_utf8_to_wcs(xmlrpc_env * const envP, 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); + decodeUtf8(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); @@ -329,7 +375,8 @@ xmlrpc_wcs_to_utf8(xmlrpc_env * const envP, utf8P = XMLRPC_MEMBLOCK_NEW(char, envP, estimate); if (!envP->fault_occurred) { - unsigned char * const buffer = XMLRPC_MEMBLOCK_CONTENTS(char, utf8P); + unsigned char * const buffer = + XMLRPC_MEMBLOCK_CONTENTS(unsigned char, utf8P); size_t bytesUsed; size_t i; @@ -401,13 +448,12 @@ xmlrpc_force_to_utf8(char * const buffer) { char * p; for (p = &buffer[0]; *p;) { - uint const length = utf8_seq_length[(unsigned char) *p]; + unsigned int const length = utf8SeqLength[(unsigned char) *p]; bool forceDel; uint32_t decoded; - forceDel = false; - decoded = 0; /* suppress compiler warning; valid when !forceDel */ + forceDel = false; /* initial value */ switch (length) { case 1: @@ -482,7 +528,7 @@ xmlrpc_force_to_xml_chars(char * const buffer) { char * p; for (p = &buffer[0]; *p;) { - uint const length = utf8_seq_length[(unsigned char) *p]; + unsigned int const length = utf8SeqLength[(unsigned char) *p]; if (length == 1) { if (*p < 0x20 && *p != '\r' && *p != '\n' && *p != '\t') @@ -505,7 +551,31 @@ xmlrpc_force_to_xml_chars(char * const buffer) { +void +xmlrpc_validate_utf8(xmlrpc_env * const envP, + const char * const utf8_data, + size_t const utf8_len) { +/*---------------------------------------------------------------------------- + Validate that a string is valid UTF-8. +-----------------------------------------------------------------------------*/ + xmlrpc_env env; + xmlrpc_env_init(&env); - - +#if HAVE_UNICODE_WCHAR + decodeUtf8(&env, utf8_data, utf8_len, NULL, NULL); +#else + /* We don't have a convenient way to validate, so we just fake it and + call it valid. + */ +#endif + + if (env.fault_occurred) { + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_INVALID_UTF8_ERROR, + "%" XMLRPC_PRId64 "-byte " + "supposed UTF-8 string is not valid UTF-8. %s", + (XMLRPC_INT64)utf8_len, env.fault_string); + } + xmlrpc_env_clean(&env); +} diff --git a/libs/xmlrpc-c/lib/libwww_transport/Makefile b/libs/xmlrpc-c/lib/libwww_transport/Makefile index 1bb362c..c8c51fa 100644 --- a/libs/xmlrpc-c/lib/libwww_transport/Makefile +++ b/libs/xmlrpc-c/lib/libwww_transport/Makefile @@ -22,15 +22,18 @@ OMIT_LIBWWW_TRANSPORT_RULE=Y include $(SRCDIR)/common.mk -LIBWWW_INCLUDES := $(shell libwww-config --cflags) +# This 'common.mk' dependency makes sure the symlinks get built before +# this make file is used for anything. + +$(SRCDIR)/common.mk: srcdir blddir -CFLAGS = $(CFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD) +LIBWWW_INCLUDES := $(shell libwww-config --cflags) INCLUDES = \ -I$(BLDDIR) \ -I$(BLDDIR)/include \ - -I$(SRCDIR)/include \ - -I$(SRCDIR)/lib/util/include \ + -Isrcdir/include \ + -Isrcdir/lib/util/include \ $(LIBWWW_INCLUDES) .PHONY: clean @@ -51,8 +54,8 @@ install: .PHONY: dep dep: dep-common -include Makefile.depend +include depend.mk -# Need this dependency for those who don't use Makefile.depend. +# Need this dependency for those who don't use depend.mk. # Without it, version.h doesn't get created. xmlrpc_libwww_transport.o xmlrpc_libwww_transport.osh: version.h diff --git a/libs/xmlrpc-c/lib/libwww_transport/Makefile.depend b/libs/xmlrpc-c/lib/libwww_transport/Makefile.depend deleted file mode 100644 index e69de29..0000000 diff --git a/libs/xmlrpc-c/lib/libwww_transport/xmlrpc_libwww_transport.c b/libs/xmlrpc-c/lib/libwww_transport/xmlrpc_libwww_transport.c index 10866c1..1a0fcc7 100644 --- a/libs/xmlrpc-c/lib/libwww_transport/xmlrpc_libwww_transport.c +++ b/libs/xmlrpc-c/lib/libwww_transport/xmlrpc_libwww_transport.c @@ -884,6 +884,7 @@ sendRequest(xmlrpc_env * const envP, const xmlrpc_server_info * const serverP, xmlrpc_mem_block * const xmlP, xmlrpc_transport_asynch_complete complete, + xmlrpc_transport_progress progress ATTR_UNUSED, struct xmlrpc_call_info * const callInfoP) { /*---------------------------------------------------------------------------- Initiate an XML-RPC rpc asynchronously. Don't wait for it to go to diff --git a/libs/xmlrpc-c/lib/libwww_transport/xmlrpc_libwww_transport.h b/libs/xmlrpc-c/lib/libwww_transport/xmlrpc_libwww_transport.h deleted file mode 100644 index 66d8048..0000000 --- a/libs/xmlrpc-c/lib/libwww_transport/xmlrpc_libwww_transport.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef XMLRPC_LIBWWW_TRANSPORT_H -#define XMLRPC_LIBWWW_TRANSPORT_H - -#include "xmlrpc-c/transport.h" - -extern struct xmlrpc_client_transport_ops xmlrpc_libwww_transport_ops; - -#endif diff --git a/libs/xmlrpc-c/lib/util/Makefile b/libs/xmlrpc-c/lib/util/Makefile index a061b2e..d79b905 100644 --- a/libs/xmlrpc-c/lib/util/Makefile +++ b/libs/xmlrpc-c/lib/util/Makefile @@ -33,6 +33,11 @@ OMIT_UTILS_RULE = Y 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 + LIBOBJS = \ casprintf.o \ cmdline_parser.o \ @@ -44,17 +49,15 @@ LIBOBJS = \ .PHONY: all all: $(LIBOBJS) -INCLUDES = -I$(SRCDIR)/$(SUBDIR)/include -I$(BLDDIR) - -CFLAGS = $(CFLAGS_COMMON) $(INCLUDES) $(CFLAGS_PERSONAL) $(CADD) +INCLUDES = -Isrcdir/$(SUBDIR)/include -I$(BLDDIR) %.o:%.c - $(CC) -c $(CFLAGS) $< + $(CC) -c $(CFLAGS_ALL) $< %.o:%.cpp - $(CXX) -c $(CFLAGS) $< + $(CXX) -c $(CXXFLAGS_ALL) $< -include Makefile.depend +include depend.mk .PHONY: clean distclean clean: clean-common diff --git a/libs/xmlrpc-c/lib/util/Makefile.depend b/libs/xmlrpc-c/lib/util/Makefile.depend deleted file mode 100644 index e69de29..0000000 diff --git a/libs/xmlrpc-c/lib/util/casprintf.c b/libs/xmlrpc-c/lib/util/casprintf.c index 959e4ce..0a26f4d 100644 --- a/libs/xmlrpc-c/lib/util/casprintf.c +++ b/libs/xmlrpc-c/lib/util/casprintf.c @@ -1,43 +1,87 @@ -//#define _GNU_SOURCE +#ifndef _GNU_SOURCE + #define _GNU_SOURCE /* But only when HAVE_ASPRINTF */ +#endif + #include #include #include +#include #include "xmlrpc_config.h" /* For HAVE_ASPRINTF, __inline__ */ +#include "bool.h" #include "casprintf.h" static __inline__ void +newVsnprintf(char * const buffer, + size_t const bufferSize, + const char * const fmt, + va_list varargs, + size_t * const formattedSizeP) { +/*---------------------------------------------------------------------------- + This is vsnprintf() with the new behavior, where not fitting in the buffer + is not a failure. + + Unfortunately, we can't practically return the size of the formatted string + if the C library has old vsnprintf() and the formatted string doesn't fit + in the buffer, so in that case we just return something larger than the + buffer. +-----------------------------------------------------------------------------*/ + if (bufferSize > INT_MAX/2) { + /* There's a danger we won't be able to coerce the return value + of XMLRPC_VSNPRINTF to an integer (which we have to do because, + while for POSIX its return value is ssize_t, on Windows it is int), + or return double the buffer size. + */ + *formattedSizeP = 0; + } else { + int rc; + + rc = XMLRPC_VSNPRINTF(buffer, bufferSize, fmt, varargs); + + if (rc < 0) { + /* We have old vsnprintf() (or Windows) and the formatted value + doesn't fit in the buffer, but we don't know how big a buffer it + needs. + */ + *formattedSizeP = bufferSize * 2; + } else { + /* Either the string fits in the buffer or we have new vsnprintf() + which tells us how big the string is regardless. + */ + *formattedSizeP = rc; + } + } +} + + + +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. - */ + size_t bufferSize; + bool outOfMemory; + + for (result = NULL, bufferSize = 4096, outOfMemory = false; + !result && !outOfMemory; + ) { + + result = malloc(bufferSize); + if (!result) + outOfMemory = true; + else { + size_t bytesNeeded; + newVsnprintf(result, bufferSize, fmt, varargs, &bytesNeeded); + if (bytesNeeded > bufferSize) { free(result); result = NULL; + bufferSize = bytesNeeded; } } } diff --git a/libs/xmlrpc-c/lib/util/cmdline_parser.c b/libs/xmlrpc-c/lib/util/cmdline_parser.c index 37caadb..cc33d8d 100644 --- a/libs/xmlrpc-c/lib/util/cmdline_parser.c +++ b/libs/xmlrpc-c/lib/util/cmdline_parser.c @@ -1,3 +1,5 @@ +#define _XOPEN_SOURCE 600 /* Make sure has strdup() */ + #include "xmlrpc_config.h" /* prereq for mallocvar.h -- defines __inline__ */ #include diff --git a/libs/xmlrpc-c/lib/util/include/int.h b/libs/xmlrpc-c/lib/util/include/int.h index 253ea34..3c7b216 100644 --- a/libs/xmlrpc-c/lib/util/include/int.h +++ b/libs/xmlrpc-c/lib/util/include/int.h @@ -11,6 +11,14 @@ long long mask= ULL(1) << 33; */ +/* 'uint' is quite convenient, but there's no simple way have it everywhere. + Some systems have it in the base system (e.g. GNU C library has it in + , and others (e.g. Solaris - 08.12.02) don't. Since we + can't define it unless we know it's not defined already, and we don't + want to burden the reader with a special Xmlrpc-c name such as xuint, + we just use standard "unsigned int" instead. +*/ + #ifdef _MSC_VER # define PRId64 "I64d" # define PRIu64 "I64u" @@ -33,9 +41,6 @@ typedef __int64 int64_t; #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 @@ -44,6 +49,11 @@ typedef unsigned char uint8_t; #define LL(x) x ## i64 #define ULL(x) x ## u64 +#elif defined(__INTERIX) +# include +# define PRId64 "I64d" +# define PRIu64 "I64u" + #else /* Not Microsoft compiler */ #include diff --git a/libs/xmlrpc-c/lib/util/include/mallocvar.h b/libs/xmlrpc-c/lib/util/include/mallocvar.h index 5dd9fc9..12ca9d9 100644 --- a/libs/xmlrpc-c/lib/util/include/mallocvar.h +++ b/libs/xmlrpc-c/lib/util/include/mallocvar.h @@ -18,7 +18,7 @@ static __inline__ void mallocProduct(void ** const resultP, unsigned int const factor1, - unsigned int const factor2) { + size_t const factor2) { /*---------------------------------------------------------------------------- malloc a space whose size in bytes is the product of 'factor1' and 'factor2'. But if that size cannot be represented as an unsigned int, @@ -102,7 +102,7 @@ do { \ #define MALLOCVAR(varName) \ - if (varName = malloc(sizeof(*varName))) memset(varName, 0, sizeof(*varName)) + varName = malloc(sizeof(*varName)) #define MALLOCVAR_NOFAIL(varName) \ do {if ((varName = malloc(sizeof(*varName))) == NULL) abort();} while(0) diff --git a/libs/xmlrpc-c/lib/util/include/pthreadx.h b/libs/xmlrpc-c/lib/util/include/pthreadx.h index 3ec8f2a..bf5a45f 100644 --- a/libs/xmlrpc-c/lib/util/include/pthreadx.h +++ b/libs/xmlrpc-c/lib/util/include/pthreadx.h @@ -26,10 +26,12 @@ #ifndef PTHREADX_H_INCLUDED #define PTHREADX_H_INCLUDED -#ifndef WIN32 +#include "xmlrpc_config.h" + +#if HAVE_PTHREAD # define _REENTRANT # include -#elif defined (WIN32) +#elif HAVE_WINDOWS_THREAD #include #ifdef __cplusplus @@ -52,11 +54,7 @@ struct { int attrs; /* currently unused. placeholder. */ } pthread_mutexattr_t; -/* 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 *); +typedef void * pthread_func(void *); extern int pthread_create(pthread_t * const new_thread_ID, const pthread_attr_t * const attr, @@ -75,6 +73,10 @@ extern int pthread_mutex_destroy(pthread_mutex_t * const mp); #ifdef __cplusplus } #endif -#endif /* WIN32 */ +#else /* HAVE_WINDOWS_THREAD */ + #error "You don't have any thread facility. (According to " + #error "HAVE_PTHREAD and HAVE_WINDOWS_THREAD macros defined in " + #error "xmlrpc_config.h)" +#endif #endif diff --git a/libs/xmlrpc-c/lib/util/include/sstring.h b/libs/xmlrpc-c/lib/util/include/sstring.h deleted file mode 100644 index c493cf2..0000000 --- a/libs/xmlrpc-c/lib/util/include/sstring.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef SSTRING_H_INCLUDED -#define SSTRING_H_INCLUDED - -/* This file contains string functions that are cognizant of the - declared size of the destination data structure. -*/ - - -/* Copy string pointed by B to array A with size checking. */ -#define SSTRCPY(A,B) \ - (strncpy((A), (B), sizeof(A)), *((A)+sizeof(A)-1) = '\0') -#define SSTRCMP(A,B) \ - (strncmp((A), (B), sizeof(A))) - -#endif diff --git a/libs/xmlrpc-c/lib/util/include/stdargx.h b/libs/xmlrpc-c/lib/util/include/stdargx.h index ee54464..0441f54 100644 --- a/libs/xmlrpc-c/lib/util/include/stdargx.h +++ b/libs/xmlrpc-c/lib/util/include/stdargx.h @@ -56,7 +56,7 @@ init_va_listx(va_listx * const argsxP, #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. + itself. (That's what happens when you pass an array in C). */ memcpy(&argsxP->v, args, sizeof(argsxP->v)); #else diff --git a/libs/xmlrpc-c/lib/util/pthreadx_win32.c b/libs/xmlrpc-c/lib/util/pthreadx_win32.c index 6a8446a..91e3f37 100644 --- a/libs/xmlrpc-c/lib/util/pthreadx_win32.c +++ b/libs/xmlrpc-c/lib/util/pthreadx_win32.c @@ -25,31 +25,65 @@ #include "xmlrpc_config.h" -#ifdef WIN32 +#include -#include "pthreadx.h" +#include "mallocvar.h" -#include +#include "pthreadx.h" #undef PACKAGE #undef VERSION +struct winStartArg { + pthread_func * func; + void * arg; +}; + + + +static unsigned int __stdcall +winThreadStart(void * const arg) { +/*---------------------------------------------------------------------------- + This is a thread start/root function for the Windows threading facility + (i.e. this can be an argument to _beginthreadex()). + + All we do is call the real start/root function, which expects to be + called in the pthread format. +-----------------------------------------------------------------------------*/ + struct winStartArg * const winStartArgP = arg; + + winStartArgP->func(winStartArgP->arg); + + free(winStartArgP); + + return 0; +} + + + int -pthread_create(pthread_t * const new_thread_ID, +pthread_create(pthread_t * const newThreadIdP, const pthread_attr_t * const attr, pthread_func * func, void * const arg) { HANDLE hThread; DWORD dwThreadID; + struct winStartArg * winStartArgP; + + MALLOCVAR_NOFAIL(winStartArgP); - hThread = (HANDLE) _beginthreadex ( - NULL, 0, func, (LPVOID)arg, CREATE_SUSPENDED, &dwThreadID); + winStartArgP->func = func; + winStartArgP->arg = arg; - SetThreadPriority (hThread, THREAD_PRIORITY_NORMAL); - ResumeThread (hThread); + hThread = (HANDLE) _beginthreadex( + NULL, 0, &winThreadStart, (LPVOID)winStartArgP, CREATE_SUSPENDED, + &dwThreadID); - *new_thread_ID = hThread; + SetThreadPriority(hThread, THREAD_PRIORITY_NORMAL); + ResumeThread(hThread); + + *newThreadIdP = hThread; return hThread ? 0 : -1; } @@ -119,5 +153,3 @@ pthread_mutex_destroy(pthread_mutex_t * const mp) { DeleteCriticalSection(mp); return 0; } - -#endif diff --git a/libs/xmlrpc-c/lib/util/string_parser.c b/libs/xmlrpc-c/lib/util/string_parser.c index 32879f5..3c1fdf5 100644 --- a/libs/xmlrpc-c/lib/util/string_parser.c +++ b/libs/xmlrpc-c/lib/util/string_parser.c @@ -50,7 +50,7 @@ interpretUll(const char * const string, errno = 0; /* So we can tell if strtoull() overflowed */ - *ullP = strtoull(strippedString, &tail, 10); + *ullP = XMLRPC_STRTOULL(strippedString, &tail, 10); if (tail[0] != '\0') casprintf(errorP, "Non-digit stuff in string: %s", tail); @@ -80,7 +80,7 @@ interpretLl(const char * const string, errno = 0; /* So we can tell if strtoll() overflowed */ - *llP = strtoll(string, &tail, 10); + *llP = XMLRPC_STRTOLL(string, &tail, 10); if (tail[0] != '\0') casprintf(errorP, "Non-digit stuff in string: %s", tail); @@ -94,9 +94,9 @@ interpretLl(const char * const string, void -interpretUint(const char * const string, - uint * const uintP, - const char ** const errorP) { +interpretUint(const char * const string, + unsigned int * 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 diff --git a/libs/xmlrpc-c/lib/util/stripcaseeq.c b/libs/xmlrpc-c/lib/util/stripcaseeq.c index 348a868..861da10 100644 --- a/libs/xmlrpc-c/lib/util/stripcaseeq.c +++ b/libs/xmlrpc-c/lib/util/stripcaseeq.c @@ -1,4 +1,3 @@ -//#define _GNU_SOURCE #include #include "bool.h" diff --git a/libs/xmlrpc-c/lib/wininet_transport/Makefile b/libs/xmlrpc-c/lib/wininet_transport/Makefile index 648c6c3..1b24efc 100644 --- a/libs/xmlrpc-c/lib/wininet_transport/Makefile +++ b/libs/xmlrpc-c/lib/wininet_transport/Makefile @@ -22,13 +22,16 @@ OMIT_WININET_TRANSPORT_RULE=Y include $(SRCDIR)/common.mk -CFLAGS = $(CFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD) +# This 'common.mk' dependency makes sure the symlinks get built before +# this make file is used for anything. + +$(SRCDIR)/common.mk: srcdir blddir INCLUDES = \ -I$(BLDDIR) \ -I$(BLDDIR)/include \ - -I$(SRCDIR)/include \ - -I$(SRCDIR)/lib/util/include \ + -Isrcdir/include \ + -Isrcdir/lib/util/include \ .PHONY: clean clean: clean-common @@ -48,8 +51,8 @@ install: .PHONY: dep dep: dep-common -include Makefile.depend +include depend.mk -# Need this dependency for those who don't use Makefile.depend. +# Need this dependency for those who don't use depend.mk. # Without it, version.h doesn't get created. xmlrpc_wininet_transport.o xmlrpc_wininet_transport.osh: version.h diff --git a/libs/xmlrpc-c/lib/wininet_transport/xmlrpc_wininet_transport.c b/libs/xmlrpc-c/lib/wininet_transport/xmlrpc_wininet_transport.c index d81c6ea..b5efb93 100644 --- a/libs/xmlrpc-c/lib/wininet_transport/xmlrpc_wininet_transport.c +++ b/libs/xmlrpc-c/lib/wininet_transport/xmlrpc_wininet_transport.c @@ -398,6 +398,15 @@ performWinInetTransaction( XMLRPC_FAIL(envP, XMLRPC_INTERNAL_ERROR, "Could not set Content-Type."); + { + /* By default, a request times out after 30 seconds. We don't want + it to timeout at all, since we don't know what the user is doing. + */ + DWORD dwTimeOut = 0x7FFFFFFF; /* Approximation of infinity */ + InternetSetOption(winInetTransactionP->hHttpRequest, + INTERNET_OPTION_RECEIVE_TIMEOUT, + &dwTimeOut, sizeof(dwTimeOut)); + } Again: /* Send the requested XML remote procedure command */ succeeded = HttpSendRequest(winInetTransactionP->hHttpRequest, NULL, 0, @@ -558,17 +567,22 @@ Again: -static unsigned __stdcall +static void * doAsyncRpc(void * const arg) { + rpc * const rpcP = arg; + xmlrpc_env env; xmlrpc_env_init(&env); + performWinInetTransaction(&env, rpcP->winInetTransactionP, rpcP->clientTransportP ); + rpcP->complete(rpcP->callInfoP, rpcP->responseXmlP, env); + xmlrpc_env_clean(&env); - return 0; + return NULL; } @@ -837,6 +851,7 @@ sendRequest(xmlrpc_env * const envP, const xmlrpc_server_info * const serverP, xmlrpc_mem_block * const callXmlP, xmlrpc_transport_asynch_complete complete, + xmlrpc_transport_progress progress, struct xmlrpc_call_info * const callInfoP) { /*---------------------------------------------------------------------------- Initiate an XML-RPC rpc asynchronously. Don't wait for it to go to diff --git a/libs/xmlrpc-c/lib/wininet_transport/xmlrpc_wininet_transport.h b/libs/xmlrpc-c/lib/wininet_transport/xmlrpc_wininet_transport.h deleted file mode 100644 index d9f2b39..0000000 --- a/libs/xmlrpc-c/lib/wininet_transport/xmlrpc_wininet_transport.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef XMLRPC_WININET_TRANSPORT_H -#define XMLRPC_WININET_TRANSPORT_H - -#include "xmlrpc-c/transport.h" - -extern struct xmlrpc_client_transport_ops xmlrpc_wininet_transport_ops; - -#endif diff --git a/libs/xmlrpc-c/ltconfig b/libs/xmlrpc-c/ltconfig deleted file mode 100755 index a01334f..0000000 --- a/libs/xmlrpc-c/ltconfig +++ /dev/null @@ -1,3078 +0,0 @@ -#! /bin/sh - -# ltconfig - Create a system-specific libtool. -# Copyright (C) 1996-1999 Free Software Foundation, Inc. -# Originally by Gordon Matzigkeit , 1996 -# -# This file is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# A lot of this script is taken from autoconf-2.10. - -# Check that we are running under the correct shell. -SHELL=${CONFIG_SHELL-/bin/sh} -echo=echo -if test "X$1" = X--no-reexec; then - # Discard the --no-reexec flag, and continue. - shift -elif test "X$1" = X--fallback-echo; then - # Avoid inline document here, it may be left over - : -elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then - # Yippee, $echo works! - : -else - # Restart under the correct shell. - exec "$SHELL" "$0" --no-reexec ${1+"$@"} -fi - -if test "X$1" = X--fallback-echo; then - # used as fallback echo - shift - cat </dev/null`} - case X$UNAME in - *-DOS) PATH_SEPARATOR=';' ;; - *) PATH_SEPARATOR=':' ;; - esac -fi - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -if test "X${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi - -if test "X${echo_test_string+set}" != Xset; then - # find a string as large as possible, as long as the shell can cope with it - for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do - # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... - if (echo_test_string="`eval $cmd`") 2>/dev/null && - echo_test_string="`eval $cmd`" && - (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null; then - break - fi - done -fi - -if test "X`($echo '\t') 2>/dev/null`" != 'X\t' || - test "X`($echo "$echo_test_string") 2>/dev/null`" != X"$echo_test_string"; then - # The Solaris, AIX, and Digital Unix default echo programs unquote - # backslashes. This makes it impossible to quote backslashes using - # echo "$something" | sed 's/\\/\\\\/g' - # - # So, first we look for a working echo in the user's PATH. - - IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" - for dir in $PATH /usr/ucb; do - if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && - test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && - test "X`($dir/echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then - echo="$dir/echo" - break - fi - done - IFS="$save_ifs" - - if test "X$echo" = Xecho; then - # We didn't find a better echo, so look for alternatives. - if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && - test "X`(print -r "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then - # This shell has a builtin print -r that does the trick. - echo='print -r' - elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && - test "X$CONFIG_SHELL" != X/bin/ksh; then - # If we have ksh, try running ltconfig again with it. - ORIGINAL_CONFIG_SHELL="${CONFIG_SHELL-/bin/sh}" - export ORIGINAL_CONFIG_SHELL - CONFIG_SHELL=/bin/ksh - export CONFIG_SHELL - exec "$CONFIG_SHELL" "$0" --no-reexec ${1+"$@"} - else - # Try using printf. - echo='printf "%s\n"' - if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && - test "X`($echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then - # Cool, printf works - : - elif test "X`("$ORIGINAL_CONFIG_SHELL" "$0" --fallback-echo '\t') 2>/dev/null`" = 'X\t' && - test "X`("$ORIGINAL_CONFIG_SHELL" "$0" --fallback-echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then - CONFIG_SHELL="$ORIGINAL_CONFIG_SHELL" - export CONFIG_SHELL - SHELL="$CONFIG_SHELL" - export SHELL - echo="$CONFIG_SHELL $0 --fallback-echo" - elif test "X`("$CONFIG_SHELL" "$0" --fallback-echo '\t') 2>/dev/null`" = 'X\t' && - test "X`("$CONFIG_SHELL" "$0" --fallback-echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then - echo="$CONFIG_SHELL $0 --fallback-echo" - else - # maybe with a smaller string... - prev=: - - for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do - if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null; then - break - fi - prev="$cmd" - done - - if test "$prev" != 'sed 50q "$0"'; then - echo_test_string=`eval $prev` - export echo_test_string - exec "${ORIGINAL_CONFIG_SHELL}" "$0" ${1+"$@"} - else - # Oops. We lost completely, so just stick with echo. - echo=echo - fi - fi - fi - fi -fi - -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -Xsed='sed -e s/^X//' -sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g' - -# Same as above, but do not quote variable references. -double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g' - -# Sed substitution to delay expansion of an escaped shell variable in a -# double_quote_subst'ed string. -delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' - -# The name of this program. -progname=`$echo "X$0" | $Xsed -e 's%^.*/%%'` - -# Constants: -PROGRAM=ltconfig -PACKAGE=libtool -VERSION=1.3.4 -TIMESTAMP=" (1.385.2.196 1999/12/07 21:47:57)" -ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' -ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' -rm="rm -f" - -help="Try \`$progname --help' for more information." - -# Global variables: -default_ofile=libtool -can_build_shared=yes -enable_shared=yes -# All known linkers require a `.a' archive for static linking (except M$VC, -# which needs '.lib'). -enable_static=yes -enable_fast_install=yes -enable_dlopen=unknown -enable_win32_dll=no -ltmain= -silent= -srcdir= -ac_config_guess= -ac_config_sub= -host= -nonopt= -ofile="$default_ofile" -verify_host=yes -with_gcc=no -with_gnu_ld=no -need_locks=yes -ac_ext=c -objext=o -libext=a -exeext= -cache_file= - -old_AR="$AR" -old_CC="$CC" -old_CFLAGS="$CFLAGS" -old_CPPFLAGS="$CPPFLAGS" -old_LDFLAGS="$LDFLAGS" -old_LD="$LD" -old_LN_S="$LN_S" -old_LIBS="$LIBS" -old_NM="$NM" -old_RANLIB="$RANLIB" -old_DLLTOOL="$DLLTOOL" -old_OBJDUMP="$OBJDUMP" -old_AS="$AS" - -# Parse the command line options. -args= -prev= -for option -do - case "$option" in - -*=*) optarg=`echo "$option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; - *) optarg= ;; - esac - - # If the previous option needs an argument, assign it. - if test -n "$prev"; then - eval "$prev=\$option" - prev= - continue - fi - - case "$option" in - --help) cat <&2 - echo "$help" 1>&2 - exit 1 - ;; - - *) - if test -z "$ltmain"; then - ltmain="$option" - elif test -z "$host"; then -# This generates an unnecessary warning for sparc-sun-solaris4.1.3_U1 -# if test -n "`echo $option| sed 's/[-a-z0-9.]//g'`"; then -# echo "$progname: warning \`$option' is not a valid host type" 1>&2 -# fi - host="$option" - else - echo "$progname: too many arguments" 1>&2 - echo "$help" 1>&2 - exit 1 - fi ;; - esac -done - -if test -z "$ltmain"; then - echo "$progname: you must specify a LTMAIN file" 1>&2 - echo "$help" 1>&2 - exit 1 -fi - -if test ! -f "$ltmain"; then - echo "$progname: \`$ltmain' does not exist" 1>&2 - echo "$help" 1>&2 - exit 1 -fi - -# Quote any args containing shell metacharacters. -ltconfig_args= -for arg -do - case "$arg" in - *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) - ltconfig_args="$ltconfig_args '$arg'" ;; - *) ltconfig_args="$ltconfig_args $arg" ;; - esac -done - -# A relevant subset of AC_INIT. - -# File descriptor usage: -# 0 standard input -# 1 file creation -# 2 errors and warnings -# 3 some systems may open it to /dev/tty -# 4 used on the Kubota Titan -# 5 compiler messages saved in config.log -# 6 checking for... messages and results -if test "$silent" = yes; then - exec 6>/dev/null -else - exec 6>&1 -fi -exec 5>>./config.log - -# NLS nuisances. -# Only set LANG and LC_ALL to C if already set. -# These must not be set unconditionally because not all systems understand -# e.g. LANG=C (notably SCO). -if test "X${LC_ALL+set}" = Xset; then LC_ALL=C; export LC_ALL; fi -if test "X${LANG+set}" = Xset; then LANG=C; export LANG; fi - -if test -n "$cache_file" && test -r "$cache_file"; then - echo "loading cache $cache_file within ltconfig" - . $cache_file -fi - -if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then - # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. - if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then - ac_n= ac_c=' -' ac_t=' ' - else - ac_n=-n ac_c= ac_t= - fi -else - ac_n= ac_c='\c' ac_t= -fi - -if test -z "$srcdir"; then - # Assume the source directory is the same one as the path to LTMAIN. - srcdir=`$echo "X$ltmain" | $Xsed -e 's%/[^/]*$%%'` - test "$srcdir" = "$ltmain" && srcdir=. -fi - -trap "$rm conftest*; exit 1" 1 2 15 -if test "$verify_host" = yes; then - # Check for config.guess and config.sub. - ac_aux_dir= - for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do - if test -f $ac_dir/config.guess; then - ac_aux_dir=$ac_dir - break - fi - done - if test -z "$ac_aux_dir"; then - echo "$progname: cannot find config.guess in $srcdir $srcdir/.. $srcdir/../.." 1>&2 - echo "$help" 1>&2 - exit 1 - fi - ac_config_guess=$ac_aux_dir/config.guess - ac_config_sub=$ac_aux_dir/config.sub - - # Make sure we can run config.sub. - if $SHELL $ac_config_sub sun4 >/dev/null 2>&1; then : - else - echo "$progname: cannot run $ac_config_sub" 1>&2 - echo "$help" 1>&2 - exit 1 - fi - - echo $ac_n "checking host system type""... $ac_c" 1>&6 - - host_alias=$host - case "$host_alias" in - "") - if host_alias=`$SHELL $ac_config_guess`; then : - else - echo "$progname: cannot guess host type; you must specify one" 1>&2 - echo "$help" 1>&2 - exit 1 - fi ;; - esac - host=`$SHELL $ac_config_sub $host_alias` - echo "$ac_t$host" 1>&6 - - # Make sure the host verified. - test -z "$host" && exit 1 - -elif test -z "$host"; then - echo "$progname: you must specify a host type if you use \`--no-verify'" 1>&2 - echo "$help" 1>&2 - exit 1 -else - host_alias=$host -fi - -# Transform linux* to *-*-linux-gnu*, to support old configure scripts. -case "$host_os" in -linux-gnu*) ;; -linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'` -esac - -host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` -host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` -host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` - -case "$host_os" in -aix3*) - # AIX sometimes has problems with the GCC collect2 program. For some - # reason, if we set the COLLECT_NAMES environment variable, the problems - # vanish in a puff of smoke. - if test "X${COLLECT_NAMES+set}" != Xset; then - COLLECT_NAMES= - export COLLECT_NAMES - fi - ;; -esac - -# Determine commands to create old-style static archives. -old_archive_cmds='$AR cru $oldlib$oldobjs' -old_postinstall_cmds='chmod 644 $oldlib' -old_postuninstall_cmds= - -# Set a sane default for `AR'. -test -z "$AR" && AR=ar - -# Set a sane default for `OBJDUMP'. -test -z "$OBJDUMP" && OBJDUMP=objdump - -# If RANLIB is not set, then run the test. -if test "${RANLIB+set}" != "set"; then - result=no - - echo $ac_n "checking for ranlib... $ac_c" 1>&6 - IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" - for dir in $PATH; do - test -z "$dir" && dir=. - if test -f $dir/ranlib || test -f $dir/ranlib$ac_exeext; then - RANLIB="ranlib" - result="ranlib" - break - fi - done - IFS="$save_ifs" - - echo "$ac_t$result" 1>&6 -fi - -if test -n "$RANLIB"; then - old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" - old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds" -fi - -# Set sane defaults for `DLLTOOL', `OBJDUMP', and `AS', used on cygwin. -test -z "$DLLTOOL" && DLLTOOL=dlltool -test -z "$OBJDUMP" && OBJDUMP=objdump -test -z "$AS" && AS=as - -# Check to see if we are using GCC. -if test "$with_gcc" != yes || test -z "$CC"; then - # If CC is not set, then try to find GCC or a usable CC. - if test -z "$CC"; then - echo $ac_n "checking for gcc... $ac_c" 1>&6 - IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" - for dir in $PATH; do - test -z "$dir" && dir=. - if test -f $dir/gcc || test -f $dir/gcc$ac_exeext; then - CC="gcc" - break - fi - done - IFS="$save_ifs" - - if test -n "$CC"; then - echo "$ac_t$CC" 1>&6 - else - echo "$ac_t"no 1>&6 - fi - fi - - # Not "gcc", so try "cc", rejecting "/usr/ucb/cc". - if test -z "$CC"; then - echo $ac_n "checking for cc... $ac_c" 1>&6 - IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" - cc_rejected=no - for dir in $PATH; do - test -z "$dir" && dir=. - if test -f $dir/cc || test -f $dir/cc$ac_exeext; then - if test "$dir/cc" = "/usr/ucb/cc"; then - cc_rejected=yes - continue - fi - CC="cc" - break - fi - done - IFS="$save_ifs" - if test $cc_rejected = yes; then - # We found a bogon in the path, so make sure we never use it. - set dummy $CC - shift - if test $# -gt 0; then - # We chose a different compiler from the bogus one. - # However, it has the same name, so the bogon will be chosen - # first if we set CC to just the name; use the full file name. - shift - set dummy "$dir/cc" "$@" - shift - CC="$@" - fi - fi - - if test -n "$CC"; then - echo "$ac_t$CC" 1>&6 - else - echo "$ac_t"no 1>&6 - fi - - if test -z "$CC"; then - echo "$progname: error: no acceptable cc found in \$PATH" 1>&2 - exit 1 - fi - fi - - # Now see if the compiler is really GCC. - with_gcc=no - echo $ac_n "checking whether we are using GNU C... $ac_c" 1>&6 - echo "$progname:581: checking whether we are using GNU C" >&5 - - $rm conftest.c - cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then - with_gcc=yes - fi - $rm conftest.c - echo "$ac_t$with_gcc" 1>&6 -fi - -# Allow CC to be a program name with arguments. -set dummy $CC -compiler="$2" - -echo $ac_n "checking for object suffix... $ac_c" 1>&6 -$rm conftest* -echo 'int i = 1;' > conftest.c -echo "$progname:603: checking for object suffix" >& 5 -if { (eval echo $progname:604: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; }; then - # Append any warnings to the config.log. - cat conftest.err 1>&5 - - for ac_file in conftest.*; do - case $ac_file in - *.c) ;; - *) objext=`echo $ac_file | sed -e s/conftest.//` ;; - esac - done -else - cat conftest.err 1>&5 - echo "$progname: failed program was:" >&5 - cat conftest.c >&5 -fi -$rm conftest* -echo "$ac_t$objext" 1>&6 - -echo $ac_n "checking for executable suffix... $ac_c" 1>&6 -if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - ac_cv_exeext="no" - $rm conftest* - echo 'main () { return 0; }' > conftest.c - echo "$progname:629: checking for executable suffix" >& 5 - if { (eval echo $progname:630: \"$ac_link\") 1>&5; (eval $ac_link) 2>conftest.err; }; then - # Append any warnings to the config.log. - cat conftest.err 1>&5 - - for ac_file in conftest.*; do - case $ac_file in - *.c | *.err | *.$objext ) ;; - *) ac_cv_exeext=.`echo $ac_file | sed -e s/conftest.//` ;; - esac - done - else - cat conftest.err 1>&5 - echo "$progname: failed program was:" >&5 - cat conftest.c >&5 - fi - $rm conftest* -fi -if test "X$ac_cv_exeext" = Xno; then - exeext="" -else - exeext="$ac_cv_exeext" -fi -echo "$ac_t$ac_cv_exeext" 1>&6 - -echo $ac_n "checking for $compiler option to produce PIC... $ac_c" 1>&6 -pic_flag= -special_shlib_compile_flags= -wl= -link_static_flag= -no_builtin_flag= - -if test "$with_gcc" = yes; then - wl='-Wl,' - link_static_flag='-static' - - case "$host_os" in - beos* | irix5* | irix6* | osf3* | osf4* | osf5*) - # PIC is the default for these OSes. - ;; - aix*) - # Below there is a dirty hack to force normal static linking with -ldl - # The problem is because libdl dynamically linked with both libc and - # libC (AIX C++ library), which obviously doesn't included in libraries - # list by gcc. This cause undefined symbols with -static flags. - # This hack allows C programs to be linked with "-static -ldl", but - # we not sure about C++ programs. - link_static_flag="$link_static_flag ${wl}-lC" - ;; - cygwin* | mingw* | os2*) - # We can build DLLs from non-PIC. - ;; - amigaos*) - # FIXME: we need at least 68020 code to build shared libraries, but - # adding the `-m68020' flag to GCC prevents building anything better, - # like `-m68040'. - pic_flag='-m68020 -resident32 -malways-restore-a4' - ;; - sysv4*MP*) - if test -d /usr/nec; then - pic_flag=-Kconform_pic - fi - ;; - *) - pic_flag='-fPIC' - ;; - esac -else - # PORTME Check for PIC flags for the system compiler. - case "$host_os" in - aix3* | aix4*) - # All AIX code is PIC. - link_static_flag='-bnso -bI:/lib/syscalls.exp' - ;; - - hpux9* | hpux10* | hpux11*) - # Is there a better link_static_flag that works with the bundled CC? - wl='-Wl,' - link_static_flag="${wl}-a ${wl}archive" - pic_flag='+Z' - ;; - - irix5* | irix6*) - wl='-Wl,' - link_static_flag='-non_shared' - # PIC (with -KPIC) is the default. - ;; - - cygwin* | mingw* | os2*) - # We can build DLLs from non-PIC. - ;; - - osf3* | osf4* | osf5*) - # All OSF/1 code is PIC. - wl='-Wl,' - link_static_flag='-non_shared' - ;; - - sco3.2v5*) - pic_flag='-Kpic' - link_static_flag='-dn' - special_shlib_compile_flags='-belf' - ;; - - solaris*) - pic_flag='-KPIC' - link_static_flag='-Bstatic' - wl='-Wl,' - ;; - - sunos4*) - pic_flag='-PIC' - link_static_flag='-Bstatic' - wl='-Qoption ld ' - ;; - - sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) - pic_flag='-KPIC' - link_static_flag='-Bstatic' - wl='-Wl,' - ;; - - uts4*) - pic_flag='-pic' - link_static_flag='-Bstatic' - ;; - sysv4*MP*) - if test -d /usr/nec ;then - pic_flag='-Kconform_pic' - link_static_flag='-Bstatic' - fi - ;; - *) - can_build_shared=no - ;; - esac -fi - -if test -n "$pic_flag"; then - echo "$ac_t$pic_flag" 1>&6 - - # Check to make sure the pic_flag actually works. - echo $ac_n "checking if $compiler PIC flag $pic_flag works... $ac_c" 1>&6 - $rm conftest* - echo "int some_variable = 0;" > conftest.c - save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $pic_flag -DPIC" - echo "$progname:776: checking if $compiler PIC flag $pic_flag works" >&5 - if { (eval echo $progname:777: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.$objext; then - # Append any warnings to the config.log. - cat conftest.err 1>&5 - - case "$host_os" in - hpux9* | hpux10* | hpux11*) - # On HP-UX, both CC and GCC only warn that PIC is supported... then they - # create non-PIC objects. So, if there were any warnings, we assume that - # PIC is not supported. - if test -s conftest.err; then - echo "$ac_t"no 1>&6 - can_build_shared=no - pic_flag= - else - echo "$ac_t"yes 1>&6 - pic_flag=" $pic_flag" - fi - ;; - *) - echo "$ac_t"yes 1>&6 - pic_flag=" $pic_flag" - ;; - esac - else - # Append any errors to the config.log. - cat conftest.err 1>&5 - can_build_shared=no - pic_flag= - echo "$ac_t"no 1>&6 - fi - CFLAGS="$save_CFLAGS" - $rm conftest* -else - echo "$ac_t"none 1>&6 -fi - -# Check to see if options -o and -c are simultaneously supported by compiler -echo $ac_n "checking if $compiler supports -c -o file.o... $ac_c" 1>&6 -$rm -r conftest 2>/dev/null -mkdir conftest -cd conftest -$rm conftest* -echo "int some_variable = 0;" > conftest.c -mkdir out -# According to Tom Tromey, Ian Lance Taylor reported there are C compilers -# that will create temporary files in the current directory regardless of -# the output directory. Thus, making CWD read-only will cause this test -# to fail, enabling locking or at least warning the user not to do parallel -# builds. -chmod -w . -save_CFLAGS="$CFLAGS" -CFLAGS="$CFLAGS -o out/conftest2.o" -echo "$progname:829: checking if $compiler supports -c -o file.o" >&5 -if { (eval echo $progname:830: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.o; then - - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - if test -s out/conftest.err; then - echo "$ac_t"no 1>&6 - compiler_c_o=no - else - echo "$ac_t"yes 1>&6 - compiler_c_o=yes - fi -else - # Append any errors to the config.log. - cat out/conftest.err 1>&5 - compiler_c_o=no - echo "$ac_t"no 1>&6 -fi -CFLAGS="$save_CFLAGS" -chmod u+w . -$rm conftest* out/* -rmdir out -cd .. -rmdir conftest -$rm -r conftest 2>/dev/null - -if test x"$compiler_c_o" = x"yes"; then - # Check to see if we can write to a .lo - echo $ac_n "checking if $compiler supports -c -o file.lo... $ac_c" 1>&6 - $rm conftest* - echo "int some_variable = 0;" > conftest.c - save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS -c -o conftest.lo" - echo "$progname:862: checking if $compiler supports -c -o file.lo" >&5 -if { (eval echo $progname:863: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.lo; then - - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - if test -s conftest.err; then - echo "$ac_t"no 1>&6 - compiler_o_lo=no - else - echo "$ac_t"yes 1>&6 - compiler_o_lo=yes - fi - else - # Append any errors to the config.log. - cat conftest.err 1>&5 - compiler_o_lo=no - echo "$ac_t"no 1>&6 - fi - CFLAGS="$save_CFLAGS" - $rm conftest* -else - compiler_o_lo=no -fi - -# Check to see if we can do hard links to lock some files if needed -hard_links="nottested" -if test "$compiler_c_o" = no && test "$need_locks" != no; then - # do not overwrite the value of need_locks provided by the user - echo $ac_n "checking if we can lock with hard links... $ac_c" 1>&6 - hard_links=yes - $rm conftest* - ln conftest.a conftest.b 2>/dev/null && hard_links=no - touch conftest.a - ln conftest.a conftest.b 2>&5 || hard_links=no - ln conftest.a conftest.b 2>/dev/null && hard_links=no - echo "$ac_t$hard_links" 1>&6 - $rm conftest* - if test "$hard_links" = no; then - echo "*** WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2 - need_locks=warn - fi -else - need_locks=no -fi - -if test "$with_gcc" = yes; then - # Check to see if options -fno-rtti -fno-exceptions are supported by compiler - echo $ac_n "checking if $compiler supports -fno-rtti -fno-exceptions ... $ac_c" 1>&6 - $rm conftest* - echo "int some_variable = 0;" > conftest.c - save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -c conftest.c" - echo "$progname:914: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 - if { (eval echo $progname:915: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.o; then - - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - if test -s conftest.err; then - echo "$ac_t"no 1>&6 - compiler_rtti_exceptions=no - else - echo "$ac_t"yes 1>&6 - compiler_rtti_exceptions=yes - fi - else - # Append any errors to the config.log. - cat conftest.err 1>&5 - compiler_rtti_exceptions=no - echo "$ac_t"no 1>&6 - fi - CFLAGS="$save_CFLAGS" - $rm conftest* - - if test "$compiler_rtti_exceptions" = "yes"; then - no_builtin_flag=' -fno-builtin -fno-rtti -fno-exceptions' - else - no_builtin_flag=' -fno-builtin' - fi - -fi - -# Check for any special shared library compilation flags. -if test -n "$special_shlib_compile_flags"; then - echo "$progname: warning: \`$CC' requires \`$special_shlib_compile_flags' to build shared libraries" 1>&2 - if echo "$old_CC $old_CFLAGS " | egrep -e "[ ]$special_shlib_compile_flags[ ]" >/dev/null; then : - else - echo "$progname: add \`$special_shlib_compile_flags' to the CC or CFLAGS env variable and reconfigure" 1>&2 - can_build_shared=no - fi -fi - -echo $ac_n "checking if $compiler static flag $link_static_flag works... $ac_c" 1>&6 -$rm conftest* -echo 'main(){return(0);}' > conftest.c -save_LDFLAGS="$LDFLAGS" -LDFLAGS="$LDFLAGS $link_static_flag" -echo "$progname:958: checking if $compiler static flag $link_static_flag works" >&5 -if { (eval echo $progname:959: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then - echo "$ac_t$link_static_flag" 1>&6 -else - echo "$ac_t"none 1>&6 - link_static_flag= -fi -LDFLAGS="$save_LDFLAGS" -$rm conftest* - -if test -z "$LN_S"; then - # Check to see if we can use ln -s, or we need hard links. - echo $ac_n "checking whether ln -s works... $ac_c" 1>&6 - $rm conftest.dat - if ln -s X conftest.dat 2>/dev/null; then - $rm conftest.dat - LN_S="ln -s" - else - LN_S=ln - fi - if test "$LN_S" = "ln -s"; then - echo "$ac_t"yes 1>&6 - else - echo "$ac_t"no 1>&6 - fi -fi - -# Make sure LD is an absolute path. -if test -z "$LD"; then - ac_prog=ld - if test "$with_gcc" = yes; then - # Check if gcc -print-prog-name=ld gives a path. - echo $ac_n "checking for ld used by GCC... $ac_c" 1>&6 - echo "$progname:991: checking for ld used by GCC" >&5 - ac_prog=`($CC -print-prog-name=ld) 2>&5` - case "$ac_prog" in - # Accept absolute paths. - [\\/]* | [A-Za-z]:[\\/]*) - re_direlt='/[^/][^/]*/\.\./' - # Canonicalize the path of ld - ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` - while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do - ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` - done - test -z "$LD" && LD="$ac_prog" - ;; - "") - # If it fails, then pretend we are not using GCC. - ac_prog=ld - ;; - *) - # If it is relative, then search for the first ld in PATH. - with_gnu_ld=unknown - ;; - esac - elif test "$with_gnu_ld" = yes; then - echo $ac_n "checking for GNU ld... $ac_c" 1>&6 - echo "$progname:1015: checking for GNU ld" >&5 - else - echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6 - echo "$progname:1018: checking for non-GNU ld" >&5 - fi - - if test -z "$LD"; then - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" - for ac_dir in $PATH; do - test -z "$ac_dir" && ac_dir=. - if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then - LD="$ac_dir/$ac_prog" - # Check to see if the program is GNU ld. I'd rather use --version, - # but apparently some GNU ld's only accept -v. - # Break only if it was the GNU/non-GNU ld that we prefer. - if "$LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then - test "$with_gnu_ld" != no && break - else - test "$with_gnu_ld" != yes && break - fi - fi - done - IFS="$ac_save_ifs" - fi - - if test -n "$LD"; then - echo "$ac_t$LD" 1>&6 - else - echo "$ac_t"no 1>&6 - fi - - if test -z "$LD"; then - echo "$progname: error: no acceptable ld found in \$PATH" 1>&2 - exit 1 - fi -fi - -# Check to see if it really is or is not GNU ld. -echo $ac_n "checking if the linker ($LD) is GNU ld... $ac_c" 1>&6 -# I'd rather use --version here, but apparently some GNU ld's only accept -v. -if $LD -v 2>&1 &5; then - with_gnu_ld=yes -else - with_gnu_ld=no -fi -echo "$ac_t$with_gnu_ld" 1>&6 - -# See if the linker supports building shared libraries. -echo $ac_n "checking whether the linker ($LD) supports shared libraries... $ac_c" 1>&6 - -allow_undefined_flag= -no_undefined_flag= -need_lib_prefix=unknown -need_version=unknown -# when you set need_version to no, make sure it does not cause -set_version -# flags to be left without arguments -archive_cmds= -archive_expsym_cmds= -old_archive_from_new_cmds= -export_dynamic_flag_spec= -whole_archive_flag_spec= -thread_safe_flag_spec= -hardcode_libdir_flag_spec= -hardcode_libdir_separator= -hardcode_direct=no -hardcode_minus_L=no -hardcode_shlibpath_var=unsupported -runpath_var= -always_export_symbols=no -export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | sed '\''s/.* //'\'' | sort | uniq > $export_symbols' -# include_expsyms should be a list of space-separated symbols to be *always* -# included in the symbol list -include_expsyms= -# exclude_expsyms can be an egrep regular expression of symbols to exclude -# it will be wrapped by ` (' and `)$', so one must not match beginning or -# end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', -# as well as any symbol that contains `d'. -exclude_expsyms="_GLOBAL_OFFSET_TABLE_" -# Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out -# platforms (ab)use it in PIC code, but their linkers get confused if -# the symbol is explicitly referenced. Since portable code cannot -# rely on this symbol name, it's probably fine to never include it in -# preloaded symbol tables. - -case "$host_os" in -cygwin* | mingw*) - # FIXME: the MSVC++ port hasn't been tested in a loooong time - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - if test "$with_gcc" != yes; then - with_gnu_ld=no - fi - ;; - -esac - -ld_shlibs=yes -if test "$with_gnu_ld" = yes; then - # If archive_cmds runs LD, not CC, wlarc should be empty - wlarc='${wl}' - - # See if GNU ld supports shared libraries. - case "$host_os" in - aix3* | aix4*) - # On AIX, the GNU linker is very broken - ld_shlibs=no - cat <&2 - -*** Warning: the GNU linker, at least up to release 2.9.1, is reported -*** to be unable to reliably create shared libraries on AIX. -*** Therefore, libtool is disabling shared libraries support. If you -*** really care for shared libraries, you may want to modify your PATH -*** so that a non-GNU linker is found, and then restart. - -EOF - ;; - - amigaos*) - archive_cmds='$rm $objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $objdir/a2ixlibrary.data~$AR cru $lib $libobjs~$RANLIB $lib~(cd $objdir && a2ixlibrary -32)' - hardcode_libdir_flag_spec='-L$libdir' - hardcode_minus_L=yes - - # Samuel A. Falvo II reports - # that the semantics of dynamic libraries on AmigaOS, at least up - # to version 4, is to share data among multiple programs linked - # with the same dynamic library. Since this doesn't match the - # behavior of shared libraries on other platforms, we can use - # them. - ld_shlibs=no - ;; - - beos*) - if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then - allow_undefined_flag=unsupported - # Joseph Beckenbach says some releases of gcc - # support --undefined. This deserves some investigation. FIXME - archive_cmds='$CC -nostart $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib' - else - ld_shlibs=no - fi - ;; - - cygwin* | mingw*) - # hardcode_libdir_flag_spec is actually meaningless, as there is - # no search path for DLLs. - hardcode_libdir_flag_spec='-L$libdir' - allow_undefined_flag=unsupported - always_export_symbols=yes - - # Extract the symbol export list from an `--export-all' def file, - # then regenerate the def file from the symbol export list, so that - # the compiled dll only exports the symbol export list. - export_symbols_cmds='test -f $objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $0 > $objdir/$soname-ltdll.c~ - test -f $objdir/$soname-ltdll.$objext || (cd $objdir && $CC -c $soname-ltdll.c)~ - $DLLTOOL --export-all --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --output-def $objdir/$soname-def $objdir/$soname-ltdll.$objext $libobjs $convenience~ - sed -e "1,/EXPORTS/d" -e "s/ @ [0-9]* ; *//" < $objdir/$soname-def > $export_symbols' - - archive_expsym_cmds='echo EXPORTS > $objdir/$soname-def~ - _lt_hint=1; - for symbol in `cat $export_symbols`; do - echo " \$symbol @ \$_lt_hint ; " >> $objdir/$soname-def; - _lt_hint=`expr 1 + \$_lt_hint`; - done~ - test -f $objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $0 > $objdir/$soname-ltdll.c~ - test -f $objdir/$soname-ltdll.$objext || (cd $objdir && $CC -c $soname-ltdll.c)~ - $CC -Wl,--base-file,$objdir/$soname-base -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts~ - $DLLTOOL --as=$AS --dllname $soname --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --def $objdir/$soname-def --base-file $objdir/$soname-base --output-exp $objdir/$soname-exp~ - $CC -Wl,--base-file,$objdir/$soname-base $objdir/$soname-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts~ - $DLLTOOL --as=$AS --dllname $soname --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --def $objdir/$soname-def --base-file $objdir/$soname-base --output-exp $objdir/$soname-exp~ - $CC $objdir/$soname-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts' - - old_archive_from_new_cmds='$DLLTOOL --as=$AS --dllname $soname --def $objdir/$soname-def --output-lib $objdir/$libname.a' - ;; - - netbsd*) - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - archive_cmds='$LD -Bshareable $libobjs $deplibs $linkopts -o $lib' - # can we support soname and/or expsyms with a.out? -oliva - fi - ;; - - solaris* | sysv5*) - if $LD -v 2>&1 | egrep 'BFD 2\.8' > /dev/null; then - ld_shlibs=no - cat <&2 - -*** Warning: The releases 2.8.* of the GNU linker cannot reliably -*** create shared libraries on Solaris systems. Therefore, libtool -*** is disabling shared libraries support. We urge you to upgrade GNU -*** binutils to release 2.9.1 or newer. Another option is to modify -*** your PATH or compiler configuration so that the native linker is -*** used, and then restart. - -EOF - elif $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then - archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - ld_shlibs=no - fi - ;; - - sunos4*) - archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linkopts' - wlarc= - hardcode_direct=yes - hardcode_shlibpath_var=no - ;; - - *) - if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then - archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - ld_shlibs=no - fi - ;; - esac - - if test "$ld_shlibs" = yes; then - runpath_var=LD_RUN_PATH - hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir' - export_dynamic_flag_spec='${wl}--export-dynamic' - case $host_os in - cygwin* | mingw*) - # dlltool doesn't understand --whole-archive et. al. - whole_archive_flag_spec= - ;; - *) - # ancient GNU ld didn't support --whole-archive et. al. - if $LD --help 2>&1 | egrep 'no-whole-archive' > /dev/null; then - whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - else - whole_archive_flag_spec= - fi - ;; - esac - fi -else - # PORTME fill in a description of your system's linker (not GNU ld) - case "$host_os" in - aix3*) - allow_undefined_flag=unsupported - always_export_symbols=yes - archive_expsym_cmds='$LD -o $objdir/$soname $libobjs $deplibs $linkopts -bE:$export_symbols -T512 -H512 -bM:SRE~$AR cru $lib $objdir/$soname' - # Note: this linker hardcodes the directories in LIBPATH if there - # are no directories specified by -L. - hardcode_minus_L=yes - if test "$with_gcc" = yes && test -z "$link_static_flag"; then - # Neither direct hardcoding nor static linking is supported with a - # broken collect2. - hardcode_direct=unsupported - fi - ;; - - aix4*) - hardcode_libdir_flag_spec='${wl}-b ${wl}nolibpath ${wl}-b ${wl}libpath:$libdir:/usr/lib:/lib' - hardcode_libdir_separator=':' - if test "$with_gcc" = yes; then - collect2name=`${CC} -print-prog-name=collect2` - if test -f "$collect2name" && \ - strings "$collect2name" | grep resolve_lib_name >/dev/null - then - # We have reworked collect2 - hardcode_direct=yes - else - # We have old collect2 - hardcode_direct=unsupported - # It fails to find uninstalled libraries when the uninstalled - # path is not listed in the libpath. Setting hardcode_minus_L - # to unsupported forces relinking - hardcode_minus_L=yes - hardcode_libdir_flag_spec='-L$libdir' - hardcode_libdir_separator= - fi - shared_flag='-shared' - else - shared_flag='${wl}-bM:SRE' - hardcode_direct=yes - fi - allow_undefined_flag=' ${wl}-berok' - archive_cmds="\$CC $shared_flag"' -o $objdir/$soname $libobjs $deplibs $linkopts ${wl}-bexpall ${wl}-bnoentry${allow_undefined_flag}' - archive_expsym_cmds="\$CC $shared_flag"' -o $objdir/$soname $libobjs $deplibs $linkopts ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}' - case "$host_os" in aix4.[01]|aix4.[01].*) - # According to Greg Wooledge, -bexpall is only supported from AIX 4.2 on - always_export_symbols=yes ;; - esac - ;; - - amigaos*) - archive_cmds='$rm $objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $objdir/a2ixlibrary.data~$AR cru $lib $libobjs~$RANLIB $lib~(cd $objdir && a2ixlibrary -32)' - hardcode_libdir_flag_spec='-L$libdir' - hardcode_minus_L=yes - # see comment about different semantics on the GNU ld section - ld_shlibs=no - ;; - - cygwin* | mingw*) - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - # hardcode_libdir_flag_spec is actually meaningless, as there is - # no search path for DLLs. - hardcode_libdir_flag_spec=' ' - allow_undefined_flag=unsupported - # Tell ltmain to make .lib files, not .a files. - libext=lib - # FIXME: Setting linknames here is a bad hack. - archive_cmds='$CC -o $lib $libobjs $linkopts `echo "$deplibs" | sed -e '\''s/ -lc$//'\''` -link -dll~linknames=' - # The linker will automatically build a .lib file if we build a DLL. - old_archive_from_new_cmds='true' - # FIXME: Should let the user specify the lib program. - old_archive_cmds='lib /OUT:$oldlib$oldobjs' - fix_srcfile_path='`cygpath -w $srcfile`' - ;; - - freebsd1*) - ld_shlibs=no - ;; - - # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor - # support. Future versions do this automatically, but an explicit c++rt0.o - # does not break anything, and helps significantly (at the cost of a little - # extra space). - freebsd2.2*) - archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts /usr/lib/c++rt0.o' - hardcode_libdir_flag_spec='-R$libdir' - hardcode_direct=yes - hardcode_shlibpath_var=no - ;; - - # Unfortunately, older versions of FreeBSD 2 do not have this feature. - freebsd2*) - archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts' - hardcode_direct=yes - hardcode_minus_L=yes - hardcode_shlibpath_var=no - ;; - - # FreeBSD 3 and greater uses gcc -shared to do shared libraries. - freebsd*) - archive_cmds='$CC -shared -o $lib $libobjs $deplibs $linkopts' - hardcode_libdir_flag_spec='-R$libdir' - hardcode_direct=yes - hardcode_shlibpath_var=no - ;; - - hpux9* | hpux10* | hpux11*) - case "$host_os" in - hpux9*) archive_cmds='$rm $objdir/$soname~$LD -b +b $install_libdir -o $objdir/$soname $libobjs $deplibs $linkopts~test $objdir/$soname = $lib || mv $objdir/$soname $lib' ;; - *) archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linkopts' ;; - esac - hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' - hardcode_libdir_separator=: - hardcode_direct=yes - hardcode_minus_L=yes # Not in the search PATH, but as the default - # location of the library. - export_dynamic_flag_spec='${wl}-E' - ;; - - irix5* | irix6*) - if test "$with_gcc" = yes; then - archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' - else - archive_cmds='$LD -shared $libobjs $deplibs $linkopts -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' - fi - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator=: - ;; - - netbsd*) - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts' # a.out - else - archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linkopts' # ELF - fi - hardcode_libdir_flag_spec='${wl}-R$libdir' - hardcode_direct=yes - hardcode_shlibpath_var=no - ;; - - openbsd*) - archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts' - hardcode_libdir_flag_spec='-R$libdir' - hardcode_direct=yes - hardcode_shlibpath_var=no - ;; - - os2*) - hardcode_libdir_flag_spec='-L$libdir' - hardcode_minus_L=yes - allow_undefined_flag=unsupported - archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $objdir/$libname.def~$echo DATA >> $objdir/$libname.def~$echo " SINGLE NONSHARED" >> $objdir/$libname.def~$echo EXPORTS >> $objdir/$libname.def~emxexp $libobjs >> $objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $linkopts $objdir/$libname.def' - old_archive_from_new_cmds='emximp -o $objdir/$libname.a $objdir/$libname.def' - ;; - - osf3*) - if test "$with_gcc" = yes; then - allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $linkopts ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' - else - allow_undefined_flag=' -expect_unresolved \*' - archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linkopts -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' - fi - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator=: - ;; - - osf4* | osf5*) # As osf3* with the addition of the -msym flag - if test "$with_gcc" = yes; then - allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $linkopts ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' - else - allow_undefined_flag=' -expect_unresolved \*' - archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linkopts -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' - fi - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator=: - ;; - - sco3.2v5*) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' - hardcode_shlibpath_var=no - runpath_var=LD_RUN_PATH - hardcode_runpath_var=yes - ;; - - solaris*) - no_undefined_flag=' -z text' - # $CC -shared without GNU ld will not create a library from C++ - # object files and a static libstdc++, better avoid it by now - archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linkopts' - archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linkopts~$rm $lib.exp' - hardcode_libdir_flag_spec='-R$libdir' - hardcode_shlibpath_var=no - case "$host_os" in - solaris2.[0-5] | solaris2.[0-5].*) ;; - *) # Supported since Solaris 2.6 (maybe 2.5.1?) - whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;; - esac - ;; - - sunos4*) - archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linkopts' - hardcode_libdir_flag_spec='-L$libdir' - hardcode_direct=yes - hardcode_minus_L=yes - hardcode_shlibpath_var=no - ;; - - sysv4) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' - runpath_var='LD_RUN_PATH' - hardcode_shlibpath_var=no - hardcode_direct=no #Motorola manual says yes, but my tests say they lie - ;; - - sysv4.3*) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' - hardcode_shlibpath_var=no - export_dynamic_flag_spec='-Bexport' - ;; - - sysv5*) - no_undefined_flag=' -z text' - # $CC -shared without GNU ld will not create a library from C++ - # object files and a static libstdc++, better avoid it by now - archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linkopts' - archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linkopts~$rm $lib.exp' - hardcode_libdir_flag_spec= - hardcode_shlibpath_var=no - runpath_var='LD_RUN_PATH' - ;; - - uts4*) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' - hardcode_libdir_flag_spec='-L$libdir' - hardcode_shlibpath_var=no - ;; - - dgux*) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' - hardcode_libdir_flag_spec='-L$libdir' - hardcode_shlibpath_var=no - ;; - - sysv4*MP*) - if test -d /usr/nec; then - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' - hardcode_shlibpath_var=no - runpath_var=LD_RUN_PATH - hardcode_runpath_var=yes - ld_shlibs=yes - fi - ;; - - sysv4.2uw2*) - archive_cmds='$LD -G -o $lib $libobjs $deplibs $linkopts' - hardcode_direct=yes - hardcode_minus_L=no - hardcode_shlibpath_var=no - hardcode_runpath_var=yes - runpath_var=LD_RUN_PATH - ;; - - unixware7*) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' - runpath_var='LD_RUN_PATH' - hardcode_shlibpath_var=no - ;; - - *) - ld_shlibs=no - ;; - esac -fi -echo "$ac_t$ld_shlibs" 1>&6 -test "$ld_shlibs" = no && can_build_shared=no - -if test -z "$NM"; then - echo $ac_n "checking for BSD-compatible nm... $ac_c" 1>&6 - case "$NM" in - [\\/]* | [A-Za-z]:[\\/]*) ;; # Let the user override the test with a path. - *) - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" - for ac_dir in $PATH /usr/ucb /usr/ccs/bin /bin; do - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/nm || test -f $ac_dir/nm$ac_exeext; then - # Check to see if the nm accepts a BSD-compat flag. - # Adding the `sed 1q' prevents false positives on HP-UX, which says: - # nm: unknown option "B" ignored - if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then - NM="$ac_dir/nm -B" - break - elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then - NM="$ac_dir/nm -p" - break - else - NM=${NM="$ac_dir/nm"} # keep the first match, but - continue # so that we can try to find one that supports BSD flags - fi - fi - done - IFS="$ac_save_ifs" - test -z "$NM" && NM=nm - ;; - esac - echo "$ac_t$NM" 1>&6 -fi - -# Check for command to grab the raw symbol name followed by C symbol from nm. -echo $ac_n "checking command to parse $NM output... $ac_c" 1>&6 - -# These are sane defaults that work on at least a few old systems. -# [They come from Ultrix. What could be older than Ultrix?!! ;)] - -# Character class describing NM global symbol codes. -symcode='[BCDEGRST]' - -# Regexp to match symbols that can be accessed directly from C. -sympat='\([_A-Za-z][_A-Za-z0-9]*\)' - -# Transform the above into a raw symbol and a C symbol. -symxfrm='\1 \2\3 \3' - -# Transform an extracted symbol line into a proper C declaration -global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'" - -# Define system-specific variables. -case "$host_os" in -aix*) - symcode='[BCDT]' - ;; -cygwin* | mingw*) - symcode='[ABCDGISTW]' - ;; -hpux*) # Its linker distinguishes data from code symbols - global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^. .* \(.*\)$/extern char \1;/p'" - ;; -irix*) - symcode='[BCDEGRST]' - ;; -solaris*) - symcode='[BDT]' - ;; -sysv4) - symcode='[DFNSTU]' - ;; -esac - -# If we're using GNU nm, then use its standard symbol codes. -if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then - symcode='[ABCDGISTW]' -fi - -# Try without a prefix undercore, then with it. -for ac_symprfx in "" "_"; do - - # Write the raw and C identifiers. - global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode\)[ ][ ]*\($ac_symprfx\)$sympat$/$symxfrm/p'" - - # Check to see that the pipe works correctly. - pipe_works=no - $rm conftest* - cat > conftest.c <&5 - if { (eval echo $progname:1636: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; } && test -s conftest.$objext; then - # Now try to grab the symbols. - nlist=conftest.nm - if { echo "$progname:1639: eval \"$NM conftest.$objext | $global_symbol_pipe > $nlist\"" >&5; eval "$NM conftest.$objext | $global_symbol_pipe > $nlist 2>&5"; } && test -s "$nlist"; then - - # Try sorting and uniquifying the output. - if sort "$nlist" | uniq > "$nlist"T; then - mv -f "$nlist"T "$nlist" - else - rm -f "$nlist"T - fi - - # Make sure that we snagged all the symbols we need. - if egrep ' nm_test_var$' "$nlist" >/dev/null; then - if egrep ' nm_test_func$' "$nlist" >/dev/null; then - cat < conftest.c -#ifdef __cplusplus -extern "C" { -#endif - -EOF - # Now generate the symbol file. - eval "$global_symbol_to_cdecl"' < "$nlist" >> conftest.c' - - cat <> conftest.c -#if defined (__STDC__) && __STDC__ -# define lt_ptr_t void * -#else -# define lt_ptr_t char * -# define const -#endif - -/* The mapping between symbol names and symbols. */ -const struct { - const char *name; - lt_ptr_t address; -} -lt_preloaded_symbols[] = -{ -EOF - sed 's/^. \(.*\) \(.*\)$/ {"\2", (lt_ptr_t) \&\2},/' < "$nlist" >> conftest.c - cat <<\EOF >> conftest.c - {0, (lt_ptr_t) 0} -}; - -#ifdef __cplusplus -} -#endif -EOF - # Now try linking the two files. - mv conftest.$objext conftstm.$objext - save_LIBS="$LIBS" - save_CFLAGS="$CFLAGS" - LIBS="conftstm.$objext" - CFLAGS="$CFLAGS$no_builtin_flag" - if { (eval echo $progname:1691: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then - pipe_works=yes - else - echo "$progname: failed program was:" >&5 - cat conftest.c >&5 - fi - LIBS="$save_LIBS" - else - echo "cannot find nm_test_func in $nlist" >&5 - fi - else - echo "cannot find nm_test_var in $nlist" >&5 - fi - else - echo "cannot run $global_symbol_pipe" >&5 - fi - else - echo "$progname: failed program was:" >&5 - cat conftest.c >&5 - fi - $rm conftest* conftst* - - # Do not use the global_symbol_pipe unless it works. - if test "$pipe_works" = yes; then - break - else - global_symbol_pipe= - fi -done -if test "$pipe_works" = yes; then - echo "${ac_t}ok" 1>&6 -else - echo "${ac_t}failed" 1>&6 -fi - -if test -z "$global_symbol_pipe"; then - global_symbol_to_cdecl= -fi - -# Check hardcoding attributes. -echo $ac_n "checking how to hardcode library paths into programs... $ac_c" 1>&6 -hardcode_action= -if test -n "$hardcode_libdir_flag_spec" || \ - test -n "$runpath_var"; then - - # We can hardcode non-existant directories. - if test "$hardcode_direct" != no && - # If the only mechanism to avoid hardcoding is shlibpath_var, we - # have to relink, otherwise we might link with an installed library - # when we should be linking with a yet-to-be-installed one - ## test "$hardcode_shlibpath_var" != no && - test "$hardcode_minus_L" != no; then - # Linking always hardcodes the temporary library directory. - hardcode_action=relink - else - # We can link without hardcoding, and we can hardcode nonexisting dirs. - hardcode_action=immediate - fi -else - # We cannot hardcode anything, or else we can only hardcode existing - # directories. - hardcode_action=unsupported -fi -echo "$ac_t$hardcode_action" 1>&6 - - -reload_flag= -reload_cmds='$LD$reload_flag -o $output$reload_objs' -echo $ac_n "checking for $LD option to reload object files... $ac_c" 1>&6 -# PORTME Some linkers may need a different reload flag. -reload_flag='-r' -echo "$ac_t$reload_flag" 1>&6 -test -n "$reload_flag" && reload_flag=" $reload_flag" - -# PORTME Fill in your ld.so characteristics -library_names_spec= -libname_spec='lib$name' -soname_spec= -postinstall_cmds= -postuninstall_cmds= -finish_cmds= -finish_eval= -shlibpath_var= -shlibpath_overrides_runpath=unknown -version_type=none -dynamic_linker="$host_os ld.so" -sys_lib_dlsearch_path_spec="/lib /usr/lib" -sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" -file_magic_cmd= -file_magic_test_file= -deplibs_check_method='unknown' -# Need to set the preceding variable on all platforms that support -# interlibrary dependencies. -# 'none' -- dependencies not supported. -# `unknown' -- same as none, but documents that we really don't know. -# 'pass_all' -- all dependencies passed with no checks. -# 'test_compile' -- check by making test program. -# 'file_magic [regex]' -- check by looking for files in library path -# which responds to the $file_magic_cmd with a given egrep regex. -# If you have `file' or equivalent on your system and you're not sure -# whether `pass_all' will *always* work, you probably want this one. -echo $ac_n "checking dynamic linker characteristics... $ac_c" 1>&6 -case "$host_os" in -aix3*) - version_type=linux - library_names_spec='${libname}${release}.so$versuffix $libname.a' - shlibpath_var=LIBPATH - - # AIX has no versioning support, so we append a major version to the name. - soname_spec='${libname}${release}.so$major' - ;; - -aix4*) - version_type=linux - # AIX has no versioning support, so currently we can not hardcode correct - # soname into executable. Probably we can add versioning support to - # collect2, so additional links can be useful in future. - # We preserve .a as extension for shared libraries though AIX4.2 - # and later linker supports .so - library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.a' - shlibpath_var=LIBPATH - deplibs_check_method=pass_all - ;; - -amigaos*) - library_names_spec='$libname.ixlibrary $libname.a' - # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done' - ;; - -beos*) - library_names_spec='${libname}.so' - dynamic_linker="$host_os ld.so" - shlibpath_var=LIBRARY_PATH - deplibs_check_method=pass_all - lt_cv_dlopen="load_add_on" - lt_cv_dlopen_libs= - lt_cv_dlopen_self=yes - ;; - -bsdi4*) - version_type=linux - need_version=no - library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' - soname_spec='${libname}${release}.so$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' - file_magic_cmd=/usr/bin/file - file_magic_test_file=/shlib/libc.so - sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" - sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" - export_dynamic_flag_spec=-rdynamic - # the default ld.so.conf also contains /usr/contrib/lib and - # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow - # libtool to hard-code these into programs - ;; - -cygwin* | mingw*) - version_type=windows - need_version=no - need_lib_prefix=no - if test "$with_gcc" = yes; then - library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.a' - else - library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.lib' - fi - dynamic_linker='Win32 ld.exe' - deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' - file_magic_cmd='${OBJDUMP} -f' - # FIXME: first we should search . and the directory the executable is in - shlibpath_var=PATH - lt_cv_dlopen="LoadLibrary" - lt_cv_dlopen_libs= - ;; - -freebsd1*) - dynamic_linker=no - ;; - -freebsd*) - objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` - version_type=freebsd-$objformat - case "$version_type" in - freebsd-elf*) - deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB shared object' - file_magic_cmd=/usr/bin/file - file_magic_test_file=`echo /usr/lib/libc.so*` - library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so' - need_version=no - need_lib_prefix=no - ;; - freebsd-*) - deplibs_check_method=unknown - library_names_spec='${libname}${release}.so$versuffix $libname.so$versuffix' - need_version=yes - ;; - esac - shlibpath_var=LD_LIBRARY_PATH - case "$host_os" in - freebsd2* | freebsd3.[01]* | freebsdelf3.[01]*) - shlibpath_overrides_runpath=yes - ;; - *) # from 3.2 on - shlibpath_overrides_runpath=no - ;; - esac - ;; - -gnu*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so${major} ${libname}.so' - soname_spec='${libname}${release}.so$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -hpux9* | hpux10* | hpux11*) - # Give a soname corresponding to the major version so that dld.sl refuses to - # link against other versions. - dynamic_linker="$host_os dld.sl" - version_type=sunos - need_lib_prefix=no - need_version=no - shlibpath_var=SHLIB_PATH - shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH - library_names_spec='${libname}${release}.sl$versuffix ${libname}${release}.sl$major $libname.sl' - soname_spec='${libname}${release}.sl$major' - # HP-UX runs *really* slowly unless shared libraries are mode 555. - postinstall_cmds='chmod 555 $lib' - ;; - -irix5* | irix6*) - version_type=irix - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}.so.$major' - library_names_spec='${libname}${release}.so.$versuffix ${libname}${release}.so.$major ${libname}${release}.so $libname.so' - case "$host_os" in - irix5*) - libsuff= shlibsuff= - # this will be overridden with pass_all, but let us keep it just in case - deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1" - ;; - *) - case "$LD" in # libtool.m4 will add one of these switches to LD - *-32|*"-32 ") libsuff= shlibsuff= libmagic=32-bit;; - *-n32|*"-n32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; - *-64|*"-64 ") libsuff=64 shlibsuff=64 libmagic=64-bit;; - *) libsuff= shlibsuff= libmagic=never-match;; - esac - ;; - esac - shlibpath_var=LD_LIBRARY${shlibsuff}_PATH - shlibpath_overrides_runpath=no - sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" - sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" - file_magic_cmd=/usr/bin/file - file_magic_test_file=`echo /lib${libsuff}/libc.so*` - deplibs_check_method='pass_all' - ;; - -# No shared lib support for Linux oldld, aout, or coff. -linux-gnuoldld* | linux-gnuaout* | linux-gnucoff*) - dynamic_linker=no - ;; - -# This must be Linux ELF. -linux-gnu*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' - soname_spec='${libname}${release}.so$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' - file_magic_cmd=/usr/bin/file - file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so` - - if test -f /lib/ld.so.1; then - dynamic_linker='GNU ld.so' - else - # Only the GNU ld.so supports shared libraries on MkLinux. - case "$host_cpu" in - powerpc*) dynamic_linker=no ;; - *) dynamic_linker='Linux ld.so' ;; - esac - fi - ;; - -netbsd*) - version_type=sunos - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - dynamic_linker='NetBSD (a.out) ld.so' - else - library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so ${libname}.so' - soname_spec='${libname}${release}.so$major' - dynamic_linker='NetBSD ld.elf_so' - fi - shlibpath_var=LD_LIBRARY_PATH - ;; - -openbsd*) - version_type=sunos - if test "$with_gnu_ld" = yes; then - need_lib_prefix=no - need_version=no - fi - library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - shlibpath_var=LD_LIBRARY_PATH - ;; - -os2*) - libname_spec='$name' - need_lib_prefix=no - library_names_spec='$libname.dll $libname.a' - dynamic_linker='OS/2 ld.exe' - shlibpath_var=LIBPATH - ;; - -osf3* | osf4* | osf5*) - version_type=osf - need_version=no - soname_spec='${libname}${release}.so' - library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so' - shlibpath_var=LD_LIBRARY_PATH - # this will be overridden with pass_all, but let us keep it just in case - deplibs_check_method='file_magic COFF format alpha shared library' - file_magic_cmd=/usr/bin/file - file_magic_test_file=/shlib/libc.so - deplibs_check_method='pass_all' - sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" - sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" - ;; - -sco3.2v5*) - version_type=osf - soname_spec='${libname}${release}.so$major' - library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' - shlibpath_var=LD_LIBRARY_PATH - ;; - -solaris*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' - soname_spec='${libname}${release}.so$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - # ldd complains unless libraries are executable - postinstall_cmds='chmod +x $lib' - deplibs_check_method="file_magic ELF [0-9][0-9]-bit [LM]SB dynamic lib" - file_magic_cmd=/usr/bin/file - file_magic_test_file=/lib/libc.so - ;; - -sunos4*) - version_type=sunos - library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' - finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - if test "$with_gnu_ld" = yes; then - need_lib_prefix=no - fi - need_version=yes - ;; - -sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) - version_type=linux - library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' - soname_spec='${libname}${release}.so$major' - shlibpath_var=LD_LIBRARY_PATH - case "$host_vendor" in - ncr) - deplibs_check_method='pass_all' - ;; - motorola) - need_lib_prefix=no - need_version=no - shlibpath_overrides_runpath=no - sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' - deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' - file_magic_cmd=/usr/bin/file - file_magic_test_file=`echo /usr/lib/libc.so*` - ;; - esac - ;; - -uts4*) - version_type=linux - library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' - soname_spec='${libname}${release}.so$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -dgux*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' - soname_spec='${libname}${release}.so$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -sysv4*MP*) - if test -d /usr/nec ;then - version_type=linux - library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so' - soname_spec='$libname.so.$major' - shlibpath_var=LD_LIBRARY_PATH - fi - ;; - -*) - dynamic_linker=no - ;; -esac -echo "$ac_t$dynamic_linker" 1>&6 -test "$dynamic_linker" = no && can_build_shared=no - -# Report the final consequences. -echo "checking if libtool supports shared libraries... $can_build_shared" 1>&6 - -# Only try to build win32 dlls if AC_LIBTOOL_WIN32_DLL was used in -# configure.in, otherwise build static only libraries. -case "$host_os" in -cygwin* | mingw* | os2*) - if test x$can_build_shared = xyes; then - test x$enable_win32_dll = xno && can_build_shared=no - echo "checking if package supports dlls... $can_build_shared" 1>&6 - fi -;; -esac - -if test -n "$file_magic_test_file" && test -n "$file_magic_cmd"; then - case "$deplibs_check_method" in - "file_magic "*) - file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`" - if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | - egrep "$file_magic_regex" > /dev/null; then - : - else - cat <&2 - -*** Warning: the command libtool uses to detect shared libraries, -*** $file_magic_cmd, produces output that libtool cannot recognize. -*** The result is that libtool may fail to recognize shared libraries -*** as such. This will affect the creation of libtool libraries that -*** depend on shared libraries, but programs linked with such libtool -*** libraries will work regardless of this problem. Nevertheless, you -*** may want to report the problem to your system manager and/or to -*** bug-libtool@gnu.org - -EOF - fi ;; - esac -fi - -echo $ac_n "checking whether to build shared libraries... $ac_c" 1>&6 -test "$can_build_shared" = "no" && enable_shared=no - -# On AIX, shared libraries and static libraries use the same namespace, and -# are all built from PIC. -case "$host_os" in -aix3*) - test "$enable_shared" = yes && enable_static=no - if test -n "$RANLIB"; then - archive_cmds="$archive_cmds~\$RANLIB \$lib" - postinstall_cmds='$RANLIB $lib' - fi - ;; - -aix4*) - test "$enable_shared" = yes && enable_static=no - ;; -esac - -echo "$ac_t$enable_shared" 1>&6 - -# Make sure either enable_shared or enable_static is yes. -test "$enable_shared" = yes || enable_static=yes - -echo "checking whether to build static libraries... $enable_static" 1>&6 - -if test "$hardcode_action" = relink; then - # Fast installation is not supported - enable_fast_install=no -elif test "$shlibpath_overrides_runpath" = yes || - test "$enable_shared" = no; then - # Fast installation is not necessary - enable_fast_install=needless -fi - -echo $ac_n "checking for objdir... $ac_c" 1>&6 -rm -f .libs 2>/dev/null -mkdir .libs 2>/dev/null -if test -d .libs; then - objdir=.libs -else - # MS-DOS does not allow filenames that begin with a dot. - objdir=_libs -fi -rmdir .libs 2>/dev/null -echo "$ac_t$objdir" 1>&6 - -if test "x$enable_dlopen" != xyes; then - enable_dlopen=unknown - enable_dlopen_self=unknown - enable_dlopen_self_static=unknown -else -if eval "test \"`echo '$''{'lt_cv_dlopen'+set}'`\" != set"; then - lt_cv_dlopen=no lt_cv_dlopen_libs= -echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6 -echo "$progname:2212: checking for dlopen in -ldl" >&5 -ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'` -if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - ac_save_LIBS="$LIBS" -LIBS="-ldl $LIBS" -cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=yes" -else - echo "$progname: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=no" -fi -rm -f conftest* -LIBS="$ac_save_LIBS" - -fi -if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then - echo "$ac_t""yes" 1>&6 - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" -else - echo "$ac_t""no" 1>&6 -echo $ac_n "checking for dlopen""... $ac_c" 1>&6 -echo "$progname:2252: checking for dlopen" >&5 -if eval "test \"`echo '$''{'ac_cv_func_dlopen'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext < -/* Override any gcc2 internal prototype to avoid an error. */ -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char dlopen(); - -int main() { - -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_dlopen) || defined (__stub___dlopen) -choke me -#else -dlopen(); -#endif - -; return 0; } -EOF -if { (eval echo $progname:2282: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - eval "ac_cv_func_dlopen=yes" -else - echo "$progname: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_func_dlopen=no" -fi -rm -f conftest* -fi -if eval "test \"`echo '$ac_cv_func_'dlopen`\" = yes"; then - echo "$ac_t""yes" 1>&6 - lt_cv_dlopen="dlopen" -else - echo "$ac_t""no" 1>&6 -echo $ac_n "checking for dld_link in -ldld""... $ac_c" 1>&6 -echo "$progname:2299: checking for dld_link in -ldld" >&5 -ac_lib_var=`echo dld'_'dld_link | sed 'y%./+-%__p_%'` -if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - ac_save_LIBS="$LIBS" -LIBS="-ldld $LIBS" -cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=yes" -else - echo "$progname: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=no" -fi -rm -f conftest* -LIBS="$ac_save_LIBS" - -fi -if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then - echo "$ac_t""yes" 1>&6 - lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" -else - echo "$ac_t""no" 1>&6 -echo $ac_n "checking for shl_load""... $ac_c" 1>&6 -echo "$progname:2339: checking for shl_load" >&5 -if eval "test \"`echo '$''{'ac_cv_func_shl_load'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext < -/* Override any gcc2 internal prototype to avoid an error. */ -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char shl_load(); - -int main() { - -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_shl_load) || defined (__stub___shl_load) -choke me -#else -shl_load(); -#endif - -; return 0; } -EOF -if { (eval echo $progname:2369: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - eval "ac_cv_func_shl_load=yes" -else - echo "$progname: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_func_shl_load=no" -fi -rm -f conftest* -fi - -if eval "test \"`echo '$ac_cv_func_'shl_load`\" = yes"; then - echo "$ac_t""yes" 1>&6 - lt_cv_dlopen="shl_load" -else - echo "$ac_t""no" 1>&6 -echo $ac_n "checking for shl_load in -ldld""... $ac_c" 1>&6 -echo "$progname:2387: checking for shl_load in -ldld" >&5 -ac_lib_var=`echo dld'_'shl_load | sed 'y%./+-%__p_%'` -if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - ac_save_LIBS="$LIBS" -LIBS="-ldld $LIBS" -cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=yes" -else - echo "$progname: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=no" -fi -rm -f conftest* -LIBS="$ac_save_LIBS" - -fi -if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then - echo "$ac_t""yes" 1>&6 - lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" -else - echo "$ac_t""no" 1>&6 -fi - - -fi - - -fi - - -fi - - -fi - -fi - - if test "x$lt_cv_dlopen" != xno; then - enable_dlopen=yes - fi - - case "$lt_cv_dlopen" in - dlopen) -for ac_hdr in dlfcn.h; do -ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` -echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "$progname:2452: checking for $ac_hdr" >&5 -if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext < -int fnord = 0; -EOF -ac_try="$ac_compile >/dev/null 2>conftest.out" -{ (eval echo $progname:2462: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } -ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` -if test -z "$ac_err"; then - rm -rf conftest* - eval "ac_cv_header_$ac_safe=yes" -else - echo "$ac_err" >&5 - echo "$progname: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_header_$ac_safe=no" -fi -rm -f conftest* -fi -if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then - echo "$ac_t""yes" 1>&6 -else - echo "$ac_t""no" 1>&6 -fi -done - - if test "x$ac_cv_header_dlfcn_h" = xyes; then - CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" - fi - eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" - LIBS="$lt_cv_dlopen_libs $LIBS" - - echo $ac_n "checking whether a program can dlopen itself""... $ac_c" 1>&6 -echo "$progname:2490: checking whether a program can dlopen itself" >&5 -if test "${lt_cv_dlopen_self+set}" = set; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test "$cross_compiling" = yes; then - lt_cv_dlopen_self=cross - else - cat > conftest.c < -#endif - -#include - -#ifdef RTLD_GLOBAL -# define LTDL_GLOBAL RTLD_GLOBAL -#else -# ifdef DL_GLOBAL -# define LTDL_GLOBAL DL_GLOBAL -# else -# define LTDL_GLOBAL 0 -# endif -#endif - -/* We may have to define LTDL_LAZY_OR_NOW in the command line if we - find out it does not work in some platform. */ -#ifndef LTDL_LAZY_OR_NOW -# ifdef RTLD_LAZY -# define LTDL_LAZY_OR_NOW RTLD_LAZY -# else -# ifdef DL_LAZY -# define LTDL_LAZY_OR_NOW DL_LAZY -# else -# ifdef RTLD_NOW -# define LTDL_LAZY_OR_NOW RTLD_NOW -# else -# ifdef DL_NOW -# define LTDL_LAZY_OR_NOW DL_NOW -# else -# define LTDL_LAZY_OR_NOW 0 -# endif -# endif -# endif -# endif -#endif - -fnord() { int i=42;} -main() { void *self, *ptr1, *ptr2; self=dlopen(0,LTDL_GLOBAL|LTDL_LAZY_OR_NOW); - if(self) { ptr1=dlsym(self,"fnord"); ptr2=dlsym(self,"_fnord"); - if(ptr1 || ptr2) { dlclose(self); exit(0); } } exit(1); } - -EOF -if { (eval echo $progname:2544: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null -then - lt_cv_dlopen_self=yes -else - echo "$progname: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -fr conftest* - lt_cv_dlopen_self=no -fi -rm -fr conftest* -fi - -fi - -echo "$ac_t""$lt_cv_dlopen_self" 1>&6 - - if test "$lt_cv_dlopen_self" = yes; then - LDFLAGS="$LDFLAGS $link_static_flag" - echo $ac_n "checking whether a statically linked program can dlopen itself""... $ac_c" 1>&6 -echo "$progname:2563: checking whether a statically linked program can dlopen itself" >&5 -if test "${lt_cv_dlopen_self_static+set}" = set; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test "$cross_compiling" = yes; then - lt_cv_dlopen_self_static=cross - else - cat > conftest.c < -#endif - -#include - -#ifdef RTLD_GLOBAL -# define LTDL_GLOBAL RTLD_GLOBAL -#else -# ifdef DL_GLOBAL -# define LTDL_GLOBAL DL_GLOBAL -# else -# define LTDL_GLOBAL 0 -# endif -#endif - -/* We may have to define LTDL_LAZY_OR_NOW in the command line if we - find out it does not work in some platform. */ -#ifndef LTDL_LAZY_OR_NOW -# ifdef RTLD_LAZY -# define LTDL_LAZY_OR_NOW RTLD_LAZY -# else -# ifdef DL_LAZY -# define LTDL_LAZY_OR_NOW DL_LAZY -# else -# ifdef RTLD_NOW -# define LTDL_LAZY_OR_NOW RTLD_NOW -# else -# ifdef DL_NOW -# define LTDL_LAZY_OR_NOW DL_NOW -# else -# define LTDL_LAZY_OR_NOW 0 -# endif -# endif -# endif -# endif -#endif - -fnord() { int i=42;} -main() { void *self, *ptr1, *ptr2; self=dlopen(0,LTDL_GLOBAL|LTDL_LAZY_OR_NOW); - if(self) { ptr1=dlsym(self,"fnord"); ptr2=dlsym(self,"_fnord"); - if(ptr1 || ptr2) { dlclose(self); exit(0); } } exit(1); } - -EOF -if { (eval echo $progname:2617: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null -then - lt_cv_dlopen_self_static=yes -else - echo "$progname: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -fr conftest* - lt_cv_dlopen_self_static=no -fi -rm -fr conftest* -fi - -fi - -echo "$ac_t""$lt_cv_dlopen_self_static" 1>&6 -fi - ;; - esac - - case "$lt_cv_dlopen_self" in - yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; - *) enable_dlopen_self=unknown ;; - esac - - case "$lt_cv_dlopen_self_static" in - yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; - *) enable_dlopen_self_static=unknown ;; - esac -fi - -# Copy echo and quote the copy, instead of the original, because it is -# used later. -ltecho="$echo" -if test "X$ltecho" = "X$CONFIG_SHELL $0 --fallback-echo"; then - ltecho="$CONFIG_SHELL \$0 --fallback-echo" -fi -LTSHELL="$SHELL" - -LTCONFIG_VERSION="$VERSION" - -# Only quote variables if we're using ltmain.sh. -case "$ltmain" in -*.sh) - # Now quote all the things that may contain metacharacters. - for var in ltecho old_CC old_CFLAGS old_CPPFLAGS \ - old_LD old_LDFLAGS old_LIBS \ - old_NM old_RANLIB old_LN_S old_DLLTOOL old_OBJDUMP old_AS \ - AR CC LD LN_S NM LTSHELL LTCONFIG_VERSION \ - reload_flag reload_cmds wl \ - pic_flag link_static_flag no_builtin_flag export_dynamic_flag_spec \ - thread_safe_flag_spec whole_archive_flag_spec libname_spec \ - library_names_spec soname_spec \ - RANLIB old_archive_cmds old_archive_from_new_cmds old_postinstall_cmds \ - old_postuninstall_cmds archive_cmds archive_expsym_cmds postinstall_cmds postuninstall_cmds \ - file_magic_cmd export_symbols_cmds deplibs_check_method allow_undefined_flag no_undefined_flag \ - finish_cmds finish_eval global_symbol_pipe global_symbol_to_cdecl \ - hardcode_libdir_flag_spec hardcode_libdir_separator \ - sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ - compiler_c_o compiler_o_lo need_locks exclude_expsyms include_expsyms; do - - case "$var" in - reload_cmds | old_archive_cmds | old_archive_from_new_cmds | \ - old_postinstall_cmds | old_postuninstall_cmds | \ - export_symbols_cmds | archive_cmds | archive_expsym_cmds | \ - postinstall_cmds | postuninstall_cmds | \ - finish_cmds | sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) - # Double-quote double-evaled strings. - eval "$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" - ;; - *) - eval "$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" - ;; - esac - done - - case "$ltecho" in - *'\$0 --fallback-echo"') - ltecho=`$echo "X$ltecho" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` - ;; - esac - - trap "$rm \"$ofile\"; exit 1" 1 2 15 - echo "creating $ofile" - $rm "$ofile" - cat < "$ofile" -#! $SHELL - -# `$echo "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. -# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) -# NOTE: Changes made to this file will be lost: look at ltconfig or ltmain.sh. -# -# Copyright (C) 1996-1999 Free Software Foundation, Inc. -# Originally by Gordon Matzigkeit , 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 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# Sed that helps us avoid accidentally triggering echo(1) options like -n. -Xsed="sed -e s/^X//" - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi - -### BEGIN LIBTOOL CONFIG -EOF - cfgfile="$ofile" - ;; - -*) - # Double-quote the variables that need it (for aesthetics). - for var in old_CC old_CFLAGS old_CPPFLAGS \ - old_LD old_LDFLAGS old_LIBS \ - old_NM old_RANLIB old_LN_S old_DLLTOOL old_OBJDUMP old_AS; do - eval "$var=\\\"\$var\\\"" - done - - # Just create a config file. - cfgfile="$ofile.cfg" - trap "$rm \"$cfgfile\"; exit 1" 1 2 15 - echo "creating $cfgfile" - $rm "$cfgfile" - cat < "$cfgfile" -# `$echo "$cfgfile" | sed 's%^.*/%%'` - Libtool configuration file. -# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) -EOF - ;; -esac - -cat <> "$cfgfile" -# Libtool was configured as follows, on host `(hostname || uname -n) 2>/dev/null | sed 1q`: -# -# CC=$old_CC CFLAGS=$old_CFLAGS CPPFLAGS=$old_CPPFLAGS \\ -# LD=$old_LD LDFLAGS=$old_LDFLAGS LIBS=$old_LIBS \\ -# NM=$old_NM RANLIB=$old_RANLIB LN_S=$old_LN_S \\ -# DLLTOOL=$old_DLLTOOL OBJDUMP=$old_OBJDUMP AS=$old_AS \\ -# $0$ltconfig_args -# -# Compiler and other test output produced by $progname, useful for -# debugging $progname, is in ./config.log if it exists. - -# The version of $progname that generated this script. -LTCONFIG_VERSION=$LTCONFIG_VERSION - -# Shell to use when invoking shell scripts. -SHELL=$LTSHELL - -# Whether or not to build shared libraries. -build_libtool_libs=$enable_shared - -# Whether or not to build static libraries. -build_old_libs=$enable_static - -# Whether or not to optimize for fast installation. -fast_install=$enable_fast_install - -# The host system. -host_alias=$host_alias -host=$host - -# An echo program that does not interpret backslashes. -echo=$ltecho - -# The archiver. -AR=$AR - -# The default C compiler. -CC=$CC - -# The linker used to build libraries. -LD=$LD - -# Whether we need hard or soft links. -LN_S=$LN_S - -# A BSD-compatible nm program. -NM=$NM - -# Used on cygwin: DLL creation program. -DLLTOOL="$DLLTOOL" - -# Used on cygwin: object dumper. -OBJDUMP="$OBJDUMP" - -# Used on cygwin: assembler. -AS="$AS" - -# The name of the directory that contains temporary libtool files. -objdir=$objdir - -# How to create reloadable object files. -reload_flag=$reload_flag -reload_cmds=$reload_cmds - -# How to pass a linker flag through the compiler. -wl=$wl - -# Object file suffix (normally "o"). -objext="$objext" - -# Old archive suffix (normally "a"). -libext="$libext" - -# Executable file suffix (normally ""). -exeext="$exeext" - -# Additional compiler flags for building library objects. -pic_flag=$pic_flag - -# Does compiler simultaneously support -c and -o options? -compiler_c_o=$compiler_c_o - -# Can we write directly to a .lo ? -compiler_o_lo=$compiler_o_lo - -# Must we lock files when doing compilation ? -need_locks=$need_locks - -# Do we need the lib prefix for modules? -need_lib_prefix=$need_lib_prefix - -# Do we need a version for libraries? -need_version=$need_version - -# Whether dlopen is supported. -dlopen=$enable_dlopen - -# Whether dlopen of programs is supported. -dlopen_self=$enable_dlopen_self - -# Whether dlopen of statically linked programs is supported. -dlopen_self_static=$enable_dlopen_self_static - -# Compiler flag to prevent dynamic linking. -link_static_flag=$link_static_flag - -# Compiler flag to turn off builtin functions. -no_builtin_flag=$no_builtin_flag - -# Compiler flag to allow reflexive dlopens. -export_dynamic_flag_spec=$export_dynamic_flag_spec - -# Compiler flag to generate shared objects directly from archives. -whole_archive_flag_spec=$whole_archive_flag_spec - -# Compiler flag to generate thread-safe objects. -thread_safe_flag_spec=$thread_safe_flag_spec - -# Library versioning type. -version_type=$version_type - -# Format of library name prefix. -libname_spec=$libname_spec - -# List of archive names. First name is the real one, the rest are links. -# The last name is the one that the linker finds with -lNAME. -library_names_spec=$library_names_spec - -# The coded name of the library, if different from the real name. -soname_spec=$soname_spec - -# Commands used to build and install an old-style archive. -RANLIB=$RANLIB -old_archive_cmds=$old_archive_cmds -old_postinstall_cmds=$old_postinstall_cmds -old_postuninstall_cmds=$old_postuninstall_cmds - -# Create an old-style archive from a shared archive. -old_archive_from_new_cmds=$old_archive_from_new_cmds - -# Commands used to build and install a shared archive. -archive_cmds=$archive_cmds -archive_expsym_cmds=$archive_expsym_cmds -postinstall_cmds=$postinstall_cmds -postuninstall_cmds=$postuninstall_cmds - -# Method to check whether dependent libraries are shared objects. -deplibs_check_method=$deplibs_check_method - -# Command to use when deplibs_check_method == file_magic. -file_magic_cmd=$file_magic_cmd - -# Flag that allows shared libraries with undefined symbols to be built. -allow_undefined_flag=$allow_undefined_flag - -# Flag that forces no undefined symbols. -no_undefined_flag=$no_undefined_flag - -# Commands used to finish a libtool library installation in a directory. -finish_cmds=$finish_cmds - -# Same as above, but a single script fragment to be evaled but not shown. -finish_eval=$finish_eval - -# Take the output of nm and produce a listing of raw symbols and C names. -global_symbol_pipe=$global_symbol_pipe - -# Transform the output of nm in a proper C declaration -global_symbol_to_cdecl=$global_symbol_to_cdecl - -# This is the shared library runtime path variable. -runpath_var=$runpath_var - -# This is the shared library path variable. -shlibpath_var=$shlibpath_var - -# Is shlibpath searched before the hard-coded library search path? -shlibpath_overrides_runpath=$shlibpath_overrides_runpath - -# How to hardcode a shared library path into an executable. -hardcode_action=$hardcode_action - -# Flag to hardcode \$libdir into a binary during linking. -# This must work even if \$libdir does not exist. -hardcode_libdir_flag_spec=$hardcode_libdir_flag_spec - -# Whether we need a single -rpath flag with a separated argument. -hardcode_libdir_separator=$hardcode_libdir_separator - -# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the -# resulting binary. -hardcode_direct=$hardcode_direct - -# Set to yes if using the -LDIR flag during linking hardcodes DIR into the -# resulting binary. -hardcode_minus_L=$hardcode_minus_L - -# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into -# the resulting binary. -hardcode_shlibpath_var=$hardcode_shlibpath_var - -# Compile-time system search path for libraries -sys_lib_search_path_spec=$sys_lib_search_path_spec - -# Run-time system search path for libraries -sys_lib_dlsearch_path_spec=$sys_lib_dlsearch_path_spec - -# Fix the shell variable \$srcfile for the compiler. -fix_srcfile_path="$fix_srcfile_path" - -# Set to yes if exported symbols are required. -always_export_symbols=$always_export_symbols - -# The commands to list exported symbols. -export_symbols_cmds=$export_symbols_cmds - -# Symbols that should not be listed in the preloaded symbols. -exclude_expsyms=$exclude_expsyms - -# Symbols that must always be exported. -include_expsyms=$include_expsyms - -EOF - -case "$ltmain" in -*.sh) - echo '### END LIBTOOL CONFIG' >> "$ofile" - echo >> "$ofile" - case "$host_os" in - aix3*) - cat <<\EOF >> "$ofile" - -# AIX sometimes has problems with the GCC collect2 program. For some -# reason, if we set the COLLECT_NAMES environment variable, the problems -# vanish in a puff of smoke. -if test "X${COLLECT_NAMES+set}" != Xset; then - COLLECT_NAMES= - export COLLECT_NAMES -fi -EOF - ;; - esac - - # Append the ltmain.sh script. - sed '$q' "$ltmain" >> "$ofile" || (rm -f "$ofile"; exit 1) - # We use sed instead of cat because bash on DJGPP gets confused if - # if finds mixed CR/LF and LF-only lines. Since sed operates in - # text mode, it properly converts lines to CR/LF. This bash problem - # is reportedly fixed, but why not run on old versions too? - - chmod +x "$ofile" - ;; - -*) - # Compile the libtool program. - echo "FIXME: would compile $ltmain" - ;; -esac - -test -n "$cache_file" || exit 0 - -# AC_CACHE_SAVE -trap '' 1 2 15 -cat > confcache <<\EOF -# This file is a shell script that caches the results of configure -# tests run on this system so they can be shared between configure -# scripts and configure runs. It is not useful on other systems. -# If it contains results you don't want to keep, you may remove or edit it. -# -# By default, configure uses ./config.cache as the cache file, -# creating it if it does not exist already. You can give configure -# the --cache-file=FILE option to use a different cache file; that is -# what configure does when it calls configure scripts in -# subdirectories, so they share the cache. -# Giving --cache-file=/dev/null disables caching, for debugging configure. -# config.status only pays attention to the cache file if you give it the -# --recheck option to rerun configure. -# -EOF -# The following way of writing the cache mishandles newlines in values, -# but we know of no workaround that is simple, portable, and efficient. -# So, don't put newlines in cache variables' values. -# Ultrix sh set writes to stderr and can't be redirected directly, -# and sets the high bit in the cache file unless we assign to the vars. -(set) 2>&1 | - case `(ac_space=' '; set | grep ac_space) 2>&1` in - *ac_space=\ *) - # `set' does not quote correctly, so add quotes (double-quote substitution - # turns \\\\ into \\, and sed turns \\ into \). - sed -n \ - -e "s/'/'\\\\''/g" \ - -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" - ;; - *) - # `set' quotes correctly as required by POSIX, so do not add quotes. - sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' - ;; - esac >> confcache -if cmp -s $cache_file confcache; then - : -else - if test -w $cache_file; then - echo "updating cache $cache_file" - cat confcache > $cache_file - else - echo "not updating unwritable cache $cache_file" - fi -fi -rm -f confcache - -exit 0 - -# Local Variables: -# mode:shell-script -# sh-indentation:2 -# End: diff --git a/libs/xmlrpc-c/src/.cvsignore b/libs/xmlrpc-c/src/.cvsignore deleted file mode 100644 index b808ac3..0000000 --- a/libs/xmlrpc-c/src/.cvsignore +++ /dev/null @@ -1,6 +0,0 @@ -Makefile -rpctest -rpctest.static -cpptest -efrpctest -efrpctest_wrapper diff --git a/libs/xmlrpc-c/src/Makefile b/libs/xmlrpc-c/src/Makefile index 50514b2..36300e9 100644 --- a/libs/xmlrpc-c/src/Makefile +++ b/libs/xmlrpc-c/src/Makefile @@ -48,15 +48,18 @@ SHARED_LIBS_TO_INSTALL := $(TARGET_LIBRARY_NAMES) TRANSPORT_MODS = TRANSPORT_LIBDEP = ifeq ($(MUST_BUILD_WININET_CLIENT),yes) - TRANSPORT_MODS += $(BLDDIR)/lib/wininet_transport/xmlrpc_wininet_transport + TRANSPORT_MODS += blddir/lib/wininet_transport/xmlrpc_wininet_transport TRANSPORT_LIBDEP += $(shell wininet-config --libs) endif ifeq ($(MUST_BUILD_CURL_CLIENT),yes) - TRANSPORT_MODS += $(BLDDIR)/lib/curl_transport/xmlrpc_curl_transport + TRANSPORT_MODS += blddir/lib/curl_transport/xmlrpc_curl_transport + TRANSPORT_MODS += blddir/lib/curl_transport/curltransaction + TRANSPORT_MODS += blddir/lib/curl_transport/curlmulti + TRANSPORT_MODS += blddir/lib/curl_transport/lock_pthread TRANSPORT_LIBDEP += $(shell curl-config --libs) endif ifeq ($(MUST_BUILD_LIBWWW_CLIENT),yes) - TRANSPORT_MODS += $(BLDDIR)/lib/libwww_transport/xmlrpc_libwww_transport + TRANSPORT_MODS += blddir/lib/libwww_transport/xmlrpc_libwww_transport TRANSPORT_LIBDEP += $(shell libwww-config --libs) endif @@ -66,14 +69,18 @@ ifeq ($(ENABLE_LIBXML2_BACKEND),yes) 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) + XML_PARSER_LIBDEP = \ + -Lblddir/lib/expat/xmlparse -lxmlrpc_xmlparse \ + -Lblddir/lib/expat/xmltok -lxmlrpc_xmltok + XML_PARSER_LIBDEP_DEP = $(LIBXMLRPC_XMLPARSE) $(LIBXMLRPC_XMLTOK) endif # LIBxxx_OBJS is the list of object files that make up library libxxx. LIBXMLRPC_MODS = \ double \ + json \ + parse_datetime \ parse_value \ resource \ trace \ @@ -130,7 +137,7 @@ 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 +cpp/all: $(BLDDIR)/transport_config.h $(TARGET_SHARED_LE_LIBS) endif #----------------------------------------------------------------------------- @@ -160,7 +167,7 @@ $(LIBXMLRPC_SERVER): \ $(call shliblefn, libxmlrpc) $(LIBXMLRPC_SERVER): LIBOBJECTS = $(LIBXMLRPC_SERVER_MODS:%=%.osh) $(LIBXMLRPC_SERVER): LIBDEP = \ - -L$(LIBXMLRPC_UTIL_DIR) -lxmlrpc_util -L. -lxmlrpc + -L. -lxmlrpc $(XML_PARSER_LIBDEP) -L$(LIBXMLRPC_UTIL_DIR) -lxmlrpc_util LIBXMLRPC_SERVER_ABYSS = $(call shlibfn, libxmlrpc_server_abyss) @@ -172,10 +179,9 @@ $(LIBXMLRPC_SERVER_ABYSS): \ $(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 + -L. -lxmlrpc $(XML_PARSER_LIBDEP) -L$(LIBXMLRPC_UTIL_DIR) -lxmlrpc_util LIBXMLRPC_SERVER_CGI = $(call shlibfn, libxmlrpc_server_cgi) @@ -186,7 +192,8 @@ $(LIBXMLRPC_SERVER_CGI): \ $(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 + -L. -lxmlrpc_server \ + -L. -lxmlrpc $(XML_PARSER_LIBDEP) -L$(LIBXMLRPC_UTIL_DIR) -lxmlrpc_util LIBXMLRPC_CLIENT = $(call shlibfn, libxmlrpc_client) @@ -199,10 +206,8 @@ $(LIBXMLRPC_CLIENT): LIBOBJECTS = \ $(LIBXMLRPC_CLIENT_MODS:%=%.osh) \ $(TRANSPORT_MODS:%=%.osh) $(LIBXMLRPC_CLIENT): LIBDEP = \ - -L$(LIBXMLRPC_UTIL_DIR) -lxmlrpc_util \ - -L. -lxmlrpc \ - $(TRANSPORT_LIBDEP) - + $(TRANSPORT_LIBDEP) \ + -L. -lxmlrpc $(XML_PARSER_LIBDEP) -L$(LIBXMLRPC_UTIL_DIR) -lxmlrpc_util libxmlrpc.a: $(LIBXMLRPC_MODS:%=%.o) libxmlrpc.a: LIBOBJECTS = $(LIBXMLRPC_MODS:%=%.o) @@ -229,20 +234,20 @@ libxmlrpc_client.a: LIBOBJECTS = \ # 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 \ + -Iblddir \ + -Iblddir/include \ + -Isrcdir/include \ + -Isrcdir/lib/util/include \ TRANSPORT_INCLUDES = \ - -I$($SRCDIR)/lib/wininet_transport \ - -I$(SRCDIR)/lib/curl_transport \ - -I$(SRCDIR)/lib/libwww_transport \ + -Isrcdir/lib/wininet_transport \ + -Isrcdir/lib/curl_transport \ + -Isrcdir/lib/libwww_transport \ ifeq ($(ENABLE_LIBXML2_BACKEND),yes) LIBXML_INCLUDES = $(shell xml2-config --cflags) else - LIBXML_INCLUDES = -I$(SRCDIR)/lib/expat/xmlparse + LIBXML_INCLUDES = -Isrcdir/lib/expat/xmlparse endif $(LIBXMLRPC_MODS:%=%.o) \ @@ -259,14 +264,12 @@ $(LIBXMLRPC_SERVER_MODS:%=%.osh): \ $(LIBXMLRPC_SERVER_ABYSS_MODS:%=%.o) \ $(LIBXMLRPC_SERVER_ABYSS_MODS:%=%.osh): \ - INCLUDES = $(BASIC_INCLUDES) -I$(SRCDIR)/lib/abyss/src + INCLUDES = $(BASIC_INCLUDES) -Isrcdir/lib/abyss/src $(LIBXMLRPC_SERVER_CGI_MODS:%=%.o) \ $(LIBXMLRPC_SERVER_CGI_MODS:%=%.osh): \ INCLUDES = $(BASIC_INCLUDES) -CFLAGS = $(CFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD) - check: $(MAKE) -C test runtests @@ -275,12 +278,15 @@ check: .PHONY: install install: install-common $(SUBDIRS:%=%/install) -.PHONY: clean clean-local distclean -clean: clean-common clean-local $(SUBDIRS:%=%/clean) +.PHONY: clean clean-local distclean distclean-local +clean: clean-common clean-local clean-local: $(MAKE) -C test clean -distclean: clean-common clean-local distclean-common $(SUBDIRS:%=%/distclean) +distclean: clean distclean-local distclean-common + +distclean-local: + $(MAKE) -C test distclean .PHONY: dep dep: $(SUBDIRS:%=%/dep) $(BLDDIR)/transport_config.h dep-common @@ -293,4 +299,4 @@ 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 +include depend.mk diff --git a/libs/xmlrpc-c/src/Makefile.depend b/libs/xmlrpc-c/src/Makefile.depend deleted file mode 100644 index e69de29..0000000 diff --git a/libs/xmlrpc-c/src/cpp/.cvsignore b/libs/xmlrpc-c/src/cpp/.cvsignore deleted file mode 100644 index 19bccb9..0000000 --- a/libs/xmlrpc-c/src/cpp/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -cpptest diff --git a/libs/xmlrpc-c/src/cpp/Makefile b/libs/xmlrpc-c/src/cpp/Makefile index fa2fac4..9142fcb 100644 --- a/libs/xmlrpc-c/src/cpp/Makefile +++ b/libs/xmlrpc-c/src/cpp/Makefile @@ -13,22 +13,26 @@ default: all # libxmlrpc_cpp is the legacy C++ wrapper library. The others are the # more elaborate replacements. -TARGET_LIB_NAMES_PP := \ +TARGET_LIB_NAMES_PP = \ libxmlrpc_cpp \ - libxmlrpc++ \ + lib$(LIBXMLRPCPP_NAME) \ libxmlrpc_server++ \ - libxmlrpc_server_abyss++ \ + libxmlrpc_server_cgi++ \ libxmlrpc_server_pstream++ \ libxmlrpc_packetsocket \ +ifeq ($(ENABLE_ABYSS_SERVER),yes) + TARGET_LIB_NAMES_PP += libxmlrpc_server_abyss++ +endif + 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) +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) \ @@ -45,11 +49,20 @@ else LIBXML_INCLUDES = -Isrcdir/lib/expat/xmlparse endif +ifeq ($(ENABLE_LIBXML2_BACKEND),yes) + XML_PARSER_LIBDEP = $(shell xml2-config --libs) +else + XML_PARSER_LIBDEP = \ + -L$(BLDDIR)/lib/expat/xmlparse -lxmlrpc_xmlparse \ + -L$(BLDDIR)/lib/expat/xmltok -lxmlrpc_xmltok +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_SERVER_CGIPP_MODS = server_cgi +LIBXMLRPC_SERVER_PSTREAMPP_MODS = server_pstream_conn server_pstream LIBXMLRPC_CLIENTPP_MODS = client client_simple curl libwww wininet pstream LIBXMLRPC_PACKETSOCKET_MODS = packetsocket @@ -58,12 +71,13 @@ TARGET_MODS_PP = \ $(LIBXMLRPCPP_MODS) \ $(LIBXMLRPC_SERVERPP_MODS) \ $(LIBXMLRPC_SERVER_ABYSSPP_MODS) \ + $(LIBXMLRPC_SERVER_CGIPP_MODS) \ $(LIBXMLRPC_SERVER_PSTREAMPP_MODS) \ $(LIBXMLRPC_CLIENTPP_MODS) \ $(LIBXMLRPC_PACKETSOCKET_MODS) \ OMIT_CPP_LIB_RULES = Y -MAJ=4 +MAJ = 7 # Major number of shared libraries in this directory include $(SRCDIR)/common.mk @@ -104,63 +118,120 @@ all: \ # shlibfn generates e.g. libxmlrpc.so.3.1 # shliblefn generates e.g. libxmlrpc.so -LIBXMLRPC_CPP = $(call shlibfn, libxmlrpc_cpp) +LIBXMLRPC_CPP_SH = $(call shlibfn, libxmlrpc_cpp) -$(LIBXMLRPC_CPP): XmlRpcCpp.osh -$(LIBXMLRPC_CPP): LIBOBJECTS = XmlRpcCpp.osh +$(LIBXMLRPC_CPP_SH): XmlRpcCpp.osh \ + $(LIBXMLRPC_UTIL) \ + $(LIBXMLRPC) \ + $(LIBXMLRPC_SERVER) \ + $(LIBXMLRPC_UTIL) +$(LIBXMLRPC_CPP_SH): LIBOBJECTS = XmlRpcCpp.osh +$(LIBXMLRPC_CPP_SH): LIBDEP = \ + -Lblddir/src -lxmlrpc_server -lxmlrpc \ + $(XML_PARSER_LIBDEP) \ + -L$(LIBXMLRPC_UTIL_DIR) -lxmlrpc_util -LIBXMLRPCPP = $(call shlibfn, libxmlrpc++) +LIBXMLRPCPP_SH = $(call shlibfn, lib$(LIBXMLRPCPP_NAME)) -$(LIBXMLRPCPP): $(LIBXMLRPCPP_MODS:%=%.osh) \ - $(LIBXMLRPC) -$(LIBXMLRPCPP): LIBOBJECTS = $(LIBXMLRPCPP_MODS:%=%.osh) -$(LIBXMLRPCPP): LIBDEP = -Lblddir/src -lxmlrpc +$(LIBXMLRPCPP_SH): $(LIBXMLRPCPP_MODS:%=%.osh) \ + $(LIBXMLRPC) \ + $(LIBXMLRPC_UTIL) +$(LIBXMLRPCPP_SH): LIBOBJECTS = $(LIBXMLRPCPP_MODS:%=%.osh) +$(LIBXMLRPCPP_SH): LIBDEP = \ + -Lblddir/src -lxmlrpc \ + $(XML_PARSER_LIBDEP) \ + -L$(LIBXMLRPC_UTIL_DIR) -lxmlrpc_util -LIBXMLRPC_SERVERPP = $(call shlibfn, libxmlrpc_server++) -$(LIBXMLRPC_SERVERPP): $(LIBXMLRPC_SERVERPP_MODS:%=%.osh) \ +LIBXMLRPC_SERVERPP_SH = $(call shlibfn, libxmlrpc_server++) + +$(LIBXMLRPC_SERVERPP_SH): $(LIBXMLRPC_SERVERPP_MODS:%=%.osh) \ $(LIBXMLRPC_SERVER) \ + $(call shliblefn, lib$(LIBXMLRPCPP_NAME)) \ + $(LIBXMLRPC_UTIL) \ $(LIBXMLRPC) -$(LIBXMLRPC_SERVERPP): LIBOBJECTS = $(LIBXMLRPC_SERVERPP_MODS:%=%.osh) -$(LIBXMLRPC_SERVERPP): LIBDEP = -Lblddir/src -lxmlrpc_server -lxmlrpc +$(LIBXMLRPC_SERVERPP_SH): LIBOBJECTS = $(LIBXMLRPC_SERVERPP_MODS:%=%.osh) +$(LIBXMLRPC_SERVERPP_SH): LIBDEP = \ + -L. -l$(LIBXMLRPCPP_NAME) \ + -Lblddir/src -lxmlrpc_server -lxmlrpc \ + $(XML_PARSER_LIBDEP) \ + -L$(LIBXMLRPC_UTIL_DIR) -lxmlrpc_util -LIBXMLRPC_SERVER_ABYSSPP = $(call shlibfn, libxmlrpc_server_abyss++) +LIBXMLRPC_SERVER_ABYSSPP_SH = $(call shlibfn, libxmlrpc_server_abyss++) -$(LIBXMLRPC_SERVER_ABYSSPP): $(LIBXMLRPC_SERVER_ABYSSPP_MODS:%=%.osh) \ +$(LIBXMLRPC_SERVER_ABYSSPP_SH): $(LIBXMLRPC_SERVER_ABYSSPP_MODS:%=%.osh) \ $(LIBXMLRPC_ABYSS) \ + $(LIBXMLRPC_SERVER_ABYSS) \ + $(call shliblefn, lib$(LIBXMLRPCPP_NAME)) \ + $(call shlibfn, libxmlrpc_server++) \ + $(LIBXMLRPC_UTIL) \ + $(LIBXMLRPC) +$(LIBXMLRPC_SERVER_ABYSSPP_SH): LIBOBJECTS = $(LIBXMLRPC_SERVER_ABYSSPP_MODS:%=%.osh) +$(LIBXMLRPC_SERVER_ABYSSPP_SH): LIBDEP = \ + -L. -lxmlrpc_server++ -l$(LIBXMLRPCPP_NAME) \ + -Lblddir/src -lxmlrpc_server_abyss -lxmlrpc_server -lxmlrpc \ + $(XML_PARSER_LIBDEP) \ + -L$(LIBXMLRPC_ABYSS_DIR) -lxmlrpc_abyss \ + -L$(LIBXMLRPC_UTIL_DIR) -lxmlrpc_util \ + +LIBXMLRPC_SERVER_CGIPP_SH = $(call shlibfn, libxmlrpc_server_cgi++) + +$(LIBXMLRPC_SERVER_CGIPP_SH): $(LIBXMLRPC_SERVER_CGIPP_MODS:%=%.osh) \ + $(call shliblefn, libxmlrpc_server++) \ + $(call shliblefn, lib$(LIBXMLRPCPP_NAME)) \ $(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_CGIPP_SH): LIBOBJECTS = $(LIBXMLRPC_SERVER_CGIPP_MODS:%=%.osh) +$(LIBXMLRPC_SERVER_CGIPP_SH): LIBDEP = \ + -L. -lxmlrpc_server++ -l$(LIBXMLRPCPP_NAME) \ + -Lblddir/src -lxmlrpc_server -lxmlrpc \ + $(XML_PARSER_LIBDEP) \ + -L$(LIBXMLRPC_UTIL_DIR) -lxmlrpc_util -LIBXMLRPC_SERVER_PSTREAMPP = $(call shlibfn, libxmlrpc_server_pstream++) +LIBXMLRPC_SERVER_PSTREAMPP_SH = $(call shlibfn, libxmlrpc_server_pstream++) -$(LIBXMLRPC_SERVER_PSTREAMPP): $(LIBXMLRPC_SERVER_PSTREAMPP_MODS:%=%.osh) \ +$(LIBXMLRPC_SERVER_PSTREAMPP_SH): $(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) \ + $(call shliblefn, lib$(LIBXMLRPCPP_NAME)) \ + $(call shliblefn, libxmlrpc_packetsocket) \ + $(call shliblefn, libxmlrpc_server++) +$(LIBXMLRPC_SERVER_PSTREAMPP_SH): LIBOBJECTS = $(LIBXMLRPC_SERVER_PSTREAMPP_MODS:%=%.osh) +$(LIBXMLRPC_SERVER_PSTREAMPP_SH): LIBDEP = \ + -L. -lxmlrpc_server++ -l$(LIBXMLRPCPP_NAME) -lxmlrpc_packetsocket \ + -Lblddir/src -lxmlrpc_server -lxmlrpc \ + $(XML_PARSER_LIBDEP) \ + -L$(LIBXMLRPC_UTIL_DIR) -lxmlrpc_util \ + +LIBXMLRPC_CLIENTPP_SH = $(call shlibfn, libxmlrpc_client++) + +$(LIBXMLRPC_CLIENTPP_SH): $(LIBXMLRPC_CLIENTPP_MODS:%=%.osh) \ + $(LIBXMLRPC_UTIL) \ + $(call shliblefn, libxmlrpc_packetsocket) \ + $(LIBXMLRPC) \ + $(call shliblefn, lib$(LIBXMLRPCPP_NAME)) \ $(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_CLIENTPP_SH): LIBOBJECTS = $(LIBXMLRPC_CLIENTPP_MODS:%=%.osh) +$(LIBXMLRPC_CLIENTPP_SH): LIBDEP = \ + -L. -l$(LIBXMLRPCPP_NAME) -lxmlrpc_packetsocket \ + -Lblddir/src -lxmlrpc_client -lxmlrpc \ + $(XML_PARSER_LIBDEP) \ + -L$(LIBXMLRPC_UTIL_DIR) -lxmlrpc_util + +LIBXMLRPC_PACKETSOCKET_SH = $(call shlibfn, libxmlrpc_packetsocket) + +$(LIBXMLRPC_PACKETSOCKET_SH): $(LIBXMLRPC_PACKETSOCKET_MODS:%=%.osh) \ + $(call shliblefn, lib$(LIBXMLRPCPP_NAME)) +$(LIBXMLRPC_PACKETSOCKET_SH): LIBOBJECTS = $(LIBXMLRPC_PACKETSOCKET_MODS:%=%.osh) +$(LIBXMLRPC_PACKETSOCKET_SH): LIBDEP = \ + -L. -l$(LIBXMLRPCPP_NAME) \ + -Lblddir/src -lxmlrpc \ + $(XML_PARSER_LIBDEP) \ + -L$(LIBXMLRPC_UTIL_DIR) -lxmlrpc_util libxmlrpc_cpp.a: XmlRpcCpp.o libxmlrpc_cpp.a: LIBOBJECTS = XmlRpcCpp.o -libxmlrpc++.a: $(LIBXMLRPCPP_MODS:%=%.o) -libxmlrpc++.a: LIBOBJECTS = $(LIBXMLRPCPP_MODS:%=%.o) +lib$(LIBXMLRPCPP_NAME).a: $(LIBXMLRPCPP_MODS:%=%.o) +lib$(LIBXMLRPCPP_NAME).a: LIBOBJECTS = $(LIBXMLRPCPP_MODS:%=%.o) libxmlrpc_server++.a: $(LIBXMLRPC_SERVERPP_MODS:%=%.o) libxmlrpc_server++.a: LIBOBJECTS = $(LIBXMLRPC_SERVERPP_MODS:%=%.o) @@ -168,6 +239,9 @@ libxmlrpc_server++.a: LIBOBJECTS = $(LIBXMLRPC_SERVERPP_MODS:%=%.o) libxmlrpc_server_abyss++.a: $(LIBXMLRPC_SERVER_ABYSSPP_MODS:%=%.o) libxmlrpc_server_abyss++.a: LIBOBJECTS=$(LIBXMLRPC_SERVER_ABYSSPP_MODS:%=%.o) +libxmlrpc_server_cgi++.a: $(LIBXMLRPC_SERVER_CGIPP_MODS:%=%.o) +libxmlrpc_server_cgi++.a: LIBOBJECTS=$(LIBXMLRPC_SERVER_CGIPP_MODS:%=%.o) + libxmlrpc_server_pstream++.a: $(LIBXMLRPC_SERVER_PSTREAMPP_MODS:%=%.o) libxmlrpc_server_pstream++.a: LIBOBJECTS=$(LIBXMLRPC_SERVER_PSTREAMPP_MODS:%=%.o) @@ -197,11 +271,15 @@ $(LIBXMLRPC_SERVERPP_MODS:%=%.osh): \ INCLUDES = $(SERVER_INCLUDES) $(LIBXMLRPC_SERVER_ABYSSPP_MODS:%=%.o) \ -$(LIBXMLRPC_SERVER_ABYSSPP_MODS:%=%.o): \ +$(LIBXMLRPC_SERVER_ABYSSPP_MODS:%=%.osh): \ + INCLUDES = $(SERVER_INCLUDES) + +$(LIBXMLRPC_SERVER_CGIPP_MODS:%=%.o) \ +$(LIBXMLRPC_SERVER_CGIPP_MODS:%=%.osh): \ INCLUDES = $(SERVER_INCLUDES) $(LIBXMLRPC_SERVER_PSTREAMPP_MODS:%=%.o) \ -$(LIBXMLRPC_SERVER_PSTREAMPP_MODS:%=%.o): \ +$(LIBXMLRPC_SERVER_PSTREAMPP_MODS:%=%.osh): \ INCLUDES = $(SERVER_INCLUDES) $(LIBXMLRPC_CLIENTPP_MODS:%=%.o) \ @@ -212,7 +290,10 @@ $(LIBXMLRPC_PACKETSOCKET_MODS:%=%.o) \ $(LIBXMLRPC_PACKETSOCKET_MODS:%=%.osh): \ INCLUDES = $(BASIC_INCLUDES) -CXXFLAGS = $(CXXFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD) +# in Glibc 2.2 has some failed inlines, so we disable that warning: +$(LIBXMLRPC_PACKETSOCKET_MODS:%=%.o) \ +$(LIBXMLRPC_PACKETSOCKET_MODS:%=%.osh): \ + CFLAGS_LOCAL = -Wno-inline TRANSPORT_CONFIG_USERS = client curl libwww wininet @@ -242,4 +323,4 @@ distclean-local: .PHONY: dep dep: dep-common $(BLDDIR)/transport_config.h -include Makefile.depend +include depend.mk diff --git a/libs/xmlrpc-c/src/cpp/Makefile.depend b/libs/xmlrpc-c/src/cpp/Makefile.depend deleted file mode 100644 index e69de29..0000000 diff --git a/libs/xmlrpc-c/src/cpp/base64.cpp b/libs/xmlrpc-c/src/cpp/base64.cpp index f9c0dac..dd07e1c 100644 --- a/libs/xmlrpc-c/src/cpp/base64.cpp +++ b/libs/xmlrpc-c/src/cpp/base64.cpp @@ -77,7 +77,7 @@ public: assert(bitsInBuffer >= 8); - *outputP = (this->buffer >> (this->bitsInBuffer - 8)) & 0x3f; + *outputP = (this->buffer >> (this->bitsInBuffer - 8)) & 0xff; this->bitsInBuffer -= 8; } diff --git a/libs/xmlrpc-c/src/cpp/client.cpp b/libs/xmlrpc-c/src/cpp/client.cpp index 2dba1bd..4ca8db0 100644 --- a/libs/xmlrpc-c/src/cpp/client.cpp +++ b/libs/xmlrpc-c/src/cpp/client.cpp @@ -26,6 +26,7 @@ using girmem::autoObject; #include "xmlrpc-c/transport.h" #include "xmlrpc-c/base.hpp" #include "xmlrpc-c/xml.hpp" +#include "xmlrpc-c/timeout.hpp" #include "xmlrpc-c/client.hpp" #include "transport_config.h" @@ -127,7 +128,7 @@ carriageParmPtr::operator->() const { carriageParm * carriageParmPtr::get() const { - return dynamic_cast(objectP); + return dynamic_cast(this->objectP); } @@ -371,6 +372,15 @@ xmlTransaction::finishErr(error const&) const { +void +xmlTransaction::progress(struct xmlrpc_progress_data const&) const { + + // This is just the base class method. A derived class may override + // this with something substantial. +} + + + xmlTransactionPtr::xmlTransactionPtr() {} @@ -503,6 +513,18 @@ clientXmlTransport::asyncComplete( void +clientXmlTransport::progress( + struct xmlrpc_call_info * const callInfoP, + struct xmlrpc_progress_data const progressData) { + + xmlTranCtl * const xmlTranCtlP = reinterpret_cast(callInfoP); + + xmlTranCtlP->xmlTranP->progress(progressData); +} + + + +void clientXmlTransport::setInterrupt(int *) { throwf("The client XML transport is not interruptible"); @@ -600,7 +622,7 @@ clientXmlTransport_http::start( this->c_transportP, carriageParmHttpP->c_serverInfoP, tranCtlP->callXmlP, - &this->asyncComplete, + &this->asyncComplete, &this->progress, reinterpret_cast(tranCtlP)); throwIfError(env); @@ -1095,8 +1117,20 @@ rpc::notifyComplete() { } + + +void +rpc::progress(struct xmlrpc_progress_data const&) const { +/*---------------------------------------------------------------------------- + If the user is interested in tracking the progress of the RPC, he will + derive a class from xmlrpc_c::rpc and override this with a progress() + that does something, such as display a progress bar. +-----------------------------------------------------------------------------*/ + +} + value rpc::getResult() const { @@ -1214,6 +1248,15 @@ xmlTransaction_client::finishErr(error const& error) const { +void +xmlTransaction_client::progress( + struct xmlrpc_progress_data const& progressData) const { + + this->tranP->progress(progressData); +} + + + xmlTransaction_clientPtr::xmlTransaction_clientPtr() {} diff --git a/libs/xmlrpc-c/src/cpp/cpptest.cpp b/libs/xmlrpc-c/src/cpp/cpptest.cpp deleted file mode 100644 index 2d07793..0000000 --- a/libs/xmlrpc-c/src/cpp/cpptest.cpp +++ /dev/null @@ -1,1187 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#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 "xmlrpc-c/client.hpp" -#include "xmlrpc-c/client_simple.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. - - -// This is a good place to set a breakpoint. -static 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())); -} - - -#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__, "Didn't get expected error")); \ - } while (0) - -#define trickToStraightenOutEmacsIndentation \ -; - -namespace { -error -fileLineError(string const filename, - unsigned int const lineNumber, - string const description) { - - ostringstream combined; - - combined << filename << ":" << lineNumber << " " << description; - - return error(combined.str()); -} -} // namespace - - - -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 nameMethod : public defaultMethod { - - void - execute(string const& methodName, - xmlrpc_c::paramList const& , // paramList - value * const retvalP) { - - *retvalP = value_string(string("no such method: ") + methodName); - } -}; - - -//========================================================================= -// 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& 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& fault) { - 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& 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& 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()); - } -} - -void test_errors (void) { - // XXX - Test typechecks on get* methods. - // XXX - Test typechceks on array and struct methods. - // XXX - Test bounds checks on arrayGetItem, structGetKeyAndValue. -} - - -static void -testXmlRpcCpp() { -/*---------------------------------------------------------------------------- - Test the legacy XmlRpcCpp.cpp library ------------------------------------------------------------------------------*/ - cout << "Testing XmlRpcCpp library..." << endl; - - test_fault(); - test_env(); - test_value(); - test_errors(); -} - - - -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: - void run(unsigned int const indentation); - - virtual void runtests(unsigned int const) { - throw(error("test suite does not have a runtests() method")); - }; - virtual string suiteName() { - return "unnamed test suite"; - } -}; - -void -testSuite::run(unsigned int const indentation) { - try { - cout << string(indentation*2, ' ') - << "Running " << suiteName() << endl; - runtests(indentation); - } catch (error thisError) { - throw(error(suiteName() + string(" failed. ") + thisError.what())); - } catch (...) { - throw(error(suiteName() + string(" failed. ") + - string("It threw an unexpected type of object"))); - } - cout << string(indentation*2, ' ') - << suiteName() << " tests passed." << endl; -} - - - -class intTestSuite : public testSuite { -public: - virtual string suiteName() { - return "intTestSuite"; - } - virtual void runtests(unsigned int const) { - value_int int1(7); - TEST(static_cast(int1) == 7); - value_int int2(-7); - TEST(static_cast(int2) == -7); - value val1(int1); - TEST(val1.type() == value::TYPE_INT); - value_int int3(val1); - TEST(static_cast(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(double1) == 3.14); - value val1(double1); - TEST(val1.type() == value::TYPE_DOUBLE); - value_double double2(val1); - TEST(static_cast(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(boolean1) == true); - value_boolean boolean2(false); - TEST(static_cast(boolean2) == false); - value val1(boolean1); - TEST(val1.type() == value::TYPE_BOOLEAN); - value_boolean boolean3(val1); - TEST(static_cast(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(datetime1) == testTime); - value_datetime datetime2(testTime); - TEST(static_cast(datetime2) == testTime); - value val1(datetime1); - TEST(val1.type() == value::TYPE_DATETIME); - value_datetime datetime3(val1); - TEST(static_cast(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(string1) == "hello world"); - value_string string2("embedded\0null"); - TEST(static_cast(string2) == "embedded\0null"); - value val1(string1); - TEST(val1.type() == value::TYPE_STRING); - value_string string3(val1); - TEST(static_cast(string3) == "hello world"); - try { - value_string string4(value_int(4)); - TEST_FAILED("invalid cast int-string suceeded"); - } catch (error) {} - } -}; - - - -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 - bytestringData(&bytestringArray[0], &bytestringArray[4]); - value_bytestring bytestring1(bytestringData); - - vector const dataReadBack1( - bytestring1.vectorUcharValue()); - TEST(dataReadBack1 == bytestringData); - value val1(bytestring1); - TEST(val1.type() == value::TYPE_BYTESTRING); - value_bytestring bytestring2(val1); - vector 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 structTestSuite : public testSuite { -public: - virtual string suiteName() { - return "structTestSuite"; - } - virtual void runtests(unsigned int const) { - map structData; - pair member("the_integer", value_int(9)); - structData.insert(member); - - value_struct struct1(structData); - - map dataReadBack(struct1); - - TEST(static_cast(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 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 dataReadBack1(array1.vectorValueValue()); - TEST(dataReadBack1[0].type() == value::TYPE_INT); - TEST(static_cast(value_int(dataReadBack1[0])) == 7); - TEST(dataReadBack1[1].type() == value::TYPE_DOUBLE); - TEST(static_cast(value_double(dataReadBack1[1])) == 2.78); - TEST(dataReadBack1[2].type() == value::TYPE_STRING); - TEST(static_cast(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); - structTestSuite().run(indentation+1); - arrayTestSuite().run(indentation+1); - } -}; - - -namespace { -string const noElementFoundXml( - "\r\n" - "\r\n" - "\r\n" - "\r\n" - "faultCode\r\n" - "-503\r\n" - "faultString\r\n" - "Call is not valid XML. " - "no element found\r\n" - "\r\n" - "\r\n" - "\r\n" - ); - -string const sampleAddGoodCallXml( - "\r\n" - "\r\n" - "sample.add\r\n" - "\r\n" - "5\r\n" - "7\r\n" - "\r\n" - "\r\n" - ); - -string const sampleAddGoodResponseXml( - "\r\n" - "\r\n" - "\r\n" - "12\r\n" - "\r\n" - "\r\n" - ); - - -string const sampleAddBadCallXml( - "\r\n" - "\r\n" - "sample.add\r\n" - "\r\n" - "5\r\n" - "\r\n" - "\r\n" - ); - -string const sampleAddBadResponseXml( - "\r\n" - "\r\n" - "\r\n" - "\r\n" - "faultCode\r\n" - "-501\r\n" - "faultString\r\n" - "Not enough parameters\r\n" - "\r\n" - "\r\n" - "\r\n" - ); - - -string const nonexistentMethodCallXml( - "\r\n" - "\r\n" - "nosuchmethod\r\n" - "\r\n" - "5\r\n" - "7\r\n" - "\r\n" - "\r\n" - ); - -string const nonexistentMethodYesDefResponseXml( - "\r\n" - "\r\n" - "\r\n" - "no such method: nosuchmethod" - "\r\n" - "\r\n" - "\r\n" - ); - -string const nonexistentMethodNoDefResponseXml( - "\r\n" - "\r\n" - "\r\n" - "\r\n" - "faultCode\r\n" - "-506\r\n" - "faultString\r\n" - "Method 'nosuchmethod' not defined" - "\r\n" - "\r\n" - "\r\n" - "\r\n" - ); - -} // namespace - - -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 - bytestringData(&bytestringArray[0], &bytestringArray[4]); - paramList1.add(value_bytestring(bytestringData)); - vector 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 structData; - pair member("the_integer", value_int(9)); - structData.insert(member); - paramList1.add(value_struct(structData)); - paramList1.add(value_nil()); - - TEST(paramList1.size() == 10); - - 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); - paramList1.verifyEnd(10); - - paramList paramList2(5); - TEST(paramList2.size() == 0); - } -}; - -class registryRegMethodTestSuite : public testSuite { - -public: - virtual string suiteName() { - return "registryRegMethodTestSuite"; - } - virtual void runtests(unsigned int) { - - 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) { - - 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 registryTestSuite : public testSuite { - -public: - virtual string suiteName() { - return "registryTestSuite"; - } - virtual void runtests(unsigned int const indentation) { - - registryRegMethodTestSuite().run(indentation+1); - registryDefaultMethodTestSuite().run(indentation+1); - } -}; - - - -class clientXmlTransportTestSuite : public testSuite { - -public: - virtual string suiteName() { - return "clientXmlTransportTestSuite"; - } - virtual void runtests(unsigned int const) { -#if MUST_BUILD_CURL_CLIENT - clientXmlTransport_curl transportc0; - clientXmlTransport_curl transportc1("eth0"); - clientXmlTransport_curl transportc2("eth0", true); - clientXmlTransport_curl transportc3("eth0", true, true); -#else - EXPECT_ERROR(clientXmlTransport_curl transportc0;); - EXPECT_ERROR(clientXmlTransport_curl transportc1("eth0");); - EXPECT_ERROR(clientXmlTransport_curl transportc0("eth0", true);); - EXPECT_ERROR(clientXmlTransport_curl transportc0("eth0", true, true);); -#endif - -#if MUST_BUILD_LIBWWW_CLIENT - clientXmlTransport_libwww transportl0; - clientXmlTransport_libwww transportl1("getbent"); - clientXmlTransport_libwww transportl2("getbent", "1.0"); -#else - EXPECT_ERROR(clientXmlTransport_libwww transportl0;); - EXPECT_ERROR(clientXmlTransport_libwww transportl1("getbent");); - EXPECT_ERROR(clientXmlTransport_libwww transportl2("getbent", "1.0");); -#endif -#if MUST_BUILD_WININET_CLIENT - clientXmlTransport_wininet transportw0; - clientXmlTransport_wininet transportw1(true); -#else - EXPECT_ERROR(clientXmlTransport_wininet transportw0;); - EXPECT_ERROR(clientXmlTransport_wininet transportw1(true);); -#endif - } -}; - - - -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 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(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); - - TEST(rpcSampleAdd1P->isFinished()); - TEST(rpcSampleAdd1P->isSuccessful()); - value_int const result1(rpcSampleAdd1P->getResult()); - TEST(static_cast(result1) == 12); - - TEST(rpcSampleAdd2P->isFinished()); - TEST(rpcSampleAdd1P->isSuccessful()); - value_int const result2(rpcSampleAdd2P->getResult()); - TEST(static_cast(result2) == 20); - - EXPECT_ERROR(clientDirect.finishAsync(timeout());); - EXPECT_ERROR(clientDirect.finishAsync(timeout(50));); - } -}; - - - -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()); - EXPECT_ERROR(fault fault0(rpcSampleAddP->getFault());); - value_int const resultDirect(rpcSampleAddP->getResult()); - TEST(static_cast(resultDirect) == 12); - } - { - /* Test a failed RPC */ - rpcPtr const rpcSampleAddP("sample.add", paramListEmpty); - rpcSampleAddP->call(&clientDirect, &carriageParmDirect); - TEST(rpcSampleAddP->isFinished()); - TEST(!rpcSampleAddP->isSuccessful()); - EXPECT_ERROR(value result(rpcSampleAddP->getResult());); - fault const fault0(rpcSampleAddP->getFault()); - TEST(fault0.getCode() == fault::CODE_TYPE); - } - - clientDirectAsyncTestSuite().run(indentation+1); - } -}; - - - -class clientTestSuite : public testSuite { - -public: - virtual string suiteName() { - return "clientTestSuite"; - } - virtual void runtests(unsigned int const indentation) { - - clientDirectTestSuite().run(indentation+1); - - clientXmlTransportTestSuite().run(indentation+1); - - carriageParm_http0 carriageParm1("http://suckthis.comm"); - carriageParm_curl0 carriageParm2("http://suckthis.comm"); - carriageParm_libwww0 carriageParm3("http://suckthis.comm"); - carriageParm_wininet0 carriageParm4("http://suckthis.comm"); - -#if MUST_BUILD_CURL_CLIENT - clientXmlTransport_curl transportc0; - client_xml client0(&transportc0); - connection connection0(&client0, &carriageParm1); - - paramList paramList0; - - rpcPtr rpc0P("blowme", paramList0); - - // This fails because RPC has not been executed - EXPECT_ERROR(value result(rpc0P->getResult());); - - // This fails because server doesn't exist - EXPECT_ERROR(rpc0P->call(&client0, &carriageParm2);); - - rpcPtr rpc1P("blowme", paramList0); - // This fails because server doesn't exist - EXPECT_ERROR(rpc1P->call(connection0);); - - rpcPtr rpc2P("blowme", paramList0); - - rpc2P->start(&client0, &carriageParm2); - - client0.finishAsync(timeout()); - - // This fails because the RPC failed because server doesn't exist - EXPECT_ERROR(value result(rpc2P->getResult());); - - // This fails because the RPC has already been executed - EXPECT_ERROR(rpc2P->start(connection0);); - - rpcPtr rpc3P("blowme", paramList0); - rpc3P->start(connection0); - - client0.finishAsync(timeout()); - - // This fails because the RPC failed because server doesn't exist - EXPECT_ERROR(value result(rpc3P->getResult());); -#endif - clientSimpleTestSuite().run(indentation+1); - } -}; - -//========================================================================= -// 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); - clientTestSuite().run(0); - - testXmlRpcCpp(); - - testsPassed = true; - } catch (error thisError) { - cout << "Unexpected error thrown: " << thisError.what() << endl; - testsPassed = false; - } catch (XmlRpcFault& 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; -} diff --git a/libs/xmlrpc-c/src/cpp/curl.cpp b/libs/xmlrpc-c/src/cpp/curl.cpp index 6181929..5751385 100644 --- a/libs/xmlrpc-c/src/cpp/curl.cpp +++ b/libs/xmlrpc-c/src/cpp/curl.cpp @@ -127,27 +127,93 @@ carriageParm_curl0Ptr::operator->() const { -clientXmlTransport_curl::constrOpt::constrOpt() { +struct clientXmlTransport_curl::constrOpt_impl { + + constrOpt_impl(); + + struct { + std::string network_interface; + bool no_ssl_verifypeer; + bool no_ssl_verifyhost; + bool dont_advertise; + 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; + std::string proxy; + unsigned int proxy_auth; + unsigned int proxy_port; + std::string proxy_userpwd; + xmlrpc_httpproxytype proxy_type; + } value; + struct { + bool network_interface; + bool no_ssl_verifypeer; + bool no_ssl_verifyhost; + bool dont_advertise; + 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; + bool proxy; + bool proxy_auth; + bool proxy_port; + bool proxy_userpwd; + bool proxy_type; + } present; +}; + +clientXmlTransport_curl::constrOpt_impl::constrOpt_impl() { 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.dont_advertise = 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; + present.sslversion = false; + present.cainfo = false; + present.capath = false; + present.randomfile = false; + present.egdsocket = false; + present.ssl_cipher_list = false; + present.timeout = false; + present.proxy = false; + present.proxy_port = false; + present.proxy_auth = false; + present.proxy_userpwd = false; + present.proxy_type = false; } @@ -155,14 +221,15 @@ clientXmlTransport_curl::constrOpt::constrOpt() { #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; \ + this->implP->value.OPTION_NAME = arg; \ + this->implP->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(dont_advertise, bool); DEFINE_OPTION_SETTER(user_agent, string); DEFINE_OPTION_SETTER(ssl_cert, string); DEFINE_OPTION_SETTER(sslcerttype, string); @@ -179,13 +246,41 @@ DEFINE_OPTION_SETTER(randomfile, string); DEFINE_OPTION_SETTER(egdsocket, string); DEFINE_OPTION_SETTER(ssl_cipher_list, string); DEFINE_OPTION_SETTER(timeout, unsigned int); +DEFINE_OPTION_SETTER(proxy, string); +DEFINE_OPTION_SETTER(proxy_port, unsigned int); +DEFINE_OPTION_SETTER(proxy_auth, unsigned int); +DEFINE_OPTION_SETTER(proxy_userpwd, string); +DEFINE_OPTION_SETTER(proxy_type, xmlrpc_httpproxytype); #undef DEFINE_OPTION_SETTER +clientXmlTransport_curl::constrOpt::constrOpt() { + + this->implP = new clientXmlTransport_curl::constrOpt_impl(); +} + + + +clientXmlTransport_curl::constrOpt::~constrOpt() { + + delete(this->implP); +} + + + +clientXmlTransport_curl::constrOpt::constrOpt(constrOpt& arg) { + + this->implP = new constrOpt_impl(*arg.implP); +} + + + #if MUST_BUILD_CURL_CLIENT void -clientXmlTransport_curl::initialize(constrOpt const& opt) { +clientXmlTransport_curl::initialize(constrOpt const& optExt) { + constrOpt_impl const opt(*optExt.implP); + struct xmlrpc_curl_xportparms transportParms; transportParms.network_interface = opt.present.network_interface ? @@ -194,6 +289,8 @@ clientXmlTransport_curl::initialize(constrOpt const& opt) { opt.value.no_ssl_verifypeer : false; transportParms.no_ssl_verifyhost = opt.present.no_ssl_verifyhost ? opt.value.no_ssl_verifyhost : false; + transportParms.dont_advertise = opt.present.dont_advertise ? + opt.value.dont_advertise : false; transportParms.user_agent = opt.present.user_agent ? opt.value.user_agent.c_str() : NULL; transportParms.ssl_cert = opt.present.ssl_cert ? @@ -226,6 +323,16 @@ clientXmlTransport_curl::initialize(constrOpt const& opt) { opt.value.ssl_cipher_list.c_str() : NULL; transportParms.timeout = opt.present.timeout ? opt.value.timeout : 0; + transportParms.proxy = opt.present.proxy ? + opt.value.proxy.c_str() : NULL; + transportParms.proxy_port = opt.present.proxy_port ? + opt.value.proxy_port : 0; + transportParms.proxy_auth = opt.present.proxy_auth ? + opt.value.proxy_auth : XMLRPC_HTTPAUTH_NONE; + transportParms.proxy_userpwd = opt.present.proxy_userpwd ? + opt.value.proxy_userpwd.c_str() : NULL; + transportParms.proxy_type = opt.present.proxy_type ? + opt.value.proxy_type : XMLRPC_HTTPPROXY_HTTP; this->c_transportOpsP = &xmlrpc_curl_transport_ops; @@ -233,7 +340,7 @@ clientXmlTransport_curl::initialize(constrOpt const& opt) { xmlrpc_curl_transport_ops.create( &env.env_c, 0, "", "", - &transportParms, XMLRPC_CXPSIZE(timeout), + &transportParms, XMLRPC_CXPSIZE(dont_advertise), &this->c_transportP); if (env.env_c.fault_occurred) diff --git a/libs/xmlrpc-c/src/cpp/env_wrap.hpp b/libs/xmlrpc-c/src/cpp/env_wrap.hpp index 0172f2b..f31cb0e 100644 --- a/libs/xmlrpc-c/src/cpp/env_wrap.hpp +++ b/libs/xmlrpc-c/src/cpp/env_wrap.hpp @@ -1,11 +1,12 @@ #ifndef ENV_INT_HPP_INCLUDED #define ENV_INT_HPP_INCLUDED +#include "xmlrpc-c/c_util.h" #include "xmlrpc-c/util.h" namespace xmlrpc_c { -class env_wrap { +class XMLRPC_DLLEXPORT env_wrap { /*---------------------------------------------------------------------------- A wrapper to assist in using the Xmlrpc-c C libraries in Xmlrpc-c C++ code. diff --git a/libs/xmlrpc-c/src/cpp/libwww.cpp b/libs/xmlrpc-c/src/cpp/libwww.cpp index 1e2998c..3a2e9a6 100644 --- a/libs/xmlrpc-c/src/cpp/libwww.cpp +++ b/libs/xmlrpc-c/src/cpp/libwww.cpp @@ -141,7 +141,8 @@ clientXmlTransport_libwww::clientXmlTransport_libwww( } #else // MUST_BUILD_LIBWWW_CLIENT - clientXmlTransport_libwww::clientXmlTransport_libwww(string, string) { + clientXmlTransport_libwww::clientXmlTransport_libwww(string const, + string const) { throw(error("There is no Libwww client XML transport " "in this XML-RPC client library")); diff --git a/libs/xmlrpc-c/src/cpp/packetsocket.cpp b/libs/xmlrpc-c/src/cpp/packetsocket.cpp index c984215..28fd09f 100644 --- a/libs/xmlrpc-c/src/cpp/packetsocket.cpp +++ b/libs/xmlrpc-c/src/cpp/packetsocket.cpp @@ -37,15 +37,15 @@ 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. + You can create a packet socket from a POSIX stream socket or a + Windows emulation of one. 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 "xmlrpc_config.h" #include #include @@ -54,10 +54,18 @@ #include #include #include -#include + #include #include -#include +#if MSVCRT +# include +# include +#else +# include +# include +# include +#endif + #include #include "c_util.h" @@ -67,10 +75,266 @@ using girerr::throwf; #include "xmlrpc-c/packetsocket.hpp" +using namespace std; #define ESC 0x1B // ASCII Escape character #define ESC_STR "\x1B" +class XMLRPC_DLLEXPORT socketx { + +public: + socketx(int const sockFd); + + ~socketx(); + + void + waitForReadable() const; + + void + waitForWritable() const; + + void + read(unsigned char * const buffer, + size_t const bufferSize, + bool * const wouldblockP, + size_t * const bytesReadP) const; + + void + writeWait(const unsigned char * const data, + size_t const size) const; +private: + int fd; + bool fdIsBorrowed; +}; + + + +/* Sockets are similar, but not identical between Unix and Windows. + Some Unix socket functions appear to be available on Windows (a + Unix compatibility feature), but work only for file descriptor + numbers < 32, so we don't use those. +*/ + +socketx::socketx(int const sockFd) { +#if MSVCRT + // We don't have any way to duplicate; we'll just have to borrow. + this->fdIsBorrowed = true; + this->fd = sockFd; + u_long iMode(1); // Nonblocking mode yes + ioctlsocket(this->fd, FIONBIO, &iMode); // Make socket nonblocking +#else + this->fdIsBorrowed = false; + + int dupRc; + + dupRc = dup(sockFd); + + if (dupRc < 0) + throwf("dup() failed. errno=%d (%s)", errno, strerror(errno)); + else { + this->fd = dupRc; + fcntl(this->fd, F_SETFL, O_NONBLOCK); // Make socket nonblocking + } +#endif +} + + + +socketx::~socketx() { + + if (!this->fdIsBorrowed) { +#if MSVCRT + ::closesocket(SOCKET(this->fd)); +#else + close(this->fd); +#endif + } +} + + + +void +socketx::waitForReadable() const { + /* Return when there is something to read from the socket + (an EOF indication counts as something to read). Also + return if there is a signal (handled, of course). Rarely, + it is OK to return when there isn't anything to read. + */ +#if MSVCRT + // poll() is not available; settle for select(). + // Starting in Windows Vista, there is WSApoll() + fd_set rd_set; + FD_ZERO(&rd_set); + FD_SET(this->fd, &rd_set); + + select(this->fd + 1, &rd_set, 0, 0, 0); +#else + // poll() beats select() because higher file descriptor numbers + // work. + struct pollfd pollfds[1]; + + pollfds[0].fd = this->fd; + pollfds[0].events = POLLIN; + + poll(pollfds, ARRAY_SIZE(pollfds), -1); +#endif +} + + + +void +socketx::waitForWritable() const { + /* Return when socket is able to be written to. */ +#if MSVCRT + fd_set wr_set; + FD_ZERO(&wr_set); + FD_SET(this->fd, &wr_set); + + select(this->fd + 1, 0, &wr_set, 0, 0); +#else + struct pollfd pollfds[1]; + + pollfds[0].fd = this->fd; + pollfds[0].events = POLLOUT; + + poll(pollfds, ARRAY_SIZE(pollfds), -1); +#endif +} + + + +static bool +wouldBlock() { +/*---------------------------------------------------------------------------- + The most recently executed system socket function, which we assume failed, + failed because the situation was such that it wanted to block, but the + socket had the nonblocking option. +-----------------------------------------------------------------------------*/ +#if MSVCRT + return (WSAGetLastError() == WSAEWOULDBLOCK || + WSAGetLastError() == WSAEINPROGRESS); +#else + /* EWOULDBLOCK and EAGAIN are normally synonyms, but POSIX allows them + to be separate and allows the OS to return whichever one it wants + for the "would block" condition. + */ + return (errno == EWOULDBLOCK || errno == EAGAIN); +#endif +} + + + +static string +lastErrorDesc() { +/*---------------------------------------------------------------------------- + A description suitable for an error message of why the most recent + failed system socket function failed. +-----------------------------------------------------------------------------*/ + ostringstream msg; +#if MSVCRT + int const lastError = WSAGetLastError(); + msg << "winsock error code " << lastError << " " + << "(" << strerror(lastError) << ")"; +#else + msg << "errno = " << errno << ", (" << strerror(errno); +#endif + return msg.str(); +} + + + + +void +socketx::read(unsigned char * const buffer, + size_t const bufferSize, + bool * const wouldblockP, + size_t * const bytesReadP) const { + + int rc; + + // We've seen a Windows library whose recv() expects a char * buffer + // (cf POSIX void *), so we cast. + + rc = recv(this->fd, (char *)buffer, bufferSize, 0); + + if (rc < 0) { + if (wouldBlock()) { + *wouldblockP = true; + *bytesReadP = 0; + } else + throwf("read() of socket failed with %s", lastErrorDesc().c_str()); + } else { + *wouldblockP = false; + *bytesReadP = rc; + } +} + + + +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) { + int rc; + + rc = send(fd, (char*)&data[totalBytesWritten], + size - totalBytesWritten, 0); + + if (rc < 0) { + if (wouldBlock()) + full = true; + else + throwf("write() of socket failed with %s", + lastErrorDesc().c_str()); + } else if (rc == 0) + throwf("Zero byte short write."); + else { + size_t const bytesWritten(rc); + totalBytesWritten += bytesWritten; + } + } + *bytesWrittenP = totalBytesWritten; +} + + + +void +socketx::writeWait(const unsigned char * const data, + size_t const size) const { +/*---------------------------------------------------------------------------- + Write the 'size' bytes at 'data' to the socket. 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(this->fd, data, size, &totalBytesWritten); + + while (totalBytesWritten < size) { + this->waitForWritable(); + + size_t bytesWritten; + + writeFd(this->fd, &data[totalBytesWritten], size - totalBytesWritten, + &bytesWritten); + + totalBytesWritten += bytesWritten; + } +} + + + namespace xmlrpc_c { @@ -86,7 +350,7 @@ packet::initialize(const unsigned char * const data, this->bytes = reinterpret_cast(malloc(dataLength)); if (this->bytes == NULL) - throwf("Can't get storage for a %u-byte packet.", dataLength); + throwf("Can't get storage for a %u-byte packet", (unsigned)dataLength); this->allocSize = dataLength; @@ -138,7 +402,7 @@ packet::addData(const unsigned char * const data, realloc(this->bytes, neededSize)); if (this->bytes == NULL) - throwf("Can't get storage for a %u-byte packet.", neededSize); + throwf("Can't get storage for a %u-byte packet", (unsigned)neededSize); memcpy(this->bytes + this->length, data, dataLength); @@ -166,33 +430,83 @@ packetPtr::operator->() const { -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); +class packetSocket_impl { - this->eof = false; - } -} +public: + packetSocket_impl(int const sockFd); + void + writeWait(packetPtr const& packetP) const; + void + read(bool * const eofP, + bool * const gotPacketP, + packetPtr * const packetPP); -packetSocket::~packetSocket() { + void + readWait(volatile const int * const interruptP, + bool * const eofP, + bool * const gotPacketP, + packetPtr * const packetPP); - close(this->sockFd); +private: + socketx sock; + // 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 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 + 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(); +}; + + + +packetSocket_impl::packetSocket_impl(int const sockFd) : + sock(sockFd) { + + this->inEscapeSeq = false; + this->inPacket = false; + this->escAccum.len = 0; + this->eof = false; } @@ -229,106 +543,27 @@ packetSocket::~packetSocket() { -----------------------------------------------------------------------------*/ -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 { +packetSocket_impl::writeWait(packetPtr const& packetP) const { const unsigned char * const packetStart( reinterpret_cast(ESC_STR "PKT")); const unsigned char * const packetEnd( reinterpret_cast(ESC_STR "END")); - writeFdWait(this->sockFd, packetStart, 4); - - writeFdWait(this->sockFd, packetP->getBytes(), packetP->getLength()); + this->sock.writeWait(packetStart, 4); - writeFdWait(this->sockFd, packetEnd, 4); -} - - - -static ssize_t -libc_read(int const fd, - void * const buf, - size_t const count) { + this->sock.writeWait(packetP->getBytes(), packetP->getLength()); - return read(fd, buf, count); + this->sock.writeWait(packetEnd, 4); } void -packetSocket::takeSomeEscapeSeq(const unsigned char * const buffer, - size_t const length, - size_t * const bytesTakenP) { +packetSocket_impl::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 @@ -378,9 +613,9 @@ packetSocket::takeSomeEscapeSeq(const unsigned char * const buffer, void -packetSocket::takeSomePacket(const unsigned char * const buffer, - size_t const length, - size_t * const bytesTakenP) { +packetSocket_impl::takeSomePacket(const unsigned char * const buffer, + size_t const length, + size_t * const bytesTakenP) { assert(!this->inEscapeSeq); @@ -408,7 +643,7 @@ packetSocket::takeSomePacket(const unsigned char * const buffer, void -packetSocket::verifyNothingAccumulated() { +packetSocket_impl::verifyNothingAccumulated() { /*---------------------------------------------------------------------------- Throw an error if there is a partial packet accumulated. -----------------------------------------------------------------------------*/ @@ -419,14 +654,14 @@ packetSocket::verifyNothingAccumulated() { 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()); + "end of packet)", (unsigned)this->packetAccumP->getLength()); } void -packetSocket::processBytesRead(const unsigned char * const buffer, - size_t const bytesRead) { +packetSocket_impl::processBytesRead(const unsigned char * const buffer, + size_t const bytesRead) { unsigned int cursor; // Cursor into buffer[] cursor = 0; @@ -456,7 +691,7 @@ packetSocket::processBytesRead(const unsigned char * const buffer, void -packetSocket::readFromFile() { +packetSocket_impl::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. @@ -473,19 +708,11 @@ packetSocket::readFromFile() { while (this->readBuffer.empty() && !this->eof && !wouldblock) { unsigned char buffer[4096]; - ssize_t rc; + size_t bytesRead; - 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); + this->sock.read(buffer, sizeof(buffer), &wouldblock, &bytesRead); + if (!wouldblock) { if (bytesRead == 0) { this->eof = true; this->verifyNothingAccumulated(); @@ -498,9 +725,9 @@ packetSocket::readFromFile() { void -packetSocket::read(bool * const eofP, - bool * const gotPacketP, - packetPtr * const packetPP) { +packetSocket_impl::read(bool * const eofP, + bool * const gotPacketP, + packetPtr * const packetPP) { /*---------------------------------------------------------------------------- Read one packet from the socket, through the internal packet buffer. @@ -535,10 +762,10 @@ packetSocket::read(bool * const eofP, void -packetSocket::readWait(volatile const int * const interruptP, - bool * const eofP, - bool * const gotPacketP, - packetPtr * const packetPP) { +packetSocket_impl::readWait(volatile const int * const interruptP, + bool * const eofP, + bool * const gotPacketP, + packetPtr * const packetPP) { bool gotPacket; bool eof; @@ -547,13 +774,8 @@ packetSocket::readWait(volatile const int * const interruptP, 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->sock.waitForReadable(); this->read(&eof, &gotPacket, packetPP); } @@ -563,6 +785,49 @@ packetSocket::readWait(volatile const int * const interruptP, +packetSocket::packetSocket(int const sockFd) { + + this->implP = new packetSocket_impl(sockFd); +} + + + +packetSocket::~packetSocket() { + + delete(this->implP); +} + + + +void +packetSocket::writeWait(packetPtr const& packetP) const { + + implP->writeWait(packetP); +} + + + +void +packetSocket::read(bool * const eofP, + bool * const gotPacketP, + packetPtr * const packetPP) { + + this->implP->read(eofP, gotPacketP, packetPP); +} + + + +void +packetSocket::readWait(volatile const int * const interruptP, + bool * const eofP, + bool * const gotPacketP, + packetPtr * const packetPP) { + + this->implP->readWait(interruptP, eofP, gotPacketP, packetPP); +} + + + void packetSocket::readWait(volatile const int * const interruptP, bool * const eofP, @@ -570,7 +835,7 @@ packetSocket::readWait(volatile const int * const interruptP, bool gotPacket; - this->readWait(interruptP, eofP, &gotPacket, packetPP); + this->implP->readWait(interruptP, eofP, &gotPacket, packetPP); if (!gotPacket) throwf("Packet read was interrupted"); diff --git a/libs/xmlrpc-c/src/cpp/pstream.cpp b/libs/xmlrpc-c/src/cpp/pstream.cpp index 6a75160..fd2a31d 100644 --- a/libs/xmlrpc-c/src/cpp/pstream.cpp +++ b/libs/xmlrpc-c/src/cpp/pstream.cpp @@ -37,9 +37,24 @@ using namespace std; namespace xmlrpc_c { -clientXmlTransport_pstream::constrOpt::constrOpt() { - present.fd = false; +struct clientXmlTransport_pstream::constrOpt_impl { + + constrOpt_impl(); + + struct { + int fd; + } value; + struct { + bool fd; + } present; +}; + + + +clientXmlTransport_pstream::constrOpt_impl::constrOpt_impl() { + + this->present.fd = false; } @@ -47,8 +62,8 @@ clientXmlTransport_pstream::constrOpt::constrOpt() { #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; \ + this->implP->value.OPTION_NAME = arg; \ + this->implP->present.OPTION_NAME = true; \ return *this; \ } @@ -58,7 +73,31 @@ DEFINE_OPTION_SETTER(fd, xmlrpc_socket); -clientXmlTransport_pstream::clientXmlTransport_pstream(constrOpt const& opt) { +clientXmlTransport_pstream::constrOpt::constrOpt() { + + this->implP = new clientXmlTransport_pstream::constrOpt_impl(); +} + + + +clientXmlTransport_pstream::constrOpt::~constrOpt() { + + delete(this->implP); +} + + + +clientXmlTransport_pstream::constrOpt::constrOpt(constrOpt& arg) { + + this->implP = new clientXmlTransport_pstream::constrOpt_impl(*arg.implP); +} + + + +clientXmlTransport_pstream::clientXmlTransport_pstream( + constrOpt const& optExt) { + + constrOpt_impl const opt(*optExt.implP); if (!opt.present.fd) throwf("You must provide a 'fd' constructor option."); diff --git a/libs/xmlrpc-c/src/cpp/registry.cpp b/libs/xmlrpc-c/src/cpp/registry.cpp index 26bfa95..9b3bc3e 100644 --- a/libs/xmlrpc-c/src/cpp/registry.cpp +++ b/libs/xmlrpc-c/src/cpp/registry.cpp @@ -59,6 +59,24 @@ methodPtr::operator->() const { +method2::method2() {} + + + +method2::~method2() {} + + +void +method2::execute(xmlrpc_c::paramList const& paramList, + xmlrpc_c::value * const resultP) { + + callInfo const nullCallInfo; + + execute(paramList, &nullCallInfo, resultP); +} + + + defaultMethod::~defaultMethod() {} @@ -90,7 +108,32 @@ defaultMethodPtr::get() const { -registry::registry() { +struct registry_impl { + + xmlrpc_registry * c_registryP; + // Pointer to the C registry object we use to implement this + // object. + + std::list 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. + + 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. + + registry_impl(); + + ~registry_impl(); +}; + + + +registry_impl::registry_impl() { env_wrap env; @@ -101,12 +144,25 @@ registry::registry() { -registry::~registry(void) { +registry_impl::~registry_impl() { xmlrpc_registry_free(this->c_registryP); } +registry::registry() { + + this->implP = new registry_impl(); +} + + + +registry::~registry(void) { + + delete(this->implP); +} + + registryPtr::registryPtr() {} @@ -173,7 +229,8 @@ pListFromXmlrpcArray(xmlrpc_value * const arrayP) { static xmlrpc_value * c_executeMethod(xmlrpc_env * const envP, xmlrpc_value * const paramArrayP, - void * const methodPtr) { + void * const methodPtr, + void * const callInfoPtr) { /*---------------------------------------------------------------------------- This is a function designed to be called via a C registry to execute an XML-RPC method, but use a C++ method object to do the @@ -188,18 +245,25 @@ c_executeMethod(xmlrpc_env * const envP, encounter in processing the result it returns, and turn it into an XML-RPC method failure. This will cause a leak if the execute() method actually created a result, since it will not get destroyed. + + This function is of type 'xmlrpc_method2'. -----------------------------------------------------------------------------*/ - xmlrpc_c::method * const methodP = - static_cast(methodPtr); - xmlrpc_c::paramList const paramList(pListFromXmlrpcArray(paramArrayP)); + method * const methodP(static_cast(methodPtr)); + paramList const paramList(pListFromXmlrpcArray(paramArrayP)); + callInfo * const callInfoP(static_cast(callInfoPtr)); xmlrpc_value * retval; + retval = NULL; // silence used-before-set warning try { - xmlrpc_c::value result; + value result; try { - methodP->execute(paramList, &result); + method2 * const method2P(dynamic_cast(methodP)); + if (method2P) + method2P->execute(paramList, callInfoP, &result); + else + methodP->execute(paramList, &result); } catch (xmlrpc_c::fault const& fault) { xmlrpc_env_set_fault(envP, fault.getCode(), fault.getDescription().c_str()); @@ -256,6 +320,7 @@ c_executeDefaultMethod(xmlrpc_env * const envP, paramList const paramList(pListFromXmlrpcArray(paramArrayP)); xmlrpc_value * retval; + retval = NULL; // silence used-before-set warning try { xmlrpc_c::value result; @@ -296,15 +361,22 @@ void registry::addMethod(string const name, methodPtr const methodP) { - this->methodList.push_back(methodP); + this->implP->methodList.push_back(methodP); + struct xmlrpc_method_info3 methodInfo; env_wrap env; + + methodInfo.methodName = name.c_str(); + methodInfo.methodFunction = &c_executeMethod; + methodInfo.serverInfo = methodP.get(); + methodInfo.stackSize = 0; + string const signatureString(methodP->signature()); + methodInfo.signatureString = signatureString.c_str(); + string const help(methodP->help()); + methodInfo.help = help.c_str(); - xmlrpc_registry_add_method_w_doc( - &env.env_c, this->c_registryP, NULL, - name.c_str(), &c_executeMethod, - (void*) methodP.get(), - methodP->signature().c_str(), methodP->help().c_str()); + xmlrpc_registry_add_method3(&env.env_c, this->implP->c_registryP, + &methodInfo); throwIfError(env); } @@ -314,12 +386,12 @@ registry::addMethod(string const name, void registry::setDefaultMethod(defaultMethodPtr const methodP) { - this->defaultMethodP = methodP; + this->implP->defaultMethodP = methodP; env_wrap env; xmlrpc_registry_set_default_method( - &env.env_c, this->c_registryP, + &env.env_c, this->implP->c_registryP, &c_executeDefaultMethod, (void*) methodP.get()); throwIfError(env); @@ -330,7 +402,7 @@ registry::setDefaultMethod(defaultMethodPtr const methodP) { void registry::disableIntrospection() { - xmlrpc_registry_disable_introspection(this->c_registryP); + xmlrpc_registry_disable_introspection(this->implP->c_registryP); } @@ -362,7 +434,7 @@ registry::setShutdown(const registry::shutdown * const shutdownP) { void * const context(const_cast(shutdownP)); - xmlrpc_registry_set_shutdown(this->c_registryP, + xmlrpc_registry_set_shutdown(this->implP->c_registryP, &shutdownServer, context); } @@ -374,9 +446,49 @@ registry::setDialect(xmlrpc_dialect const dialect) { env_wrap env; - xmlrpc_registry_set_dialect(&env.env_c, this->c_registryP, dialect); + xmlrpc_registry_set_dialect(&env.env_c, this->implP->c_registryP, dialect); + + throwIfError(env); +} + + + +void +registry::processCall(string const& callXml, + const callInfo * const callInfoP, + string * const responseXmlP) const { +/*---------------------------------------------------------------------------- + Process an XML-RPC call whose XML is 'callXml'. + + Return the response XML as *responseXmlP. + + If we are unable to execute the call, we throw an error. But if + the call executes and the method merely fails in an XML-RPC sense, we + don't. In that case, *responseXmlP indicates the failure. +-----------------------------------------------------------------------------*/ + env_wrap env; + xmlrpc_mem_block * response; + + // 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 + // the result into XML and return it as *responseXmlP. It will + // also have to execute system methods (e.g. introspection) + // itself. This will be more or less like what + // xmlrpc_registry_process_call() does. + + xmlrpc_registry_process_call2( + &env.env_c, this->implP->c_registryP, + callXml.c_str(), callXml.length(), + const_cast(callInfoP), + &response); throwIfError(env); + + *responseXmlP = string(XMLRPC_MEMBLOCK_CONTENTS(char, response), + XMLRPC_MEMBLOCK_SIZE(char, response)); + + xmlrpc_mem_block_free(response); } @@ -405,7 +517,7 @@ registry::processCall(string const& callXml, // xmlrpc_registry_process_call() does. output = xmlrpc_registry_process_call( - &env.env_c, this->c_registryP, NULL, + &env.env_c, this->implP->c_registryP, NULL, callXml.c_str(), callXml.length()); throwIfError(env); @@ -416,12 +528,24 @@ registry::processCall(string const& callXml, xmlrpc_mem_block_free(output); } -xmlrpc_registry * -registry::c_registry() const { - return this->c_registryP; + +#define PROCESS_CALL_STACK_SIZE 256 + // This is our liberal estimate of how much stack space + // registry::processCall() needs, not counting what + // the call the to C registry uses. + + + +size_t +registry::maxStackSize() const { + + return xmlrpc_registry_max_stackSize(this->implP->c_registryP) + + PROCESS_CALL_STACK_SIZE; } + + } // namespace diff --git a/libs/xmlrpc-c/src/cpp/server_abyss.cpp b/libs/xmlrpc-c/src/cpp/server_abyss.cpp index 3501f35..58fdd9b 100644 --- a/libs/xmlrpc-c/src/cpp/server_abyss.cpp +++ b/libs/xmlrpc-c/src/cpp/server_abyss.cpp @@ -1,10 +1,11 @@ +#include "xmlrpc_config.h" #include #include #include #include #include #include -#ifndef _WIN32 +#if !MSVCRT #include #endif @@ -14,9 +15,13 @@ using girerr::error; using girerr::throwf; #include "xmlrpc-c/base.h" +#include "xmlrpc-c/util.h" #include "xmlrpc-c/base.hpp" +#include "xmlrpc-c/abyss.h" #include "xmlrpc-c/server_abyss.h" #include "xmlrpc-c/registry.hpp" +#include "env_wrap.hpp" + #include "xmlrpc-c/server_abyss.hpp" using namespace std; @@ -43,14 +48,13 @@ 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). - 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 some, the system does this - automatically if the signal is blocked. + 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. And reaping the dead child. -----------------------------------------------------------------------------*/ #ifndef _WIN32 - /* Reap zombie children until there aren't any more. */ + // Reap zombie children / report to Abyss until there aren't any more. bool zombiesExist; bool error; @@ -71,7 +75,8 @@ sigchld(int const ASSERT_ONLY_ARG(signalClass)) { // This is OK - it's a ptrace notification } else error = true; - } + } else + ServerHandleSigchld(pid); } #endif /* _WIN32 */ } @@ -160,41 +165,78 @@ public: -serverAbyss::shutdown::shutdown(serverAbyss * const serverAbyssP) : - serverAbyssP(serverAbyssP) {} - - - -serverAbyss::shutdown::~shutdown() {} - - - -void -serverAbyss::shutdown::doit(string const&, - void * const) const { - - this->serverAbyssP->terminate(); -} +callInfo_serverAbyss::callInfo_serverAbyss( + serverAbyss * const serverAbyssP, + TSession * const abyssSessionP) : + serverAbyssP(serverAbyssP), abyssSessionP(abyssSessionP) {} + + + +struct serverAbyss::constrOpt_impl { + + constrOpt_impl(); + + 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; + std::string allowOrigin; + unsigned int accessCtlMaxAge; + bool serverOwnsSignals; + bool expectSigchld; + } value; + struct { + bool registryPtr; + bool registryP; + bool socketFd; + bool portNumber; + bool logFileName; + bool keepaliveTimeout; + bool keepaliveMaxConn; + bool timeout; + bool dontAdvertise; + bool uriPath; + bool chunkResponse; + bool allowOrigin; + bool accessCtlMaxAge; + bool serverOwnsSignals; + bool expectSigchld; + } present; +}; -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; +serverAbyss::constrOpt_impl::constrOpt_impl() { + 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; + present.allowOrigin = false; + present.accessCtlMaxAge = false; + present.serverOwnsSignals = false; + present.expectSigchld = false; // Set default values - value.dontAdvertise = false; - value.uriPath = string("/RPC2"); - value.chunkResponse = false; + value.dontAdvertise = false; + value.uriPath = string("/RPC2"); + value.chunkResponse = false; + value.serverOwnsSignals = true; + value.expectSigchld = false; } @@ -202,40 +244,40 @@ serverAbyss::constrOpt::constrOpt() { #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; \ + this->implP->value.OPTION_NAME = arg; \ + this->implP->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); +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); +DEFINE_OPTION_SETTER(allowOrigin, string); +DEFINE_OPTION_SETTER(accessCtlMaxAge, unsigned int); +DEFINE_OPTION_SETTER(serverOwnsSignals, bool); +DEFINE_OPTION_SETTER(expectSigchld, bool); + +#undef DEFINE_OPTION_SETTER +serverAbyss::constrOpt::constrOpt() { -void -serverAbyss::setAdditionalServerParms(constrOpt const& opt) { + this->implP = new serverAbyss::constrOpt_impl(); +} - /* 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); + +serverAbyss::constrOpt::~constrOpt() { + + delete(this->implP); } @@ -280,10 +322,155 @@ createServer(bool const logFileNameGiven, +struct serverAbyss_impl { + registryPtr regPtr; + // This just holds a reference to the registry so that it may + // get destroyed when the serverAbyss gets destroyed. If the + // creator of the serverAbyss is managing lifetime himself, + // this is a null pointer. 'registryP' is what you really use + // to access the registry. + + const registry * registryP; + + TServer cServer; + + serverAbyss_impl(serverAbyss::constrOpt_impl const& opt, + serverAbyss * const serverAbyssP); + + ~serverAbyss_impl(); + + void + setAdditionalServerParms(serverAbyss::constrOpt_impl const& opt); + + void + setHttpReqHandlers(string const& uriPath, + bool const chunkResponse, + bool const doHttpAccessControl, + string const& allowOrigin, + bool const accessCtlExpires, + unsigned int const accessCtlMaxAge); + void + run(); + + void + processCall(std::string const& call, + TSession * const abyssSessionP, + std::string * const responseP); + + serverAbyss * const serverAbyssP; + // The server for which we are the implementation. + + bool expectSigchld; + bool serverOwnsSignals; +}; + + + +static void +processXmlrpcCall(xmlrpc_env * const envP, + void * const arg, + const char * const callXml, + size_t const callXmlLen, + TSession * const abyssSessionP, + xmlrpc_mem_block ** const responseXmlPP) { +/*---------------------------------------------------------------------------- + This is an XML-RPC XML call processor, as called by the HTTP request + handler of the libxmlrpc_server_abyss C library. + + 'callXml'/'callXmlLen' is the XML text of a supposed XML-RPC call. + We execute the RPC and return the XML text of the XML-RPC response + as *responseXmlPP. + + 'arg' carries the information that tells us how to do that; e.g. + what XML-RPC methods are defined. +-----------------------------------------------------------------------------*/ + serverAbyss_impl * const implP( + static_cast(arg)); + + try { + string const call(callXml, callXmlLen); + + string response; + + implP->processCall(call, abyssSessionP, &response); + + xmlrpc_mem_block * responseMbP; + + responseMbP = XMLRPC_MEMBLOCK_NEW(char, envP, 0); + + if (!envP->fault_occurred) { + XMLRPC_MEMBLOCK_APPEND(char, envP, responseMbP, + response.c_str(), response.length()); + + *responseXmlPP = responseMbP; + } + } catch (exception const& e) { + xmlrpc_env_set_fault(envP, XMLRPC_INTERNAL_ERROR, e.what()); + } +} + + + void -serverAbyss::initialize(constrOpt const& opt) { +serverAbyss_impl::setAdditionalServerParms( + serverAbyss::constrOpt_impl const& opt) { - const registry * registryP; + // The following ought to be parameters on ServerCreate(). + + 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); + if (opt.value.expectSigchld) + ServerUseSigchld(&this->cServer); +} + + + +void +serverAbyss_impl::setHttpReqHandlers(string const& uriPath, + bool const chunkResponse, + bool const doHttpAccessControl, + string const& allowOrigin, + bool const accessCtlExpires, + unsigned int const accessCtlMaxAge) { +/*---------------------------------------------------------------------------- + This is a constructor helper. Don't assume *this is complete. +-----------------------------------------------------------------------------*/ + env_wrap env; + xmlrpc_server_abyss_handler_parms parms; + + parms.xml_processor = &processXmlrpcCall; + parms.xml_processor_arg = this; + parms.xml_processor_max_stack = this->registryP->maxStackSize(); + parms.uri_path = uriPath.c_str(); + parms.chunk_response = chunkResponse; + parms.allow_origin = doHttpAccessControl ? allowOrigin.c_str() : NULL; + parms.access_ctl_expires = accessCtlExpires; + parms.access_ctl_max_age = accessCtlMaxAge; + + xmlrpc_server_abyss_set_handler3( + &env.env_c, &this->cServer, + &parms, XMLRPC_AHPSIZE(access_ctl_max_age)); + + if (env.env_c.fault_occurred) + throwf("Failed to register the HTTP handler for XML-RPC " + "with the underlying Abyss HTTP server. " + "xmlrpc_server_abyss_set_handler3() failed with: %s", + env.env_c.fault_string); + + xmlrpc_server_abyss_set_default_handler(&this->cServer); +} + + + +serverAbyss_impl::serverAbyss_impl( + serverAbyss::constrOpt_impl const& opt, + serverAbyss * const serverAbyssP) : + serverAbyssP(serverAbyssP) { if (!opt.present.registryP && !opt.present.registryPtr) throwf("You must specify the 'registryP' or 'registryPtr' option"); @@ -292,15 +479,21 @@ serverAbyss::initialize(constrOpt const& opt) { "the 'registryPtr' options"); else { if (opt.present.registryP) - registryP = opt.value.registryP; + this->registryP = opt.value.registryP; else { - this->registryPtr = opt.value.registryPtr; - registryP = this->registryPtr.get(); + this->regPtr = opt.value.registryPtr; + this->registryP = this->regPtr.get(); } } if (opt.present.portNumber && opt.present.socketFd) throwf("You can't specify both portNumber and socketFd options"); + this->serverOwnsSignals = opt.value.serverOwnsSignals; + + if (opt.value.serverOwnsSignals && opt.value.expectSigchld) + throwf("You can't specify both expectSigchld " + "and serverOwnsSignals options"); + DateInit(); createServer(opt.present.logFileName, opt.value.logFileName, @@ -309,18 +502,16 @@ serverAbyss::initialize(constrOpt const& opt) { &this->cServer); try { - setAdditionalServerParms(opt); + this->setAdditionalServerParms(opt); + + this->setHttpReqHandlers(opt.value.uriPath, + opt.value.chunkResponse, + opt.present.allowOrigin, + opt.value.allowOrigin, + opt.present.accessCtlMaxAge, + opt.value.accessCtlMaxAge); + - // 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 (...) { @@ -331,6 +522,94 @@ serverAbyss::initialize(constrOpt const& opt) { +serverAbyss_impl::~serverAbyss_impl() { + + ServerFree(&this->cServer); +} + + + +static void +setupSignalsAndRunAbyss(TServer * const abyssServerP) { + + /* We do some pretty ugly stuff for an object method: we set signal + handlers, which are process-global. + + 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; + + setupSignalHandlers(&oldHandlers); + + ServerUseSigchld(abyssServerP); + + ServerRun(abyssServerP); + + restoreSignalHandlers(oldHandlers); +} + + + +void +serverAbyss_impl::run() { + + if (this->serverOwnsSignals) + setupSignalsAndRunAbyss(&this->cServer); + else { + if (this->expectSigchld) + ServerUseSigchld(&this->cServer); + + ServerRun(&this->cServer); + } +} + + + +void +serverAbyss_impl::processCall(string const& call, + TSession * const abyssSessionP, + string * const responseP) { + + callInfo_serverAbyss const callInfo(this->serverAbyssP, abyssSessionP); + + this->registryP->processCall(call, &callInfo, responseP); +} + + + +serverAbyss::shutdown::shutdown(serverAbyss * const serverAbyssP) : + serverAbyssP(serverAbyssP) {} + + + +serverAbyss::shutdown::~shutdown() {} + + + +void +serverAbyss::shutdown::doit(string const&, + void * const) const { + + this->serverAbyssP->terminate(); +} + + + +void +serverAbyss::initialize(constrOpt const& opt) { + + this->implP = new serverAbyss_impl(*opt.implP, this); +} + + + serverAbyss::serverAbyss(constrOpt const& opt) { initialize(opt); @@ -376,7 +655,7 @@ serverAbyss::serverAbyss( serverAbyss::~serverAbyss() { - ServerFree(&this->cServer); + delete(this->implP); } @@ -384,83 +663,147 @@ serverAbyss::~serverAbyss() { void serverAbyss::run() { - /* We do some pretty ugly stuff for an object method: we set signal - handlers, which are process-global. + this->implP->run(); +} + - 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; +void +serverAbyss::runOnce() { - setupSignalHandlers(&oldHandlers); + ServerRunOnce(&this->implP->cServer); +} - ServerRun(&this->cServer); - restoreSignalHandlers(oldHandlers); + +void +serverAbyss::runConn(int const socketFd) { + + ServerRunConn(&this->implP->cServer, socketFd); } - + +#ifndef WIN32 void -serverAbyss::runOnce() { +serverAbyss::sigchld(pid_t const pid) { + + // There's a hole in the design here, because the Abyss server uses + // a process-global list of children (so there can't be more than one + // Abyss object in the process), so while this is an object method, + // it doesn't really refer to the object at all. - ServerRunOnce(&this->cServer); + // We might conceivably fix Abyss some day, then this method would do + // what you expect -- affect only its own object. But forking Abyss is + // obsolete anyway, so we just don't worry about it. + + ServerHandleSigchld(pid); } +#endif void -serverAbyss::runConn(int const socketFd) { +serverAbyss::terminate() { - ServerRunConn(&this->cServer, socketFd); + ServerTerminate(&this->implP->cServer); } +callInfo_abyss::callInfo_abyss(TSession * const abyssSessionP) : + abyssSessionP(abyssSessionP) {} + + + void -serverAbyss::terminate() { +processXmlrpcCall2(xmlrpc_env * const envP, + void * const arg, + const char * const callXml, + size_t const callXmlLen, + TSession * const abyssSessionP, + xmlrpc_mem_block ** const responseXmlPP) { +/*---------------------------------------------------------------------------- + This is an XML-RPC XML call processor, as called by the HTTP request + handler of the libxmlrpc_server_abyss C library. + + 'callXml'/'callXmlLen' is the XML text of a supposed XML-RPC call. + We execute the RPC and return the XML text of the XML-RPC response + as *responseXmlPP. + + 'arg' carries the information that tells us how to do that; e.g. + what XML-RPC methods are defined. +-----------------------------------------------------------------------------*/ + const registry * const registryP(static_cast(arg)); + + try { + string const call(callXml, callXmlLen); + callInfo_abyss const callInfo(abyssSessionP); - ServerTerminate(&this->cServer); + string response; + + registryP->processCall(call, &callInfo, &response); + + xmlrpc_mem_block * responseMbP; + + responseMbP = XMLRPC_MEMBLOCK_NEW(char, envP, response.length()); + + if (!envP->fault_occurred) { + XMLRPC_MEMBLOCK_APPEND(char, envP, responseMbP, + response.c_str(), response.length()); + + *responseXmlPP = responseMbP; + } + } catch (exception const& e) { + xmlrpc_env_set_fault(envP, XMLRPC_INTERNAL_ERROR, e.what()); + } } + + +static void +setHandlers(TServer * const serverP, + string const& uriPath, + registry const& registry) { + + xmlrpc_server_abyss_set_handler2( + serverP, uriPath.c_str(), + processXmlrpcCall2, + const_cast(®istry), + registry.maxStackSize(), + false); + + xmlrpc_server_abyss_set_default_handler(serverP); +} + + + void -server_abyss_set_handlers(TServer * const srvP, +server_abyss_set_handlers(TServer * const serverP, registry const& registry, string const& uriPath) { - xmlrpc_server_abyss_set_handlers2(srvP, - uriPath.c_str(), - registry.c_registry()); + setHandlers(serverP, uriPath, registry); } void -server_abyss_set_handlers(TServer * const srvP, +server_abyss_set_handlers(TServer * const serverP, const registry * const registryP, string const& uriPath) { - xmlrpc_server_abyss_set_handlers2(srvP, - uriPath.c_str(), - registryP->c_registry()); + setHandlers(serverP, uriPath, *registryP); } void -server_abyss_set_handlers(TServer * const srvP, +server_abyss_set_handlers(TServer * const serverP, registryPtr const registryPtr, string const& uriPath) { - xmlrpc_server_abyss_set_handlers2(srvP, - uriPath.c_str(), - registryPtr->c_registry()); + setHandlers(serverP, uriPath, *registryPtr.get()); } diff --git a/libs/xmlrpc-c/src/cpp/server_cgi.cpp b/libs/xmlrpc-c/src/cpp/server_cgi.cpp new file mode 100644 index 0000000..41e5848 --- /dev/null +++ b/libs/xmlrpc-c/src/cpp/server_cgi.cpp @@ -0,0 +1,354 @@ +/*============================================================================= + server_cgi +=============================================================================== + + This is the definition of the xmlrpc_c::server_cgi class. An object of + this class is the guts of a CGI-based XML-RPC server. It runs inside + a CGI script and gets the XML-RPC call from and delivers the XML-RPC + response to the CGI environment. + + By Bryan Henderson 08.09.17. + + Contributed to the public domain by its author. +=============================================================================*/ + +#include "xmlrpc_config.h" +#if MSVCRT +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS +#endif +#include +#include +#endif +#include // for getenv +#include +#include + +#include "xmlrpc-c/girerr.hpp" +using girerr::throwf; +#include "xmlrpc-c/server_cgi.hpp" + +using namespace std; + + + +namespace { + +class httpInfo { + +public: + string requestMethod; + bool contentTypePresent; + string contentType; + unsigned int contentLength; + bool contentLengthPresent; + bool authCookiePresent; + string authCookie; + + httpInfo() { + + const char * const requestMethodC = getenv("REQUEST_METHOD"); + const char * const contentTypeC = getenv("CONTENT_TYPE"); + const char * const contentLengthC = getenv("CONTENT_LENGTH"); + const char * const authCookieC = getenv("HTTP_COOKIE_AUTH"); + + if (requestMethodC) + this->requestMethod = string(requestMethodC); + else + throwf("Invalid CGI environment; environment variable " + "REQUEST_METHOD is not set"); + + if (contentTypeC) { + this->contentTypePresent = true; + this->contentType = string(contentTypeC); + } else + this->contentTypePresent = false; + + if (contentLengthC) { + this->contentLengthPresent = true; + + int const lengthAtoi(atoi(string(contentLengthC).c_str())); + + if (lengthAtoi < 0) + throwf("Content-length HTTP header value is negative"); + else if (lengthAtoi == 0) + throwf("Content-length HTTP header value is zero"); + else + this->contentLength = lengthAtoi; + } else + this->contentLengthPresent = false; + + if (authCookieC) { + this->authCookie = string(authCookieC); + this->authCookiePresent = true; + } else + this->authCookiePresent = false; + } +}; + + + +class httpError { + +public: + + int const code; + string const msg; + + httpError(int const code, + string const& msg) : + code(code), msg(msg) {} +}; + + +} // namespace + + + +namespace xmlrpc_c { + +struct serverCgi_impl { + // '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; + + serverCgi_impl(serverCgi::constrOpt const& opt); + + void + establishRegistry(serverCgi::constrOpt const& opt); + + void + tryToProcessCall(); +}; + + + + +void +serverCgi_impl::establishRegistry(serverCgi::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(); + } + } +} + + + +serverCgi_impl::serverCgi_impl(serverCgi::constrOpt const& opt) { + this->establishRegistry(opt); +} + + + +serverCgi::constrOpt::constrOpt() { + + present.registryP = false; + present.registryPtr = false; +} + + + +#define DEFINE_OPTION_SETTER(OPTION_NAME, TYPE) \ +serverCgi::constrOpt & \ +serverCgi::constrOpt::OPTION_NAME(TYPE const& arg) { \ + this->value.OPTION_NAME = arg; \ + this->present.OPTION_NAME = true; \ + return *this; \ +} + +DEFINE_OPTION_SETTER(registryP, const registry *); +DEFINE_OPTION_SETTER(registryPtr, xmlrpc_c::registryPtr); + +#undef DEFINE_OPTION_SETTER + + + +serverCgi::serverCgi(constrOpt const& opt) { + + this->implP = new serverCgi_impl(opt); +} + + + +serverCgi::~serverCgi() { + + delete(this->implP); +} + + + +#if MSVCRT +#define FILEVAR fileP +#else +#define FILEVAR +#endif + +static void +setModeBinary(FILE * const FILEVAR) { + +#if MSVCRT + /* Fix from Jeff Stewart: NT opens stdin and stdout in text mode + by default, badly confusing our length calculations. So we need + to set the file handle to binary. + */ + _setmode(_fileno(FILEVAR), _O_BINARY); +#endif +} + + + +static string +getHttpBody(FILE * const fileP, + size_t const length) { + + setModeBinary(fileP); + char * const buffer(new char[length]); + auto_ptr p(buffer); // To make it go away when we leave + + size_t count; + + count = fread(buffer, sizeof(buffer[0]), length, fileP); + if (count < length) + throwf("Expected %lu bytes, received %lu", + (unsigned long) length, (unsigned long) count); + + return string(buffer, length); +} + + + +static void +writeNormalHttpResp(FILE * const fileP, + bool const sendCookie, + string const& authCookie, + string const& httpBody) { + + setModeBinary(fileP); + + // HTTP headers + + fprintf(fileP, "Status: 200 OK\n"); + + if (sendCookie) + fprintf(fileP, "Set-Cookie: auth=%s\n", authCookie.c_str()); + + fprintf(fileP, "Content-type: text/xml; charset=\"utf-8\"\n"); + fprintf(fileP, "Content-length: %u\n", (unsigned)httpBody.size()); + fprintf(fileP, "\n"); + + // HTTP body + + fwrite(httpBody.c_str(), sizeof(char), httpBody.size(), fileP); +} + + + +void +processCall2(const registry * const registryP, + FILE * const callFileP, + unsigned int const callSize, + bool const sendCookie, + string const& authCookie, + FILE * const respFileP) { + + if (callSize > xmlrpc_limit_get(XMLRPC_XML_SIZE_LIMIT_ID)) + throw(xmlrpc_c::fault(string("XML-RPC call is too large"), + fault::CODE_LIMIT_EXCEEDED)); + else { + string const callXml(getHttpBody(callFileP, callSize)); + + string responseXml; + + try { + registryP->processCall(callXml, &responseXml); + } catch (exception const& e) { + throw(httpError(500, e.what())); + } + + writeNormalHttpResp(respFileP, sendCookie, authCookie, responseXml); + } +} + + + + +static void +sendHttpErrorResp(FILE * const fileP, + httpError const& e) { + + setModeBinary(fileP); + + // HTTP headers + + fprintf(fileP, "Status: %d %s\n", e.code, e.msg.c_str()); + fprintf(fileP, "Content-type: text/html\n"); + fprintf(fileP, "\n"); + + // HTTP body: HTML error message + + fprintf(fileP, "%d %s\n", e.code, e.msg.c_str()); + fprintf(fileP, "

%d %s

\n", e.code, e.msg.c_str()); + fprintf(fileP, "

The Xmlrpc-c CGI server was unable to process " + "your request. It could not process it even enough to generate " + "an XML-RPC fault response.

\n"); +} + + + +void +serverCgi_impl::tryToProcessCall() { + + httpInfo httpInfo; + + if (httpInfo.requestMethod != string("POST")) + throw(httpError(405, "Method must be POST")); + + if (!httpInfo.contentTypePresent) + throw(httpError(400, "Must have content-type header")); + + if (httpInfo.contentType != string("text/xml")) + throw(httpError(400, string("ContentType must be 'text/xml', not '") + + httpInfo.contentType + string("'"))); + + if (!httpInfo.contentLengthPresent) + throw(httpError(411, "Content-length required")); + + processCall2(this->registryP, stdin, httpInfo.contentLength, + httpInfo.authCookiePresent, httpInfo.authCookie, stdout); +} + + + +void +serverCgi::processCall() { +/*---------------------------------------------------------------------------- + Get the XML-RPC call from Standard Input and environment variables, + parse it, find the right method, call it, prepare an XML-RPC + response with the result, and write it to Standard Output. +-----------------------------------------------------------------------------*/ + try { + this->implP->tryToProcessCall(); + } catch (httpError const e) { + sendHttpErrorResp(stdout, e); + } +} + + + +} // namespace diff --git a/libs/xmlrpc-c/src/cpp/server_pstream.cpp b/libs/xmlrpc-c/src/cpp/server_pstream.cpp index 86f2cc9..a1b19f8 100644 --- a/libs/xmlrpc-c/src/cpp/server_pstream.cpp +++ b/libs/xmlrpc-c/src/cpp/server_pstream.cpp @@ -9,24 +9,27 @@ 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. + By Bryan Henderson 09.03.22 Contributed to the public domain by its author. =============================================================================*/ +#include "xmlrpc_config.h" +#if MSVCRT +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS +#endif +#include +typedef int socklen_t; +#else +#include +#endif +#include +#include #include #include "xmlrpc-c/girerr.hpp" using girerr::throwf; -#include "xmlrpc-c/packetsocket.hpp" #include "xmlrpc-c/server_pstream.hpp" @@ -35,20 +38,52 @@ using namespace std; namespace xmlrpc_c { -serverPstreamConn::constrOpt::constrOpt() { +struct serverPstream::constrOpt_impl { + + constrOpt_impl(); + + struct value { + xmlrpc_c::registryPtr registryPtr; + const xmlrpc_c::registry * registryP; + XMLRPC_SOCKET socketFd; + } value; + struct { + bool registryPtr; + bool registryP; + bool socketFd; + } present; +}; + + + +serverPstream::constrOpt_impl::constrOpt_impl() { + + this->present.socketFd = false; + this->present.registryP = false; + this->present.registryPtr = false; +} + + + +serverPstream::constrOpt::constrOpt() { - present.socketFd = false; - present.registryP = false; - present.registryPtr = false; + this->implP = new serverPstream::constrOpt_impl(); +} + + + +serverPstream::constrOpt::~constrOpt() { + + delete(this->implP); } #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; \ +serverPstream::constrOpt & \ +serverPstream::constrOpt::OPTION_NAME(TYPE const& arg) { \ + this->implP->value.OPTION_NAME = arg; \ + this->implP->present.OPTION_NAME = true; \ return *this; \ } @@ -60,8 +95,63 @@ DEFINE_OPTION_SETTER(registryPtr, xmlrpc_c::registryPtr); +struct serverPstream_impl { + + serverPstream_impl(serverPstream::constrOpt_impl const& opt); + + ~serverPstream_impl(); + + void + establishRegistry(serverPstream::constrOpt_impl const& opt); + + // '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; + + XMLRPC_SOCKET listenSocketFd; + // The socket on which we accept connections from clients. This comes + // to us from the creator, already bound and in listen mode. That + // way, this object doesn't have to know anything about socket + // addresses or listen parameters such as the maximum connection + // backlog size. + + bool termRequested; + // User has requested that the run method return ASAP; i.e. that + // the server cease servicing RPCs. +}; + + + +serverPstream_impl::serverPstream_impl( + serverPstream::constrOpt_impl const& opt) { + + this->establishRegistry(opt); + + if (!opt.present.socketFd) + throwf("You must provide a 'socketFd' constructor option."); + + this->listenSocketFd = opt.value.socketFd; + + this->termRequested = false; +} + + + +serverPstream_impl::~serverPstream_impl() { + +} + + + void -serverPstreamConn::establishRegistry(constrOpt const& opt) { +serverPstream_impl::establishRegistry( + serverPstream::constrOpt_impl const& opt) { if (!opt.present.registryP && !opt.present.registryPtr) throwf("You must specify the 'registryP' or 'registryPtr' option"); @@ -79,109 +169,110 @@ serverPstreamConn::establishRegistry(constrOpt const& opt) { } +/*----------------------------------------------------------------------------- + serverPstream::shutdown is a derived class of registry::shutdown. You give + it to the registry object to allow XML-RPC method 'system.shutdown' to +-----------------------------------------------------------------------------*/ -void -serverPstreamConn::establishPacketSocket(constrOpt const& opt) { +serverPstream::shutdown::shutdown(serverPstream * const serverPstreamP) : + serverPstreamP(serverPstreamP) {} - if (!opt.present.socketFd) - throwf("You must provide a 'socketFd' constructor option."); - - auto_ptr packetSocketAP; - try { - auto_ptr 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(); -} +serverPstream::shutdown::~shutdown() {} -serverPstreamConn::serverPstreamConn(constrOpt const& opt) { - this->establishRegistry(opt); +void +serverPstream::shutdown::doit(string const&, + void * const) const { - this->establishPacketSocket(opt); + this->serverPstreamP->terminate(); } +/*---------------------------------------------------------------------------*/ -serverPstreamConn::~serverPstreamConn() { +serverPstream::serverPstream(constrOpt const& opt) { - delete(this->packetSocketP); + this->implP = new serverPstream_impl(*opt.implP); } -void -processCall(const registry * const registryP, - packetPtr const& callPacketP, - packetPtr * const responsePacketPP) { +serverPstream::~serverPstream() { - string const callXml(reinterpret_cast(callPacketP->getBytes()), - callPacketP->getLength()); + delete(this->implP); +} - string responseXml; - registryP->processCall(callXml, &responseXml); - *responsePacketPP = packetPtr(new packet(responseXml.c_str(), - responseXml.length())); +void +serverPstream::runSerial(volatile const int * const interruptP) { + + while (!this->implP->termRequested && !*interruptP) { + struct sockaddr peerAddr; + socklen_t size = sizeof(peerAddr); + int rc; + + rc = accept(this->implP->listenSocketFd, &peerAddr, &size); + + if (!*interruptP) { + if (rc < 0) + if (errno == EINTR) { + // system call was interrupted, but user doesn't want + // to interrupt the server, so just keep trying + } else + throwf("Failed to accept a connection " + "on the listening socket. accept() failed " + "with errno %d (%s)", errno, strerror(errno)); + else { + int const acceptedFd = rc; + + serverPstreamConn connectionServer( + xmlrpc_c::serverPstreamConn::constrOpt() + .socketFd(acceptedFd) + .registryP(this->implP->registryP)); + + callInfo_serverPstream callInfo(this, peerAddr, size); + + connectionServer.run(&callInfo, interruptP); + } + } + } } void -serverPstreamConn::runOnce(volatile const int * const interruptP, - bool * const eofP) { -/*---------------------------------------------------------------------------- - Get and execute one RPC from the client. +serverPstream::runSerial() { - 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()); - } - } + int const interrupt(0); // Never interrupt + + this->runSerial(&interrupt); } void -serverPstreamConn::runOnce(bool * const eofP) { -/*---------------------------------------------------------------------------- - Get and execute one RPC from the client. ------------------------------------------------------------------------------*/ - int const interrupt(0); // Never interrupt +serverPstream::terminate() { - this->runOnce(&interrupt, eofP); + this->implP->termRequested = true; } +callInfo_serverPstream::callInfo_serverPstream( + serverPstream * const serverP, + struct sockaddr const clientAddr, + socklen_t const clientAddrSize) : + + serverP(serverP), + clientAddr(clientAddr), + clientAddrSize(clientAddrSize) + +{} + + + } // namespace diff --git a/libs/xmlrpc-c/src/cpp/server_pstream_conn.cpp b/libs/xmlrpc-c/src/cpp/server_pstream_conn.cpp new file mode 100644 index 0000000..3598164 --- /dev/null +++ b/libs/xmlrpc-c/src/cpp/server_pstream_conn.cpp @@ -0,0 +1,364 @@ +/*============================================================================= + 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 + +#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 { + + +struct serverPstreamConn::constrOpt_impl { + + constrOpt_impl(); + + 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_impl::constrOpt_impl() { + + this->present.socketFd = false; + this->present.registryP = false; + this->present.registryPtr = false; +} + + + +serverPstreamConn::constrOpt::constrOpt() { + + this->implP = new constrOpt_impl(); +} + + + +serverPstreamConn::constrOpt::~constrOpt() { + + delete(this->implP); +} + + + +#define DEFINE_OPTION_SETTER(OPTION_NAME, TYPE) \ +serverPstreamConn::constrOpt & \ +serverPstreamConn::constrOpt::OPTION_NAME(TYPE const& arg) { \ + this->implP->value.OPTION_NAME = arg; \ + this->implP->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 + + + +struct serverPstreamConn_impl { + + serverPstreamConn_impl(serverPstreamConn::constrOpt_impl const& opt); + + ~serverPstreamConn_impl(); + + void + establishRegistry(serverPstreamConn::constrOpt_impl const& opt); + + void + establishPacketSocket(serverPstreamConn::constrOpt_impl const& opt); + + void + processRecdPacket(packetPtr const callPacketP, + callInfo * const callInfoP); + + // '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. +}; + + + +serverPstreamConn_impl::serverPstreamConn_impl( + serverPstreamConn::constrOpt_impl const& opt) { + + this->establishRegistry(opt); + + this->establishPacketSocket(opt); +} + + + +serverPstreamConn_impl::~serverPstreamConn_impl() { + + delete(this->packetSocketP); +} + + + +void +serverPstreamConn_impl::establishRegistry( + serverPstreamConn::constrOpt_impl 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_impl::establishPacketSocket( + serverPstreamConn::constrOpt_impl const& opt) { + + if (!opt.present.socketFd) + throwf("You must provide a 'socketFd' constructor option."); + + auto_ptr packetSocketAP; + + try { + auto_ptr 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->implP = new serverPstreamConn_impl(*opt.implP); +} + + + +serverPstreamConn::~serverPstreamConn() { + + delete(this->implP); +} + + + +static void +processCall(const registry * const registryP, + packetPtr const& callPacketP, + callInfo * const callInfoP, + packetPtr * const responsePacketPP) { + + string const callXml(reinterpret_cast(callPacketP->getBytes()), + callPacketP->getLength()); + + string responseXml; + + registryP->processCall(callXml, callInfoP, &responseXml); + + *responsePacketPP = packetPtr(new packet(responseXml.c_str(), + responseXml.length())); +} + + + +void +serverPstreamConn_impl::processRecdPacket(packetPtr const callPacketP, + callInfo * const callInfoP) { + + packetPtr responsePacketP; + try { + processCall(this->registryP, callPacketP, callInfoP, &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(callInfo * const callInfoP, + 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->implP->packetSocketP->readWait(interruptP, eofP, &gotPacket, + &callPacketP); + } catch (exception const& e) { + throwf("Error reading a packet from the packet socket. %s", + e.what()); + } + if (gotPacket) + this->implP->processRecdPacket(callPacketP, callInfoP); +} + + + +void +serverPstreamConn::runOnce(volatile const int * const interruptP, + bool * const eofP) { + + this->runOnce(NULL, interruptP, eofP); +} + + + +void +serverPstreamConn::runOnce(bool * const eofP) { +/*---------------------------------------------------------------------------- + Get and execute one RPC from the client. +-----------------------------------------------------------------------------*/ + int const interrupt(0); // Never interrupt + + this->runOnce(&interrupt, eofP); +} + + + +void +serverPstreamConn::runOnceNoWait(callInfo * const callInfoP, + bool * const eofP, + bool * const didOneP) { +/*---------------------------------------------------------------------------- + Get and execute one RPC from the client, unless none has been + received yet. Return as *didOneP whether or not one has been + received. Unless didOneP is NULL. +-----------------------------------------------------------------------------*/ + bool gotPacket; + packetPtr callPacketP; + + try { + this->implP->packetSocketP->read(eofP, &gotPacket, &callPacketP); + } catch (exception const& e) { + throwf("Error reading a packet from the packet socket. %s", + e.what()); + } + if (gotPacket) + this->implP->processRecdPacket(callPacketP, callInfoP); + + if (didOneP) + *didOneP = gotPacket; +} + + + +void +serverPstreamConn::runOnceNoWait(bool * const eofP, + bool * const didOneP) { + + this->runOnceNoWait(NULL, eofP, didOneP); +} + + + +void +serverPstreamConn::runOnceNoWait(bool * const eofP) { +/*---------------------------------------------------------------------------- + Get and execute one RPC from the client, unless none has been + received yet. +-----------------------------------------------------------------------------*/ + this->runOnceNoWait(eofP, NULL); +} + + + +void +serverPstreamConn::run(callInfo * const callInfoP, + volatile const int * const interruptP) { + + for (bool clientHasDisconnected = false; + !clientHasDisconnected && !*interruptP;) + this->runOnce(callInfoP, interruptP, &clientHasDisconnected); +} + + + +void +serverPstreamConn::run(volatile const int * const interruptP) { + + this->run(NULL, interruptP); +} + + + +void +serverPstreamConn::run() { + + int const interrupt(0); // Never interrupt + + this->run(&interrupt); +} + + + +} // namespace diff --git a/libs/xmlrpc-c/src/cpp/test/Makefile b/libs/xmlrpc-c/src/cpp/test/Makefile index ff6750f..ccde8f5 100644 --- a/libs/xmlrpc-c/src/cpp/test/Makefile +++ b/libs/xmlrpc-c/src/cpp/test/Makefile @@ -17,20 +17,16 @@ all: $(PROGS) XMLRPC_C_CONFIG = $(BLDDIR)/xmlrpc-c-config.test -CXXFLAGS = $(CXXFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD) - -LDFLAGS += $(shell $(XMLRPC_C_CONFIG) client --ldadd) +LIBS := $(shell $(XMLRPC_C_CONFIG) client --ldadd) ifeq ($(MUST_BUILD_CURL_CLIENT),yes) - LDFLAGS += $(shell curl-config --libs) + LIBS += $(shell curl-config --libs) endif ifeq ($(MUST_BUILD_LIBWWW_CLIENT),yes) - LDFLAGS += $(shell libwww-config --libs) + LIBS += $(shell libwww-config --libs) endif -LDFLAGS += "-lpthread" - -LDFLAGS += $(LADD) +LIBS += -lpthread INCLUDES = -Isrcdir/include -I$(BLDDIR) -Isrcdir -Isrcdir/lib/util/include @@ -42,7 +38,15 @@ Makefile: srcdir include $(SRCDIR)/common.mk -TEST_OBJS = test.o registry.o server_abyss.o server_pstream.o tools.o +TEST_OBJS = \ + test.o \ + base64.o \ + registry.o \ + server_abyss.o \ + server_pstream.o \ + tools.o \ + value.o \ + xml.o \ ifeq ($(MUST_BUILD_CLIENT),yes) TEST_OBJS += testclient.o @@ -69,16 +73,17 @@ TEST_LIBS = \ ifneq ($(ENABLE_LIBXML2_BACKEND),yes) # We're using the internal Expat XML parser TEST_LIBS += $(LIBXMLRPC_XMLPARSE_A) $(LIBXMLRPC_XMLTOK_A) - LDADD_XML = + LIB_XML = + registry.o: D_INTERNAL_EXPAT=-DINTERNAL_EXPAT else - LDADD_XML = $(shell xml2-config --libs) + LIB_XML = $(shell xml2-config --libs) endif test: $(TEST_OBJS) $(TEST_LIBS) - $(CXXLD) -o $@ $(LDFLAGS) $(LDADD_XML) $^ + $(CXXLD) -o $@ $(LDFLAGS) $(LADD) $^ $(LIB_XML) $(LIBS) %.o:%.cpp - $(CXX) -c $(INCLUDES) $(CXXFLAGS) $< + $(CXX) -c $(INCLUDES) $(CXXFLAGS_ALL) $(D_INTERNAL_EXPAT) $< # Note the difference between 'check' and 'runtests'. 'check' means to check # our own correctness. 'runtests' means to run the tests that check our @@ -104,4 +109,4 @@ distclean: clean distclean-common .PHONY: dep dep: dep-common -include Makefile.depend +include depend.mk diff --git a/libs/xmlrpc-c/src/cpp/test/base64.cpp b/libs/xmlrpc-c/src/cpp/test/base64.cpp new file mode 100644 index 0000000..17e4e78 --- /dev/null +++ b/libs/xmlrpc-c/src/cpp/test/base64.cpp @@ -0,0 +1,54 @@ +#include +#include +#include + +#include "xmlrpc-c/girerr.hpp" +using girerr::error; +#include "xmlrpc-c/base64.hpp" + +#include "tools.hpp" + +#include "base64.hpp" + +using namespace xmlrpc_c; +using namespace std; + + + +string +base64TestSuite::suiteName() { + return "base64TestSuite"; +} + + + +void +base64TestSuite::runtests(unsigned int const) { + + unsigned char const bytes0Data[] = "This is a test"; + + vector bytes0(&bytes0Data[0], + &bytes0Data[sizeof(bytes0Data)]); + + string const base64_0("VGhpcyBpcyBhIHRlc3QA"); + + string const expectedBase64_0(base64_0 + "\r\n"); + + TEST(base64FromBytes(bytes0) == expectedBase64_0); + + TEST(bytesFromBase64(base64_0) == bytes0); + + unsigned char const bytes1Data[] = {0x80, 0xff}; + + vector bytes1(&bytes1Data[0], + &bytes1Data[sizeof(bytes1Data)]); + + string const base64_1("gP8="); + + string const expectedBase64_1(base64_1 + "\r\n"); + + TEST(base64FromBytes(bytes1) == expectedBase64_1); + + TEST(bytesFromBase64(base64_1) == bytes1); + +} diff --git a/libs/xmlrpc-c/src/cpp/test/base64.hpp b/libs/xmlrpc-c/src/cpp/test/base64.hpp new file mode 100644 index 0000000..72ee02d --- /dev/null +++ b/libs/xmlrpc-c/src/cpp/test/base64.hpp @@ -0,0 +1,9 @@ +#include "tools.hpp" + +class base64TestSuite : public testSuite { + +public: + virtual std::string suiteName(); + virtual void runtests(unsigned int const indentation); +}; + diff --git a/libs/xmlrpc-c/src/cpp/test/registry.cpp b/libs/xmlrpc-c/src/cpp/test/registry.cpp index 6ca265a..c7e6e42 100644 --- a/libs/xmlrpc-c/src/cpp/test/registry.cpp +++ b/libs/xmlrpc-c/src/cpp/test/registry.cpp @@ -20,11 +20,19 @@ using namespace xmlrpc_c; using namespace std; -string const xmlPrologue("\r\n"); +namespace { + +static string const +xmlPrologue("\r\n"); + +static string const +apacheUrl("http://ws.apache.org/xmlrpc/namespaces/extensions"); + +static string const +xmlnsApache("xmlns:ex=\"" + apacheUrl + "\""); -namespace { string const noElementFoundXml( xmlPrologue + "\r\n" @@ -41,6 +49,22 @@ string const noElementFoundXml( "\r\n" ); +string const invalidXMLCall( + xmlPrologue + + "\r\n" + "\r\n" + "\r\n" + "faultCode\r\n" + "-503\r\n" + "faultString\r\n" + "Call XML not a proper XML-RPC call. " + "Call is not valid XML. XML parsing failed" + "\r\n" + "\r\n" + "\r\n" + "\r\n" + ); + string const sampleAddGoodCallXml( xmlPrologue + "\r\n" @@ -86,6 +110,24 @@ string const sampleAddBadResponseXml( "\r\n" ); +string const testCallInfoCallXml( + xmlPrologue + + "\r\n" + "test.callinfo\r\n" + "\r\n" + "\r\n" + "\r\n" + ); + +string const testCallInfoResponseXml( + xmlPrologue + + "\r\n" + "\r\n" + "this is a test callInfo" + "\r\n" + "\r\n" + "\r\n" + ); string const nonexistentMethodCallXml( xmlPrologue + @@ -123,31 +165,30 @@ string const nonexistentMethodNoDefResponseXml( "\r\n" ); -} // namespace string const echoI8ApacheCall( xmlPrologue + - "\r\n" + "\r\n" "echo\r\n" "\r\n" - "5\r\n" + "5\r\n" "\r\n" "\r\n" ); string const echoI8ApacheResponse( xmlPrologue + - "\r\n" + "\r\n" "\r\n" - "5\r\n" + "5\r\n" "\r\n" "\r\n" ); string const echoNilApacheCall( xmlPrologue + - "\r\n" + "\r\n" "echo\r\n" "\r\n" "\r\n" @@ -157,14 +198,26 @@ string const echoNilApacheCall( string const echoNilApacheResponse( xmlPrologue + - "\r\n" + "\r\n" "\r\n" - "\r\n" + "\r\n" "\r\n" "\r\n" ); +class callInfo_test : public callInfo { + +public: + callInfo_test() : data("this is a test callInfo") {} + + callInfo_test(string const& data) : data(data) {}; + + string data; +}; + + + class sampleAddMethod : public method { public: sampleAddMethod() { @@ -186,6 +239,51 @@ public: +class sampleAddMethod2 : public method2 { +public: + sampleAddMethod2() { + this->_signature = "i:ii"; + this->_help = "This method adds two integers together"; + } + void + execute(xmlrpc_c::paramList const& paramList, + const callInfo * const, + value * const retvalP) { + + int const addend(paramList.getInt(0)); + int const adder(paramList.getInt(1)); + + paramList.verifyEnd(2); + + *retvalP = value_int(addend + adder); + } +}; + + + +class testCallInfoMethod : public method2 { +public: + testCallInfoMethod() { + this->_signature = "s:"; + } + void + execute(xmlrpc_c::paramList const& paramList, + const callInfo * const callInfoPtr, + value * const retvalP) { + + const callInfo_test * const callInfoP( + dynamic_cast(callInfoPtr)); + + TEST(callInfoP != NULL); + + paramList.verifyEnd(0); + + *retvalP = value_string(callInfoP->data); + } +}; + + + class nameMethod : public defaultMethod { void @@ -213,6 +311,22 @@ public: +static void +testEmptyXmlDocCall(xmlrpc_c::registry const& myRegistry) { + + string response; + myRegistry.processCall("", &response); + +#ifdef INTERNAL_EXPAT + TEST(response == noElementFoundXml); +#else + // This is what we get with libxml2 + TEST(response == invalidXMLCall); +#endif +} + + + class registryRegMethodTestSuite : public testSuite { public: @@ -227,11 +341,7 @@ public: xmlrpc_c::methodPtr(new sampleAddMethod)); myRegistry.disableIntrospection(); - { - string response; - myRegistry.processCall("", &response); - TEST(response == noElementFoundXml); - } + testEmptyXmlDocCall(myRegistry); { string response; myRegistry.processCall(sampleAddGoodCallXml, &response); @@ -242,6 +352,12 @@ public: myRegistry.processCall(sampleAddBadCallXml, &response); TEST(response == sampleAddBadResponseXml); } + { + string response; + callInfo const callInfo; + myRegistry.processCall(sampleAddBadCallXml, &callInfo, &response); + TEST(response == sampleAddBadResponseXml); + } } }; @@ -284,6 +400,93 @@ public: +class method2TestSuite : public testSuite { + +public: + virtual string suiteName() { + return "method2TestSuite"; + } + virtual void runtests(unsigned int const) { + + xmlrpc_c::registry myRegistry; + + myRegistry.addMethod("sample.add", + xmlrpc_c::methodPtr(new sampleAddMethod2)); + + myRegistry.addMethod("test.callinfo", + xmlrpc_c::methodPtr(new testCallInfoMethod)); + + { + string response; + myRegistry.processCall(sampleAddGoodCallXml, &response); + TEST(response == sampleAddGoodResponseXml); + } + { + string response; + myRegistry.processCall(sampleAddBadCallXml, &response); + TEST(response == sampleAddBadResponseXml); + } + { + string response; + callInfo_test const callInfo; + myRegistry.processCall(testCallInfoCallXml, &callInfo, &response); + TEST(response == testCallInfoResponseXml); + } + } +}; + + + +class dialectTestSuite : public testSuite { + +public: + virtual string suiteName() { + return "dialectTestSuite"; + } + virtual void runtests(unsigned int const) { + + registry myRegistry; + string response; + + myRegistry.addMethod("sample.add", methodPtr(new sampleAddMethod)); + myRegistry.addMethod("echo", methodPtr(new echoMethod)); + + myRegistry.setDialect(xmlrpc_dialect_i8); + + myRegistry.setDialect(xmlrpc_dialect_apache); + + myRegistry.processCall(echoI8ApacheCall, &response); + + TEST(response == echoI8ApacheResponse); + + myRegistry.processCall(echoNilApacheCall, &response); + + TEST(response == echoNilApacheResponse); + + EXPECT_ERROR( // invalid dialect + myRegistry.setDialect(static_cast(300)); + ); + } +}; + + + +class testShutdown : public xmlrpc_c::registry::shutdown { +/*---------------------------------------------------------------------------- + This class is logically local to + registryShutdownTestSuite::runtests(), but if we declare it that + way, gcc 2.95.3 fails with some bogus messages about undefined + references from random functions when we do that. +-----------------------------------------------------------------------------*/ +public: + void doit(string const&, + void * const) const { + + } +}; + + + class registryShutdownTestSuite : public testSuite { public: @@ -294,15 +497,7 @@ public: xmlrpc_c::registry myRegistry; - class myshutdown : public xmlrpc_c::registry::shutdown { - public: - void doit(string const&, - void * const) const { - - } - }; - - myshutdown shutdown; + testShutdown shutdown; myRegistry.setShutdown(&shutdown); } @@ -310,6 +505,10 @@ public: +} // unnamed namespace + + + string registryTestSuite::suiteName() { return "registryTestSuite"; @@ -327,32 +526,19 @@ registryTestSuite::runtests(unsigned int const indentation) { } registryRegMethodTestSuite().run(indentation+1); + registryDefaultMethodTestSuite().run(indentation+1); - registry myRegistry; - - myRegistry.addMethod("sample.add", methodPtr(new sampleAddMethod)); - myRegistry.addMethod("echo", methodPtr(new echoMethod)); + method2TestSuite().run(indentation+1); - string response; + registry myRegistry; myRegistry.disableIntrospection(); - myRegistry.setDialect(xmlrpc_dialect_i8); - - myRegistry.setDialect(xmlrpc_dialect_apache); + dialectTestSuite().run(indentation+1); registryShutdownTestSuite().run(indentation+1); - myRegistry.processCall(echoI8ApacheCall, &response); - - TEST(response == echoI8ApacheResponse); - - myRegistry.processCall(echoNilApacheCall, &response); - - TEST(response == echoNilApacheResponse); + TEST(myRegistry.maxStackSize() >= 256); - EXPECT_ERROR( // invalid dialect - myRegistry.setDialect(static_cast(300)); - ); } diff --git a/libs/xmlrpc-c/src/cpp/test/server_abyss.cpp b/libs/xmlrpc-c/src/cpp/test/server_abyss.cpp index 4b236ef..2b50688 100644 --- a/libs/xmlrpc-c/src/cpp/test/server_abyss.cpp +++ b/libs/xmlrpc-c/src/cpp/test/server_abyss.cpp @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include #ifdef WIN32 #include @@ -17,6 +19,7 @@ #include #include #include + #include #endif #include "xmlrpc-c/girerr.hpp" @@ -34,6 +37,9 @@ using namespace xmlrpc_c; using namespace std; + +namespace { + static void closesock(int const fd) { #ifdef WIN32 @@ -75,7 +81,7 @@ public: closesock(this->fd); } - int fd; + XMLRPC_SOCKET fd; }; @@ -259,6 +265,10 @@ public: .timeout(20) .dontAdvertise(true) .uriPath("/xmlrpc") + .chunkResponse(true) + .allowOrigin("*") + .serverOwnsSignals(false) + .expectSigchld(true) ); } @@ -274,6 +284,54 @@ public: +class testCallInfoMethod : public method2 { +public: + void + execute(paramList const& paramList, + const callInfo * const callInfoPtr, + value * const retvalP) { + + const callInfo_serverAbyss * const callInfoP( + dynamic_cast(callInfoPtr)); + + TEST(callInfoP != NULL); + + paramList.verifyEnd(0); + + TEST(callInfoP->serverAbyssP != NULL); + TEST(callInfoP->abyssSessionP != NULL); + + *retvalP = value_nil(); + } +}; + + + +class callInfoTestSuite : public testSuite { + +public: + virtual string suiteName() { + return "callInfoTestSuite"; + } + virtual void runtests(unsigned int const) { + + registry myRegistry; + + myRegistry.addMethod("sample.add", methodPtr(new testCallInfoMethod)); + + serverAbyss abyssServer(serverAbyss::constrOpt() + .registryP(&myRegistry) + .portNumber(12345) + ); + } +}; + + + +} // unnamed namespace + + + string serverAbyssTestSuite::suiteName() { return "serverAbyssTestSuite"; @@ -289,4 +347,5 @@ serverAbyssTestSuite::runtests(unsigned int const indentation) { createTestSuite().run(indentation+1); + callInfoTestSuite().run(indentation+1); } diff --git a/libs/xmlrpc-c/src/cpp/test/server_pstream.cpp b/libs/xmlrpc-c/src/cpp/test/server_pstream.cpp index 83b3e88..1d93273 100644 --- a/libs/xmlrpc-c/src/cpp/test/server_pstream.cpp +++ b/libs/xmlrpc-c/src/cpp/test/server_pstream.cpp @@ -4,16 +4,37 @@ Test the pstream server C++ facilities of XML-RPC for C/C++. =============================================================================*/ -#include -#include -#include + +#include "xmlrpc_config.h" + +#if MSVCRT + #include + #include +#else + #include + #include + #include +#endif + #include #include +#include #include +#include "xmlrpc-c/config.h" + +#if MSVCRT + int + xmlrpc_win32_socketpair(int const domain, + int const type, + int const protocol, + SOCKET socks[2]); +#endif + #include "xmlrpc-c/girerr.hpp" using girerr::error; using girerr::throwf; +#include "xmlrpc-c/sleep_int.h" #include "xmlrpc-c/base.hpp" #include "xmlrpc-c/registry.hpp" #include "xmlrpc-c/server_pstream.hpp" @@ -25,6 +46,41 @@ using namespace xmlrpc_c; using namespace std; +namespace { + +static void +setNonBlocking(XMLRPC_SOCKET const socket) { + +#if MSVCRT + u_long iMode = 1; + ioctlsocket(socket, FIONBIO, &iMode); +#else + fcntl(socket, F_SETFL, O_NONBLOCK); +#endif +} + + + +#define ESC_STR "\x1B" + + +static string const +xmlPrologue("\r\n"); + +static string const +packetStart(ESC_STR "PKT"); + +static string const +packetEnd(ESC_STR "END"); + + +class callInfo_test : public callInfo { +public: + callInfo_test() : info("this is a test") {} + string const info; +}; + + class sampleAddMethod : public method { public: @@ -45,51 +101,542 @@ public: } }; +string const sampleAddCallXml( + xmlPrologue + + "\r\n" + "sample.add\r\n" + "\r\n" + "5\r\n" + "7\r\n" + "\r\n" + "\r\n" + ); + +string const sampleAddResponseXml( + xmlPrologue + + "\r\n" + "\r\n" + "12\r\n" + "\r\n" + "\r\n" + ); + + +class testCallInfoMethod : public method2 { + +public: + virtual void + execute(paramList const& paramList, + const callInfo * const callInfoPtr, + value * const retvalP) { + + const callInfo_test * const callInfoP( + dynamic_cast(callInfoPtr)); + + TEST(callInfoP != NULL); + + paramList.verifyEnd(0); + + TEST(callInfoP->info == string("this is a test")); + + *retvalP = value_nil(); + } +}; + +string const testCallInfoCallXml( + xmlPrologue + + "\r\n" + "test.callinfo\r\n" + "\r\n" + "\r\n" + "\r\n" + ); + +string const testCallInfoResponseXml( + xmlPrologue + + "\r\n" + "\r\n" + "" + "\r\n" + "\r\n" + "\r\n" + ); + static void -createTestFile(string const& contents, - int * const fdP) { +waitForNetworkTransport() { +/*---------------------------------------------------------------------------- + Wait for a message to travel through the network. + + This is part of our hack to allow us to test client/server communication + without the bother of a separate thread for each. One party writes + to a socket, causing the OS to buffer the message, then the other party + reads from the socket, getting the buffered message. We never wait + to send or receive, because with only one thread to do both, we would + deadlock. Instead, we just count on the buffer being big enough. + + But on some systems, the message doesn't immediately travel like this. It + takes action by an independent thread (provided by the OS) to move the + message. In particular, we've seen this behavior on Windows (2010.10). + + So we just sleep for a small amount of time to let the message move. +-----------------------------------------------------------------------------*/ + + // xmlrpc_millisecond_sleep() is allowed to return early, and on Windows + // it does that in preference to returning late insofar as the clock + // resolution doesn't allow returning at the exact time. It is rumored + // that Windows clock period may be as long as 40 milliseconds. + + xmlrpc_millisecond_sleep(50); +} - 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()); + + +class client { +/*---------------------------------------------------------------------------- + This is an object you can use as a client to test a packet stream + server. + + You attach the 'serverFd' member to your packet stream server, then + call the 'sendCall' method to send a call to your server, then call + the 'recvResp' method to get the response. + + Destroying the object closes the connection. + + We rely on typical, though unguaranteed socket function: we need to + be able to write 'contents' to the socket in a single write() + system call before the other side reads anything -- i.e. the socket + has to have a buffer that big. We do this because we're lazy; doing + it right would require forking a writer process. +-----------------------------------------------------------------------------*/ +public: + + client(); + ~client(); + + void + sendCall(string const& callBytes) const; + + void + hangup(); + + void + recvResp(string * const respBytesP) const; + + int serverFd; + +private: + + int clientFd; +}; + + + +client::client() { + + enum { + SERVER = 0, + CLIENT = 1, + }; + XMLRPC_SOCKET sockets[2]; + int rc; + + rc = XMLRPC_SOCKETPAIR(AF_UNIX, SOCK_STREAM, 0, sockets); + if (rc < 0) - throwf("Failed to create file '%s' as a test tool. errno=%d (%s)", - filename.c_str(), errno, strerror(errno)); + throwf("Failed to create UNIX domain stream socket pair " + "as test tool. errno=%d (%s)", + errno, strerror(errno)); else { - int const fd(rc); + setNonBlocking(sockets[CLIENT]); - 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; + this->serverFd = sockets[SERVER]; + this->clientFd = sockets[CLIENT]; } } +client::~client() { + + XMLRPC_CLOSESOCKET(this->clientFd); + XMLRPC_CLOSESOCKET(this->serverFd); +} + + + +void +client::sendCall(string const& packetBytes) const { + + int rc; + + rc = send(this->clientFd, packetBytes.c_str(), packetBytes.length(), 0); + + waitForNetworkTransport(); + + if (rc < 0) + throwf("send() of test data to socket failed, errno=%d (%s)", + errno, strerror(errno)); + else { + unsigned int bytesWritten(rc); + + if (bytesWritten != packetBytes.length()) + throwf("Short write to socket"); + } +} + + + +void +client::hangup() { + + // Closing the socket (close()) would be a better simulation of the + // real world, and easier, but we shut down just the client->server + // half of the socket and remain open to receive an RPC response. + // That's because this test program is lazy and does the client and + // server in the same thread, depending on socket buffering on the + // receive side to provide parallelism. We need to be able to do the + // following sequence: + // + // - Client sends call + // - Client hangs up + // - Server gets call + // - Server sends response + // - Client gets response + // - Server notices hangup + + shutdown(this->clientFd, 1); // Shutdown for transmission only +} + + + +void +client::recvResp(string * const packetBytesP) const { + + char buffer[4096]; + int rc; + + waitForNetworkTransport(); + + rc = recv(this->clientFd, buffer, sizeof(buffer), 0); + + if (rc < 0) + throwf("recv() from socket failed, errno=%d (%s)", + errno, strerror(errno)); + else { + unsigned int bytesReceived(rc); + + *packetBytesP = string(buffer, bytesReceived); + } +} + + + +static void +testEmptyStream(registry const& myRegistry) { +/*---------------------------------------------------------------------------- + Here we send the pstream server an empty stream; i.e. we close the + socket from the client end without sending anything. + + This should cause the server to recognize EOF. +-----------------------------------------------------------------------------*/ + + client client; + + serverPstreamConn server(serverPstreamConn::constrOpt() + .registryP(&myRegistry) + .socketFd(client.serverFd)); + + client.hangup(); + + bool eof; + server.runOnce(&eof); + + TEST(eof); +} + + + +static void +testBrokenPacket(registry const& myRegistry) { +/*---------------------------------------------------------------------------- + Here we send a stream that is not a legal packetsocket stream: it + doesn't have any control word. +-----------------------------------------------------------------------------*/ + client client; + + serverPstreamConn server(serverPstreamConn::constrOpt() + .registryP(&myRegistry) + .socketFd(client.serverFd)); + + client.sendCall("junk"); + client.hangup(); + + bool eof; + + EXPECT_ERROR( + server.runOnce(&eof); + ); +} + + + +static void +testEmptyPacket(registry const& myRegistry) { +/*---------------------------------------------------------------------------- + Here we send the pstream server one empty packet. It should respond + with one packet, being an XML-RPC fault response complaining that the + call is not valid XML. +-----------------------------------------------------------------------------*/ + client client; + + serverPstreamConn server(serverPstreamConn::constrOpt() + .registryP(&myRegistry) + .socketFd(client.serverFd)); + + client.sendCall(packetStart + packetEnd); + + bool eof; + server.runOnce(&eof); + + TEST(!eof); + + string response; + client.recvResp(&response); + + // We ought to validate that the response is a complaint about + // the empty call + + client.hangup(); + + server.runOnce(&eof); + + TEST(eof); +} + + + +static void +testCallInfo(client * const clientP, + serverPstreamConn * const serverP) { + + string const testCallInfoCallStream( + packetStart + testCallInfoCallXml + packetEnd + ); + + string const testCallInfoResponseStream( + packetStart + testCallInfoResponseXml + packetEnd + ); + + clientP->sendCall(testCallInfoCallStream); + + callInfo_test callInfo; + int nointerrupt(0); + bool eof; + serverP->runOnce(&callInfo, &nointerrupt, &eof); + + TEST(!eof); + + string response; + clientP->recvResp(&response); + + TEST(response == testCallInfoResponseStream); +} + + + +static void +testNormalCall(registry const& myRegistry) { + + string const sampleAddGoodCallStream( + packetStart + sampleAddCallXml + packetEnd + ); + + string const sampleAddGoodResponseStream( + packetStart + sampleAddResponseXml + packetEnd + ); + + client client; + + serverPstreamConn server(serverPstreamConn::constrOpt() + .registryP(&myRegistry) + .socketFd(client.serverFd)); + + client.sendCall(sampleAddGoodCallStream); + + bool eof; + + int interrupt(1); + server.runOnce(&interrupt, &eof); // returns without reading socket + TEST(!eof); + + server.runOnce(&eof); + + TEST(!eof); + + string response; + client.recvResp(&response); + + TEST(response == sampleAddGoodResponseStream); + + testCallInfo(&client, &server); + + client.hangup(); + + server.runOnce(&eof); + + TEST(eof); +} + + + +static void +testNoWaitCall(registry const& myRegistry) { + + string const sampleAddGoodCallStream( + packetStart + + xmlPrologue + + "\r\n" + "sample.add\r\n" + "\r\n" + "5\r\n" + "7\r\n" + "\r\n" + "\r\n" + + packetEnd + ); + + + string const sampleAddGoodResponseStream( + packetStart + + xmlPrologue + + "\r\n" + "\r\n" + "12\r\n" + "\r\n" + "\r\n" + + packetEnd + ); + + client client; + + serverPstreamConn server(serverPstreamConn::constrOpt() + .registryP(&myRegistry) + .socketFd(client.serverFd)); + + bool eof; + bool gotOne; + string response; + + server.runOnceNoWait(&eof, &gotOne); + + TEST(!eof); + TEST(!gotOne); + + server.runOnceNoWait(&eof); + + TEST(!eof); + + client.sendCall(sampleAddGoodCallStream); + + server.runOnceNoWait(&eof, &gotOne); + + TEST(!eof); + TEST(gotOne); + + client.recvResp(&response); + + TEST(response == sampleAddGoodResponseStream); + + client.sendCall(sampleAddGoodCallStream); + + server.runOnce(&eof); + + TEST(!eof); + client.recvResp(&response); + TEST(response == sampleAddGoodResponseStream); + + client.hangup(); + + server.runOnce(&eof); + + TEST(eof); +} + + + +static void +testMultiRpcRunNoRpc(registry const& myRegistry) { + + client client; + + serverPstreamConn server(serverPstreamConn::constrOpt() + .registryP(&myRegistry) + .socketFd(client.serverFd)); + + client.hangup(); + + server.run(); +} + + + +static void +testMultiRpcRunOneRpc(registry const& myRegistry) { + + string const sampleAddGoodCallStream( + packetStart + + xmlPrologue + + "\r\n" + "sample.add\r\n" + "\r\n" + "5\r\n" + "7\r\n" + "\r\n" + "\r\n" + + packetEnd + ); + + + string const sampleAddGoodResponseStream( + packetStart + + xmlPrologue + + "\r\n" + "\r\n" + "12\r\n" + "\r\n" + "\r\n" + + packetEnd + ); + + client client; + + serverPstreamConn server(serverPstreamConn::constrOpt() + .registryP(&myRegistry) + .socketFd(client.serverFd)); + + + client.sendCall(sampleAddGoodCallStream); + client.hangup(); + + int interrupt; + + interrupt = 1; + server.run(&interrupt); // Returns without reading socket + + interrupt = 0; + server.run(&interrupt); // Does the buffered RPC + + string response; + client.recvResp(&response); + + TEST(response == sampleAddGoodResponseStream); +} + + + class serverPstreamConnTestSuite : public testSuite { public: @@ -97,14 +644,12 @@ public: 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)); + myRegistry.addMethod("sample.add", + methodPtr(new sampleAddMethod)); + myRegistry.addMethod("test.callinfo", + methodPtr(new testCallInfoMethod)); registryPtr myRegistryP(new registry); @@ -125,43 +670,140 @@ public: .registryP(&myRegistry)); ); - EXPECT_ERROR( // No such file descriptor - serverPstreamConn server(serverPstreamConn::constrOpt() - .registryP(&myRegistry) - .socketFd(37)); - ); + testEmptyStream(myRegistry); + + testBrokenPacket(myRegistry); + + testEmptyPacket(myRegistry); + + testNormalCall(myRegistry); + + testNoWaitCall(myRegistry); + + testMultiRpcRunNoRpc(myRegistry); + + testMultiRpcRunOneRpc(myRegistry); + } +}; + + + +static void +testMultiConnInterrupt(registry const& myRegistry) { + + // We use a nonexistent file descriptor, but the server won't + // ever access it, so it won't know. + + serverPstream server(serverPstream::constrOpt() + .registryP(&myRegistry) + .socketFd(37)); + + int interrupt(1); // interrupt immediately + + server.runSerial(&interrupt); +} + + + +class derivedServer : public xmlrpc_c::serverPstream { +public: + derivedServer(serverPstream::constrOpt const& constrOpt) : + serverPstream(constrOpt), + info("this is my derived server") {} + + string const info; +}; + + + +class multiTestCallInfoMethod : public method2 { + +// The test isn't sophisticated enough actually to do an RPC, so this +// code never runs. We just want to see if it compiles. + +public: + virtual void + execute(paramList const& paramList, + const callInfo * const callInfoPtr, + value * const retvalP) { + + const callInfo_serverPstream * const callInfoP( + dynamic_cast(callInfoPtr)); + + TEST(callInfoP != NULL); - { - serverPstreamConn server(serverPstreamConn::constrOpt() - .registryP(&myRegistry) - .socketFd(devNullFd)); + paramList.verifyEnd(0); - bool eof; - server.runOnce(&eof); - TEST(eof); - } - { - int fd; - createTestFile("junk", &fd); + derivedServer * const derivedServerP( + dynamic_cast(callInfoP->serverP)); - serverPstreamConn server(serverPstreamConn::constrOpt() - .registryP(&myRegistry) - .socketFd(fd)); + TEST(derivedServerP->info == string("this is my derived server")); + + TEST(callInfoP->clientAddr.sa_family == AF_INET); + TEST(callInfoP->clientAddrSize >= sizeof(struct sockaddr_in)); + + *retvalP = value_nil(); + } +}; + +static void +testMultiConnCallInfo() { + + registry myRegistry; + + myRegistry.addMethod("testCallInfo", + methodPtr(new multiTestCallInfoMethod)); + + derivedServer server(serverPstream::constrOpt() + .registryP(&myRegistry) + .socketFd(37)); +} + + + +class multiConnServerTestSuite : public testSuite { + +public: + virtual string suiteName() { + return "multiConnServerTestSuite"; + } + 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( // Empty options + serverPstream::constrOpt opt; + serverPstream server(opt); + ); - bool eof; + EXPECT_ERROR( // No registry + serverPstream server(serverPstream::constrOpt() + .socketFd(3)); + ); - EXPECT_ERROR( // EOF in the middle of a packet - server.runOnce(&eof); - ); - close(fd); - } + EXPECT_ERROR( // No socket fd + serverPstream server(serverPstream::constrOpt() + .registryP(&myRegistry)); + ); + + testMultiConnInterrupt(myRegistry); - close(devNullFd); + testMultiConnCallInfo(); } }; +} // unnamed namespace + + + string serverPstreamTestSuite::suiteName() { return "serverPstreamTestSuite"; @@ -173,5 +815,6 @@ serverPstreamTestSuite::runtests(unsigned int const indentation) { serverPstreamConnTestSuite().run(indentation + 1); + multiConnServerTestSuite().run(indentation + 1); } diff --git a/libs/xmlrpc-c/src/cpp/test/test.cpp b/libs/xmlrpc-c/src/cpp/test/test.cpp index c92653f..e632595 100644 --- a/libs/xmlrpc-c/src/cpp/test/test.cpp +++ b/libs/xmlrpc-c/src/cpp/test/test.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include "xmlrpc-c/girerr.hpp" @@ -13,6 +14,9 @@ using girerr::error; #include "xmlrpc-c/oldcppwrapper.hpp" #include "xmlrpc-c/registry.hpp" +#include "base64.hpp" +#include "xml.hpp" +#include "value.hpp" #include "testclient.hpp" #include "registry.hpp" #include "server_abyss.hpp" @@ -189,7 +193,7 @@ void test_value (void) { XmlRpcValue::makeArray().getArray(); XmlRpcValue::makeStruct().getStruct(); - // Test Base64 values. + // Test byte string values. const unsigned char *b64_data; size_t b64_len; XmlRpcValue val6 = XmlRpcValue::makeBase64((unsigned char*) "a\0\0b", 4); @@ -216,7 +220,7 @@ void test_value (void) { TEST(strct.structSize() == 2); TEST(strct.structHasKey("bar")); TEST(!strct.structHasKey("nosuch")); - for (size_t i = 0; i < strct.structSize(); i++) { + for (int i = 0; i < (int)strct.structSize(); ++i) { string key; XmlRpcValue value; strct.structGetKeyAndValue(i, key, value); @@ -240,285 +244,66 @@ testXmlRpcCpp() { -class intTestSuite : public testSuite { -public: - virtual string suiteName() { - return "intTestSuite"; - } - virtual void runtests(unsigned int const) { - value_int int1(7); - TEST(static_cast(int1) == 7); - value_int int2(-7); - TEST(static_cast(int2) == -7); - value val1(int1); - TEST(val1.type() == value::TYPE_INT); - value_int int3(val1); - TEST(static_cast(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(double1) == 3.14); - value val1(double1); - TEST(val1.type() == value::TYPE_DOUBLE); - value_double double2(val1); - TEST(static_cast(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(boolean1) == true); - value_boolean boolean2(false); - TEST(static_cast(boolean2) == false); - value val1(boolean1); - TEST(val1.type() == value::TYPE_BOOLEAN); - value_boolean boolean3(val1); - TEST(static_cast(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(datetime1) == testTime); - value_datetime datetime2(testTime); - TEST(static_cast(datetime2) == testTime); - value val1(datetime1); - TEST(val1.type() == value::TYPE_DATETIME); - value_datetime datetime3(val1); - TEST(static_cast(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(string1) == "hello world"); - value_string string2("embedded\0null"); - TEST(static_cast(string2) == "embedded\0null"); - value val1(string1); - TEST(val1.type() == value::TYPE_STRING); - value_string string3(val1); - TEST(static_cast(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(string5) == "hello world"); - value_string string6("hello\nthere\rworld\r\n\n", - value_string::nlCode_all); - TEST(static_cast(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(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 - bytestringData(&bytestringArray[0], &bytestringArray[4]); - value_bytestring bytestring1(bytestringData); - - vector const dataReadBack1( - bytestring1.vectorUcharValue()); - TEST(dataReadBack1 == bytestringData); - value val1(bytestring1); - TEST(val1.type() == value::TYPE_BYTESTRING); - value_bytestring bytestring2(val1); - vector 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(int1) == 7); - value_i8 int2(-7); - TEST(static_cast(int2) == -7); - value_i8 int5(1ull << 40); - TEST(static_cast(int5) == (1ull << 40)); - value val1(int1); - TEST(val1.type() == value::TYPE_I8); - value_i8 int3(val1); - TEST(static_cast(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 structData; - pair member("the_integer", value_int(9)); - structData.insert(member); - - value_struct struct1(structData); - - map dataReadBack(struct1); - - TEST(static_cast(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 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 dataReadBack1(array1.vectorValueValue()); - TEST(dataReadBack1[0].type() == value::TYPE_INT); - TEST(static_cast(value_int(dataReadBack1[0])) == 7); - TEST(dataReadBack1[1].type() == value::TYPE_DOUBLE); - TEST(static_cast(value_double(dataReadBack1[1])) == 2.78); - TEST(dataReadBack1[2].type() == value::TYPE_STRING); - TEST(static_cast(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) {} - } -}; +static void +buildParamListWithAdd(paramList * const paramListP, + time_t const timeFuture) { + + paramListP->add(value_int(7)); + paramListP->add(value_boolean(true)).add(value_double(3.14)); + time_t const timeZero(0); + paramListP->add(value_datetime(timeZero)); + paramListP->add(value_datetime(timeFuture)); + paramListP->add(value_string("hello world")); + unsigned char bytestringArray[] = {0x10, 0x11, 0x12, 0x13, 0x14}; + vector + bytestringData(&bytestringArray[0], &bytestringArray[4]); + paramListP->add(value_bytestring(bytestringData)); + vector arrayData; + arrayData.push_back(value_int(7)); + arrayData.push_back(value_double(2.78)); + arrayData.push_back(value_string("hello world")); + paramListP->add(value_array(arrayData)); + map structData; + pair member("the_integer", value_int(9)); + structData.insert(member); + paramListP->add(value_struct(structData)); + paramListP->add(value_nil()); + paramListP->add(value_i8((xmlrpc_int64)UINT_MAX + 1)); +} -class valueTestSuite : public testSuite { +static void +verifyParamList(paramList const& paramList, + time_t const timeFuture) { + + TEST(paramList.size() == 11); + + TEST(paramList.getInt(0) == 7); + TEST(paramList.getInt(0, 7) == 7); + TEST(paramList.getInt(0, -5, 7) == 7); + TEST(paramList.getBoolean(1) == true); + TEST(paramList.getDouble(2) == 3.14); + TEST(paramList.getDouble(2, 1) == 3.14); + TEST(paramList.getDouble(2, 1, 4) == 3.14); + time_t const timeZero(0); + TEST(paramList.getDatetime_sec(3) == timeZero); + TEST(paramList.getDatetime_sec(3, paramList::TC_ANY) == timeZero); + TEST(paramList.getDatetime_sec(3, paramList::TC_NO_FUTURE) + == timeZero); + TEST(paramList.getDatetime_sec(4, paramList::TC_NO_PAST) + == timeFuture); + TEST(paramList.getString(5) == "hello world"); + TEST(paramList.getBytestring(6)[0] == 0x10); + TEST(paramList.getArray(7).size() == 3); + TEST(paramList.getArray(7, 3).size() == 3); + TEST(paramList.getArray(7, 1, 3).size() == 3); + paramList.getStruct(8)["the_integer"]; + paramList.getNil(9); + TEST(paramList.getI8(10) == (xmlrpc_int64)UINT_MAX + 1); + paramList.verifyEnd(11); +} -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 { @@ -529,60 +314,24 @@ public: } virtual void runtests(unsigned int const) { + time_t const timeFuture(time(NULL)+100); + 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 - bytestringData(&bytestringArray[0], &bytestringArray[4]); - paramList1.add(value_bytestring(bytestringData)); - vector 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 structData; - pair 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); + buildParamListWithAdd(¶mList1, timeFuture); + + verifyParamList(paramList1, timeFuture); paramList paramList2(5); TEST(paramList2.size() == 0); + + paramList2.addc(7); + paramList2.addc(true).addc(3.14); + TEST(paramList2.size() == 3); + TEST(paramList2.getInt(0) == 7); + TEST(paramList2.getBoolean(1) == true); + TEST(paramList2.getDouble(2) == 3.14); } }; @@ -604,13 +353,13 @@ main(int argc, char**) { try { // Add your test suites here. + base64TestSuite().run(0); + xmlTestSuite().run(0); valueTestSuite().run(0); paramListTestSuite().run(0); registryTestSuite().run(0); serverAbyssTestSuite().run(0); -#ifndef WIN32 serverPstreamTestSuite().run(0); -#endif clientTestSuite().run(0); testXmlRpcCpp(); diff --git a/libs/xmlrpc-c/src/cpp/test/testclient.cpp b/libs/xmlrpc-c/src/cpp/test/testclient.cpp index 6eadf8d..f8a2b3a 100644 --- a/libs/xmlrpc-c/src/cpp/test/testclient.cpp +++ b/libs/xmlrpc-c/src/cpp/test/testclient.cpp @@ -32,10 +32,12 @@ using namespace std; +namespace { + class sampleAddMethod : public method { public: sampleAddMethod() { - this->_signature = "ii"; + this->_signature = "i:ii"; this->_help = "This method adds two integers together"; } void @@ -78,7 +80,15 @@ public: class clientXmlTransport_direct : public clientXmlTransport { +/*---------------------------------------------------------------------------- + Though this fills the shoes of a client XML transport, it's really a + simulation, because it doesn't transport anything anywhere. The call() + method, which is supposed to transport a call to a server and then + transport the response back, actually just executes the method itself. + Part of a carriage parameter for a transport of this class is the handle + of a method registry, so the transport knows how to execute the method. +-----------------------------------------------------------------------------*/ public: void call(xmlrpc_c::carriageParm * const carriageParmP, @@ -158,6 +168,64 @@ public: +class MyRpc : public rpc { + +public: + MyRpc(std::string const methodName, + paramList const& paramList) : + rpc(methodName, paramList) {} + + void + progress(struct xmlrpc_progress_data const& data) const { + + // The way the tests are currently written, this never actually + // runs; we're just testing for ability to compile. + + cout << "Progress of " << this << ": " + << data.call.total << " " + << data.call.now << " " + << data.response.total << " " + << data.response.now + << endl; + } +}; + + + +class clientDerivedRpcTestSuite : public testSuite { +/*---------------------------------------------------------------------------- + The object of this class tests the ability to derive a class + from xmlrpc_c::rpc in order to override certain methods. +-----------------------------------------------------------------------------*/ +public: + virtual string suiteName() { + return "clientDerivedRpcTestSuite"; + } + 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 paramListSampleAdd; + paramListSampleAdd.add(value_int(5)); + paramListSampleAdd.add(value_int(7)); + { + /* Test a successful RPC */ + rpcPtr rpcSampleAddP(new MyRpc("sample.add", paramListSampleAdd)); + rpcSampleAddP->call(&clientDirect, &carriageParmDirect); + TEST(rpcSampleAddP->isFinished()); + TEST(rpcSampleAddP->isSuccessful()); + value_int const resultDirect(rpcSampleAddP->getResult()); + TEST(static_cast(resultDirect) == 12); + } + } +}; + + + class clientDirectTestSuite : public testSuite { /*---------------------------------------------------------------------------- The object of this class tests the client facilities by using a @@ -241,6 +309,8 @@ public: // Same as above clientDirectAsyncTestSuite().run(indentation+1); + + clientDerivedRpcTestSuite().run(indentation+1); } }; @@ -263,6 +333,7 @@ public: .network_interface("eth0") .no_ssl_verifypeer(true) .no_ssl_verifyhost(true) + .dont_advertise(true) .user_agent("my user agent") .ssl_cert("/etc/sslcert") .sslcerttype("PEM") @@ -278,6 +349,10 @@ public: .randomfile("/dev/random") .egdsocket("/tmp/egdsocket") .ssl_cipher_list("RC4-SHA:DEFAULT") + .proxy("example.com") + .proxy_port(8080) + .proxy_userpwd("password") + .proxy_type(XMLRPC_HTTPPROXY_SOCKS5) ); clientXmlTransport_curl transport5( @@ -831,6 +906,10 @@ public: +} // unnamed namespace + + + string clientTestSuite::suiteName() { return "clientTestSuite"; diff --git a/libs/xmlrpc-c/src/cpp/test/value.cpp b/libs/xmlrpc-c/src/cpp/test/value.cpp new file mode 100644 index 0000000..f8d8e3f --- /dev/null +++ b/libs/xmlrpc-c/src/cpp/test/value.cpp @@ -0,0 +1,453 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#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 "c_util.h" + +#include "tools.hpp" + +#include "value.hpp" + +using namespace xmlrpc_c; +using namespace std; + + + +namespace { + +class intTestSuite : public testSuite { +public: + virtual string suiteName() { + return "intTestSuite"; + } + virtual void runtests(unsigned int const) { + value_int int1(7); + TEST(static_cast(int1) == 7); + value_int int2(-7); + TEST(static_cast(int2) == -7); + value val1(int1); + TEST(val1.type() == value::TYPE_INT); + value_int int3(val1); + TEST(static_cast(int3) == 7); + try { + value_int int4(value_double(3.7)); + TEST_FAILED("invalid cast double-int suceeded"); + } catch (error) {} + + value const int1x(toValue(7)); + TEST(int1x.type() == value::TYPE_INT); + TEST(static_cast(value_int(int1x)) == 7); + + int test1x; + fromValue(test1x, int1x); + TEST(test1x == 7); + } +}; + + + +class doubleTestSuite : public testSuite { +public: + virtual string suiteName() { + return "doubleTestSuite"; + } + virtual void runtests(unsigned int const) { + value_double double1(3.14); + TEST(static_cast(double1) == 3.14); + value val1(double1); + TEST(val1.type() == value::TYPE_DOUBLE); + value_double double2(val1); + TEST(static_cast(double2) == 3.14); + try { + value_double double4(value_int(4)); + TEST_FAILED("invalid cast int-double suceeded"); + } catch (error) {} + + value const double1x(toValue(3.14)); + TEST(double1x.type() == value::TYPE_DOUBLE); + TEST(static_cast(value_double(double1x)) == 3.14); + + double test1x; + fromValue(test1x, double1x); + TEST(test1x == 3.14); + } +}; + + + +class booleanTestSuite : public testSuite { +public: + virtual string suiteName() { + return "booleanTestSuite"; + } + virtual void runtests(unsigned int const) { + value_boolean boolean1(true); + TEST(static_cast(boolean1) == true); + value_boolean boolean2(false); + TEST(static_cast(boolean2) == false); + value val1(boolean1); + TEST(val1.type() == value::TYPE_BOOLEAN); + value_boolean boolean3(val1); + TEST(static_cast(boolean3) == true); + try { + value_boolean boolean4(value_int(4)); + TEST_FAILED("invalid cast int-boolean suceeded"); + } catch (error) {} + + value const boolean1x(toValue(true)); + TEST(boolean1x.type() == value::TYPE_BOOLEAN); + TEST(static_cast(value_boolean(boolean1x)) == true); + + bool test1x; + fromValue(test1x, boolean1x); + TEST(test1x == true); + } +}; + + + +#if XMLRPC_HAVE_TIMEVAL + +static struct timeval +makeTv(time_t const secs, + unsigned int const usecs) { + + struct timeval retval; + + retval.tv_sec = secs; + retval.tv_usec = usecs; + + return retval; +} + +static bool +tvIsEqual(struct timeval const comparand, + struct timeval const comparator) { + return + comparand.tv_sec == comparator.tv_sec && + comparand.tv_usec == comparator.tv_usec; +} +#endif + + + +#if XMLRPC_HAVE_TIMESPEC + +static struct timespec +makeTs(time_t const secs, + unsigned int const usecs) { + + struct timespec retval; + + retval.tv_sec = secs; + retval.tv_nsec = usecs * 1000; + + return retval; +} + +static bool +tsIsEqual(struct timespec const comparand, + struct timespec const comparator) { + return + comparand.tv_sec == comparator.tv_sec && + comparand.tv_nsec == comparator.tv_nsec; +} +#endif + + + +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(datetime1) == testTime); + value_datetime datetime2(testTime); + TEST(static_cast(datetime2) == testTime); + value val1(datetime1); + TEST(val1.type() == value::TYPE_DATETIME); + value_datetime datetime3(val1); + TEST(static_cast(datetime3) == testTime); +#if XMLRPC_HAVE_TIMEVAL + struct timeval const testTimeTv(makeTv(testTime, 0)); + value_datetime datetime4(testTimeTv); + TEST(static_cast(datetime4) == testTime); + TEST(tvIsEqual(static_cast(datetime4), testTimeTv)); +#endif +#if XMLRPC_HAVE_TIMESPEC + struct timespec const testTimeTs(makeTs(testTime, 0)); + value_datetime datetime5(testTimeTs); + TEST(static_cast(datetime5) == testTime); + TEST(tsIsEqual(static_cast(datetime5), testTimeTs)); +#endif + 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(string1) == "hello world"); + value_string string2("embedded\0null"); + TEST(static_cast(string2) == "embedded\0null"); + value val1(string1); + TEST(val1.type() == value::TYPE_STRING); + value_string string3(val1); + TEST(static_cast(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(string5) == "hello world"); + value_string string6("hello\nthere\rworld\r\n\n", + value_string::nlCode_all); + TEST(static_cast(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(string7) == "hello\nthere\rworld\r\n\n"); + + value const string1x(toValue("hello world")); + TEST(string1x.type() == value::TYPE_STRING); + TEST(static_cast(value_string(string1x)) == "hello world"); + + string test1x; + fromValue(test1x, string1x); + TEST(test1x == "hello world"); + + value const string2x(toValue(string("hello world"))); + TEST(string2x.type() == value::TYPE_STRING); + TEST(static_cast(value_string(string2x)) == "hello world"); + } +}; + + + +class bytestringTestSuite : public testSuite { +public: + virtual string suiteName() { + return "bytestringTestSuite"; + } + virtual void runtests(unsigned int const) { + unsigned char bytestringArray[] = {0x10, 0x11, 0x12, 0x13, 0x14}; + cbytestring + bytestringData(&bytestringArray[0], &bytestringArray[4]); + value_bytestring bytestring1(bytestringData); + + cbytestring const dataReadBack1(bytestring1.vectorUcharValue()); + TEST(dataReadBack1 == bytestringData); + value val1(bytestring1); + TEST(val1.type() == value::TYPE_BYTESTRING); + value_bytestring bytestring2(val1); + vector const dataReadBack2( + bytestring2.vectorUcharValue()); + TEST(dataReadBack2 == bytestringData); + try { + value_bytestring bytestring4(value_int(4)); + TEST_FAILED("invalid cast int-bytestring suceeded"); + } catch (error) {} + + value const bytestring1x(toValue(bytestringData)); + TEST(bytestring1x.type() == value::TYPE_BYTESTRING); + vector const dataReadBack1x( + value_bytestring(bytestring1x).vectorUcharValue()); + TEST(dataReadBack1x == bytestringData); + + vector test1x; + fromValue(test1x, bytestring1x); + TEST(test1x == bytestringData); + + } +}; + + + +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(int1) == 7); + value_i8 int2(-7); + TEST(static_cast(int2) == -7); + value_i8 int5(1ull << 40); + TEST(static_cast(int5) == (1ull << 40)); + value val1(int1); + TEST(val1.type() == value::TYPE_I8); + value_i8 int3(val1); + TEST(static_cast(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) { + cstruct structData; + pair member("the_integer", value_int(9)); + structData.insert(member); + + value_struct struct1(structData); + + map dataReadBack(struct1); + + TEST(static_cast(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) {} + + map structDatax; + structDatax["one"] = 1; + structDatax["two"] = 2; + + value const struct5(toValue(structDatax)); + TEST(struct5.type() == value::TYPE_STRUCT); + map dataReadBackx; + dataReadBackx = value_struct(struct5); + + TEST(static_cast(value_int(dataReadBackx["two"])) == 2); + + map test5x; + fromValue(test5x, struct5); + TEST(test5x["two"] == 2); + } +}; + + + +class arrayTestSuite : public testSuite { +public: + virtual string suiteName() { + return "arrayTestSuite"; + } + virtual void runtests(unsigned int const) { + carray 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 dataReadBack1(array1.vectorValueValue()); + TEST(dataReadBack1[0].type() == value::TYPE_INT); + TEST(static_cast(value_int(dataReadBack1[0])) == 7); + TEST(dataReadBack1[1].type() == value::TYPE_DOUBLE); + TEST(static_cast(value_double(dataReadBack1[1])) == 2.78); + TEST(dataReadBack1[2].type() == value::TYPE_STRING); + TEST(static_cast(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) {} + + int const arrayDatax[] = {7, 4}; + + value const array5( + arrayValueArray(arrayDatax, ARRAY_SIZE(arrayDatax))); + TEST(array5.type() == value::TYPE_ARRAY); + TEST(value_array(array5).size() == 2); + vector dataReadBackx(value_array(array5).vectorValueValue()); + + TEST(dataReadBackx.size() == 2); + TEST(static_cast(value_int(dataReadBackx[0])) == 7); + vector test5x; + fromValue(test5x, array5); + TEST(test5x[1] == 4); + + vector arrayDataVec; + arrayDataVec.push_back("hello world"); + value const array6(toValue(arrayDataVec)); + TEST(array6.type() == value::TYPE_ARRAY); + TEST(value_array(array6).size() == 1); + } +}; + + +} // unnamed namespace + + +string +valueTestSuite::suiteName() { + return "valueTestSuite"; +} + + + +void +valueTestSuite::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); +} diff --git a/libs/xmlrpc-c/src/cpp/test/value.hpp b/libs/xmlrpc-c/src/cpp/test/value.hpp new file mode 100644 index 0000000..65d0d90 --- /dev/null +++ b/libs/xmlrpc-c/src/cpp/test/value.hpp @@ -0,0 +1,9 @@ +#include "tools.hpp" + +class valueTestSuite : public testSuite { + +public: + virtual std::string suiteName(); + virtual void runtests(unsigned int const indentation); +}; + diff --git a/libs/xmlrpc-c/src/cpp/test/xml.cpp b/libs/xmlrpc-c/src/cpp/test/xml.cpp new file mode 100644 index 0000000..0a73e24 --- /dev/null +++ b/libs/xmlrpc-c/src/cpp/test/xml.cpp @@ -0,0 +1,100 @@ +/*============================================================================= + xml +=============================================================================== + Test the XML generator and parser C++ facilities of XML-RPC for C/C++. + +=============================================================================*/ + +#include + +#include "xmlrpc-c/girerr.hpp" +using girerr::error; +using girerr::throwf; +#include "xmlrpc-c/base.hpp" +#include "xmlrpc-c/xml.hpp" + +#include "tools.hpp" +#include "xml.hpp" + +using namespace xmlrpc_c; +using namespace std; + + +namespace { + +class callTestSuite : public testSuite { + +public: + virtual string suiteName() { + return "callTestSuite"; + } + virtual void runtests(unsigned int const) { + + string callXml; + + string const methodName0("myMethod"); + paramList const paramList0; + + xml::generateCall(methodName0, paramList(), &callXml); + + string methodName; + paramList paramList; + + xml::parseCall(callXml, &methodName, ¶mList); + + TEST(methodName == methodName0); + TEST(paramList.size() == paramList0.size()); + } +}; + + + +class responseTestSuite : public testSuite { + +public: + virtual string suiteName() { + return "responseTestSuite"; + } + virtual void runtests(unsigned int const) { + + string respXml; + + rpcOutcome outcome0(value_int(7)); + + xml::generateResponse(outcome0, &respXml); + + rpcOutcome outcome; + + xml::parseResponse(respXml, &outcome); + + TEST((int)value_int(outcome.getResult()) == + (int)value_int(outcome0.getResult())); + + value result; + + xml::parseSuccessfulResponse(respXml, &result); + + TEST((int)value_int(result) == (int)value_int(outcome0.getResult())); + } +}; + + + +} // unnamed namespace + + + +string +xmlTestSuite::suiteName() { + return "XMLTestSuite"; +} + + + +void +xmlTestSuite::runtests(unsigned int const indentation) { + + callTestSuite().run(indentation+1); + + responseTestSuite().run(indentation+1); +} diff --git a/libs/xmlrpc-c/src/cpp/test/xml.hpp b/libs/xmlrpc-c/src/cpp/test/xml.hpp new file mode 100644 index 0000000..3946f46 --- /dev/null +++ b/libs/xmlrpc-c/src/cpp/test/xml.hpp @@ -0,0 +1,9 @@ +#include "tools.hpp" + +class xmlTestSuite : public testSuite { + +public: + virtual std::string suiteName(); + virtual void runtests(unsigned int const indentation); +}; + diff --git a/libs/xmlrpc-c/src/cpp/value.cpp b/libs/xmlrpc-c/src/cpp/value.cpp index 6dcba93..3af785c 100644 --- a/libs/xmlrpc-c/src/cpp/value.cpp +++ b/libs/xmlrpc-c/src/cpp/value.cpp @@ -64,6 +64,22 @@ public: this->valueP = xmlrpc_datetime_new_sec(&env.env_c, cppvalue); throwIfError(env); } +#if XMLRPC_HAVE_TIMEVAL + cDatetimeValueWrapper(struct timeval const cppvalue) { + env_wrap env; + + this->valueP = xmlrpc_datetime_new_timeval(&env.env_c, cppvalue); + throwIfError(env); + } +#endif +#if XMLRPC_HAVE_TIMESPEC + cDatetimeValueWrapper(struct timespec const cppvalue) { + env_wrap env; + + this->valueP = xmlrpc_datetime_new_timespec(&env.env_c, cppvalue); + throwIfError(env); + } +#endif ~cDatetimeValueWrapper() { xmlrpc_DECREF(this->valueP); } @@ -93,13 +109,13 @@ public: namespace xmlrpc_c { -value::value() { +value::value() { // default constructor this->cValueP = NULL; } -value::value(xmlrpc_value * const valueP) { // default constructor +value::value(xmlrpc_value * const valueP) { this->instantiate(valueP); } @@ -135,7 +151,7 @@ value::~value() { bool value::isInstantiated() const { /*---------------------------------------------------------------------------- - Return whether the value is actually a value, as opposed to a placeholder + Return whether the object is actually a value, as opposed to a placeholder variable waiting to be assigned a value. -----------------------------------------------------------------------------*/ return (this->cValueP != NULL); @@ -144,6 +160,20 @@ value::isInstantiated() const { void +value::validateInstantiated() const { // private +/*---------------------------------------------------------------------------- + Throw an exception if the object is just a placeholder, rather than an + actual XML-RPC value. +-----------------------------------------------------------------------------*/ + if (!this->cValueP) + throw(error("Reference to xmlrpc_c::value that has not been " + "instantiated. (xmlrpc_c::value::isInstantiated may be " + "useful in diagnosing)")); +} + + + +void value::instantiate(xmlrpc_value * const valueP) { xmlrpc_INCREF(valueP); @@ -168,6 +198,8 @@ value::appendToCArray(xmlrpc_value * const arrayP) const { /*---------------------------------------------------------------------------- Append this value to the C array 'arrayP'. ----------------------------------------------------------------------------*/ + this->validateInstantiated(); + env_wrap env; xmlrpc_array_append_item(&env.env_c, arrayP, this->cValueP); @@ -183,6 +215,8 @@ value::addToCStruct(xmlrpc_value * const structP, /*---------------------------------------------------------------------------- Add this value to the C array 'arrayP' with key 'key'. ----------------------------------------------------------------------------*/ + this->validateInstantiated(); + env_wrap env; xmlrpc_struct_set_value_n(&env.env_c, structP, @@ -196,8 +230,11 @@ value::addToCStruct(xmlrpc_value * const structP, value::type_t value::type() const { + + this->validateInstantiated(); + /* You'd think we could just cast from xmlrpc_type to - value:type_t, but Gcc warns if we do that. So we have to do this + value::type_t, but Gcc warns if we do that. So we have to do this even messier union nonsense. */ union { @@ -212,6 +249,15 @@ value::type() const { +ostream& operator<<(ostream& out, value::type_t const& type) { + + string typeName; + + return out << string(xmlrpc_type_name((xmlrpc_type)type)); +} + + + value_int::value_int(int const cppvalue) { class cWrapper { @@ -249,6 +295,8 @@ value_int::value_int(xmlrpc_c::value const baseValue) { value_int::operator int() const { + this->validateInstantiated(); + int retval; env_wrap env; @@ -260,6 +308,14 @@ value_int::operator int() const { +int +value_int::cvalue() const { + + return static_cast(*this); +} + + + value_double::value_double(double const cppvalue) { class cWrapper { @@ -295,6 +351,8 @@ value_double::value_double(xmlrpc_c::value const baseValue) { value_double::operator double() const { + this->validateInstantiated(); + double retval; env_wrap env; @@ -307,6 +365,14 @@ value_double::operator double() const { +double +value_double::cvalue() const { + + return static_cast(*this); +} + + + value_boolean::value_boolean(bool const cppvalue) { class cWrapper { @@ -331,8 +397,21 @@ value_boolean::value_boolean(bool const cppvalue) { +value_boolean::value_boolean(xmlrpc_c::value const baseValue) { + + if (baseValue.type() != xmlrpc_c::value::TYPE_BOOLEAN) + throw(error("Not boolean type. See type() method")); + else { + this->instantiate(baseValue.cValueP); + } +} + + + value_boolean::operator bool() const { + this->validateInstantiated(); + xmlrpc_bool retval; env_wrap env; @@ -345,13 +424,10 @@ value_boolean::operator bool() const { -value_boolean::value_boolean(xmlrpc_c::value const baseValue) { +bool +value_boolean::cvalue() const { - if (baseValue.type() != xmlrpc_c::value::TYPE_BOOLEAN) - throw(error("Not boolean type. See type() method")); - else { - this->instantiate(baseValue.cValueP); - } + return static_cast(*this); } @@ -393,7 +469,7 @@ value_datetime::value_datetime(time_t const cppvalue) { #if XMLRPC_HAVE_TIMEVAL value_datetime::value_datetime(struct timeval const& cppvalue) { - cDatetimeValueWrapper wrapper(cppvalue.tv_sec); + cDatetimeValueWrapper wrapper(cppvalue); this->instantiate(wrapper.valueP); } @@ -404,7 +480,7 @@ value_datetime::value_datetime(struct timeval const& cppvalue) { #if XMLRPC_HAVE_TIMESPEC value_datetime::value_datetime(struct timespec const& cppvalue) { - cDatetimeValueWrapper wrapper(cppvalue.tv_sec); + cDatetimeValueWrapper wrapper(cppvalue); this->instantiate(wrapper.valueP); } @@ -425,6 +501,8 @@ value_datetime::value_datetime(xmlrpc_c::value const baseValue) { value_datetime::operator time_t() const { + this->validateInstantiated(); + time_t retval; env_wrap env; @@ -436,6 +514,50 @@ value_datetime::operator time_t() const { +#if XMLRPC_HAVE_TIMEVAL + +value_datetime::operator timeval() const { + + this->validateInstantiated(); + + struct timeval retval; + env_wrap env; + + xmlrpc_read_datetime_timeval(&env.env_c, this->cValueP, &retval); + throwIfError(env); + + return retval; +} +#endif + + + +#if XMLRPC_HAVE_TIMESPEC + +value_datetime::operator timespec() const { + + this->validateInstantiated(); + + struct timespec retval; + env_wrap env; + + xmlrpc_read_datetime_timespec(&env.env_c, this->cValueP, &retval); + throwIfError(env); + + return retval; +} +#endif + + + +time_t +value_datetime::cvalue() const { + + return static_cast(*this); +} + + + class cNewStringWrapper { public: xmlrpc_value * valueP; @@ -517,6 +639,8 @@ value_string::crlfValue() const { } }; + this->validateInstantiated(); + cWrapper wrapper(this->cValueP); return string(wrapper.str, wrapper.length); @@ -526,7 +650,7 @@ value_string::crlfValue() const { value_string::operator string() const { - env_wrap env; + this->validateInstantiated(); cStringWrapper adapter(this->cValueP); @@ -535,6 +659,14 @@ value_string::operator string() const { +std::string +value_string::cvalue() const { + + return static_cast(*this); +} + + + value_bytestring::value_bytestring( vector const& cppvalue) { @@ -561,6 +693,17 @@ value_bytestring::value_bytestring( +value_bytestring::value_bytestring(xmlrpc_c::value const baseValue) { + + if (baseValue.type() != xmlrpc_c::value::TYPE_BYTESTRING) + throw(error("Not byte string type. See type() method")); + else { + this->instantiate(baseValue.cValueP); + } +} + + + vector value_bytestring::vectorUcharValue() const { @@ -580,6 +723,8 @@ value_bytestring::vectorUcharValue() const { } }; + this->validateInstantiated(); + cWrapper wrapper(this->cValueP); return vector(&wrapper.contents[0], @@ -588,9 +733,19 @@ value_bytestring::vectorUcharValue() const { +vector +value_bytestring::cvalue() const { + + return this->vectorUcharValue(); +} + + + size_t value_bytestring::length() const { + this->validateInstantiated(); + env_wrap env; size_t length; @@ -602,17 +757,6 @@ value_bytestring::length() const { -value_bytestring::value_bytestring(xmlrpc_c::value const baseValue) { - - if (baseValue.type() != xmlrpc_c::value::TYPE_BYTESTRING) - throw(error("Not byte string type. See type() method")); - else { - this->instantiate(baseValue.cValueP); - } -} - - - value_array::value_array(vector const& cppvalue) { class cWrapper { @@ -655,6 +799,8 @@ value_array::value_array(xmlrpc_c::value const baseValue) { vector value_array::vectorValueValue() const { + this->validateInstantiated(); + env_wrap env; unsigned int arraySize; @@ -693,9 +839,19 @@ value_array::vectorValueValue() const { +vector +value_array::cvalue() const { + + return this->vectorValueValue(); +} + + + size_t value_array::size() const { + this->validateInstantiated(); + env_wrap env; unsigned int arraySize; @@ -752,6 +908,8 @@ value_struct::value_struct(xmlrpc_c::value const baseValue) { value_struct::operator map() const { + this->validateInstantiated(); + env_wrap env; unsigned int structSize; @@ -796,6 +954,14 @@ value_struct::operator map() const { +map +value_struct::cvalue() const { + + return static_cast >(*this); +} + + + value_nil::value_nil() { class cWrapper { @@ -831,6 +997,14 @@ value_nil::value_nil(xmlrpc_c::value const baseValue) { +void * +value_nil::cvalue() const { + + return NULL; +} + + + value_i8::value_i8(xmlrpc_int64 const cppvalue) { class cWrapper { @@ -868,6 +1042,8 @@ value_i8::value_i8(xmlrpc_c::value const baseValue) { value_i8::operator xmlrpc_int64() const { + this->validateInstantiated(); + xmlrpc_int64 retval; env_wrap env; @@ -879,4 +1055,12 @@ value_i8::operator xmlrpc_int64() const { +xmlrpc_int64 +value_i8::cvalue() const { + + return static_cast(*this); +} + + + } // namespace diff --git a/libs/xmlrpc-c/src/cpp/xml.cpp b/libs/xmlrpc-c/src/cpp/xml.cpp index 9c57bf3..79802b9 100644 --- a/libs/xmlrpc-c/src/cpp/xml.cpp +++ b/libs/xmlrpc-c/src/cpp/xml.cpp @@ -21,14 +21,38 @@ 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. + at the end of a scope -- even if the scope ends with a throw. -----------------------------------------------------------------------------*/ public: - xmlrpc_value * valueP; + xmlrpc_value * const valueP; cValueWrapper(xmlrpc_value * valueP) : valueP(valueP) {} ~cValueWrapper() { xmlrpc_DECREF(valueP); } }; + + +class cStringWrapper { +public: + const char * const cString; + cStringWrapper(const char * const cString) : cString(cString) {} + ~cStringWrapper() { xmlrpc_strfree(cString); } +}; + + + +class memblockWrapper { + xmlrpc_mem_block * const memblockP; +public: + memblockWrapper(xmlrpc_mem_block * const memblockP) : + memblockP(memblockP) {} + + ~memblockWrapper() { + XMLRPC_MEMBLOCK_FREE(char, memblockP); + } +}; + + + xmlrpc_value * cArrayFromParamList(paramList const& paramList) { @@ -53,6 +77,42 @@ cArrayFromParamList(paramList const& paramList) { return paramArrayP; } + + +paramList const +paramListFromCArray(xmlrpc_value * const cArrayP) { + + paramList retval; + env_wrap env; + + unsigned int const nParam(xmlrpc_array_size(&env.env_c, cArrayP)); + + if (!env.env_c.fault_occurred) { + for (unsigned int i = 0; + i < nParam && !env.env_c.fault_occurred; + ++i) { + + xmlrpc_value * cParamP; + + xmlrpc_array_read_item(&env.env_c, cArrayP, i, &cParamP); + + if (!env.env_c.fault_occurred) { + + cValueWrapper const paramAuto(cParamP); + // Causes xmlrpc_DECREF(cParamP) at end of scope + + retval.add(cParamP); + } + } + } + if (env.env_c.fault_occurred) + throw(error(env.env_c.fault_string)); + + return retval; +} + + + } // namespace @@ -71,17 +131,6 @@ generateCall(string const& methodName, Use dialect 'dialect' of XML-RPC. -----------------------------------------------------------------------------*/ - class memblockWrapper { - xmlrpc_mem_block * const memblockP; - public: - memblockWrapper(xmlrpc_mem_block * const memblockP) : - memblockP(memblockP) {} - - ~memblockWrapper() { - XMLRPC_MEMBLOCK_FREE(char, memblockP); - } - }; - xmlrpc_mem_block * callXmlMP; env_wrap env; @@ -118,6 +167,86 @@ generateCall(string const& methodName, void +parseCall(string const& callXml, + string * const methodNameP, + paramList * const paramListP) { + + env_wrap env; + const char * c_methodName; + xmlrpc_value * c_paramArrayP; + + xmlrpc_parse_call(&env.env_c, callXml.c_str(), callXml.size(), + &c_methodName, &c_paramArrayP); + + if (env.env_c.fault_occurred) + throw(error(env.env_c.fault_string)); + else { + cValueWrapper const paramListAuto(c_paramArrayP); + // Causes XMLRPC_decref(c_paramArrayP) at end of scope + cStringWrapper const methodNameAuto(c_methodName); + // Causes xmlrpc_strfree(c_methodName) at end of scope + + *paramListP = paramListFromCArray(c_paramArrayP); + *methodNameP = string(c_methodName); + } +} + + + +void +generateResponse(rpcOutcome const& outcome, + xmlrpc_dialect const dialect, + string * const respXmlP) { +/*---------------------------------------------------------------------------- + Generate the XML for an XML-RPC resp, given the RPC outcome. + + Use dialect 'dialect' of XML-RPC. +-----------------------------------------------------------------------------*/ + xmlrpc_mem_block * respXmlMP; + env_wrap env; + + respXmlMP = XMLRPC_MEMBLOCK_NEW(char, &env.env_c, 0); + if (!env.env_c.fault_occurred) { + memblockWrapper respXmlAuto(respXmlMP); + // Makes respXmlMP get freed at end of scope + + if (outcome.succeeded()) { + cValueWrapper cResult(outcome.getResult().cValue()); + + xmlrpc_serialize_response2(&env.env_c, respXmlMP, + cResult.valueP, dialect); + + *respXmlP = string(XMLRPC_MEMBLOCK_CONTENTS(char, respXmlMP), + XMLRPC_MEMBLOCK_SIZE(char, respXmlMP)); + } else { + env_wrap cFault; + + xmlrpc_env_set_fault(&cFault.env_c, outcome.getFault().getCode(), + outcome.getFault().getDescription().c_str()); + + xmlrpc_serialize_fault(&env.env_c, respXmlMP, &cFault.env_c); + + *respXmlP = string(XMLRPC_MEMBLOCK_CONTENTS(char, respXmlMP), + XMLRPC_MEMBLOCK_SIZE(char, respXmlMP)); + } + } + if (env.env_c.fault_occurred) + throw(error(env.env_c.fault_string)); +} + + + +void +generateResponse(rpcOutcome const& outcome, + string * const respXmlP) { + + generateResponse(outcome, xmlrpc_dialect_i8, respXmlP); + +} + + + +void parseResponse(string const& responseXml, rpcOutcome * const outcomeP) { /*---------------------------------------------------------------------------- diff --git a/libs/xmlrpc-c/src/double.c b/libs/xmlrpc-c/src/double.c index 1968d40..f96728b 100644 --- a/libs/xmlrpc-c/src/double.c +++ b/libs/xmlrpc-c/src/double.c @@ -3,6 +3,7 @@ #include #include "xmlrpc-c/util.h" +#include "xmlrpc-c/util_int.h" #include "double.h" @@ -34,8 +35,8 @@ bufferConcat(buffer * const bufferP, if (bufferP->bytes) { if (bufferP->next >= bufferP->end) { - unsigned int const oldSize = bufferP->end - bufferP->bytes; - unsigned int const newSize = oldSize + 64; + size_t const oldSize = bufferP->end - bufferP->bytes; + size_t const newSize = oldSize + 64; bufferP->bytes = realloc(bufferP->bytes, newSize); bufferP->next = bufferP->bytes + oldSize; bufferP->end = bufferP->bytes + newSize; @@ -58,6 +59,23 @@ digitChar(unsigned int const digitValue) { +static unsigned int +leadDigit(double const arg, + double const precision) { +/*---------------------------------------------------------------------------- + Assuming 'arg' has one digit before the decimal point (which may be zero), + return that digit. + + We assume the precision of 'arg' is plus or minus 'precision', and bias our + estimation of the first digit up. We do that bias in order to bias toward + shorter decimal ciphers: It's cleaner to consider 2.9999999 to be 3 than to + consider 3 to be 2.999999. +-----------------------------------------------------------------------------*/ + return MIN(9, (unsigned int)(arg + precision)); +} + + + static void floatWhole(double const value, buffer * const formattedP, @@ -88,7 +106,8 @@ floatWhole(double const value, */ leastValue = 0; } else - leastValue = (unsigned int)(value - nonLeastAmount * 10); + leastValue = leadDigit(value - nonLeastAmount * 10, + nonLeastPrecision * 10); bufferConcat(formattedP, digitChar(leastValue)); @@ -120,7 +139,7 @@ floatFractionPart(double const value, unsigned int digitValue; d *= 10; - digitValue = (unsigned int) d; + digitValue = leadDigit(d, precision); d -= digitValue; @@ -154,7 +173,7 @@ floatFraction(double const value, precision = DBL_EPSILON; while (d > precision) { - unsigned int const digitValue = (unsigned int) d; + unsigned int const digitValue = leadDigit(d, precision); bufferConcat(formattedP, digitChar(digitValue)); diff --git a/libs/xmlrpc-c/src/json.c b/libs/xmlrpc-c/src/json.c new file mode 100644 index 0000000..e422687 --- /dev/null +++ b/libs/xmlrpc-c/src/json.c @@ -0,0 +1,1466 @@ +/*============================================================================= + json.c +=============================================================================== + + Bo Lorentsen (bl@lue.dk) had the idea to do XML-RPC values in JSON + and wrote the original version of this code in February and March + 2010. + + Bryan Henderson restructured the code and improved diagnostic information + (made it tell you where the JSON is screwed up) before its first release + in XML-RPC for C and C++ in Release 1.22. + + JSON: RFC-4627 +=============================================================================*/ + +#include "xmlrpc_config.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "xmlrpc-c/json.h" +#include "xmlrpc-c/util.h" +#include "xmlrpc-c/base_int.h" +#include "xmlrpc-c/string_int.h" +#include "xmlrpc-c/string_number.h" + + + +/*============================================================================= + Tokenizer for the json parser +=============================================================================*/ +enum ttype { + typeNone, + typeOpenBrace, + typeCloseBrace, + typeOpenBracket, + typeCloseBracket, + typeColon, + typeComma, + typeString, + typeInteger, + typeFloat, + typeNull, + typeUndefined, + typeTrue, + typeFalse, + typeEof, +} ; + +static const char * +tokTypeName(enum ttype const type) { + + switch (type) { + case typeNone: return "None"; + case typeOpenBrace: return "Open brace"; + case typeCloseBrace: return "Close brace"; + case typeOpenBracket: return "Open bracket"; + case typeCloseBracket: return "Close bracket"; + case typeColon: return "Colon"; + case typeComma: return "Comma"; + case typeString: return "String"; + case typeInteger: return "Integer"; + case typeFloat: return "Float"; + case typeNull: return "Null"; + case typeUndefined: return "Undefined"; + case typeTrue: return "True"; + case typeFalse: return "False"; + case typeEof: return "Eof"; + default: return "???"; + } +} + + + +typedef struct { + const char * original; + size_t size; + const char * begin; + const char * end; + enum ttype type; +} Tokenizer; + + + +static void +initializeTokenizer(Tokenizer * const tokP, + const char * const str) { + + tokP->original = str; + tokP->end = str; /* end of the "previous" token */ + tokP->type = typeNone; +} + + + +static void +terminateTokenizer(Tokenizer * const tokP ATTR_UNUSED ) { + +} + + + +struct docPosition { + /* A position in the document, as meaningful to the user */ + unsigned int lineNum; /* First line is 1 */ + unsigned int colNum; /* First column is 1 */ +}; + + + +static struct docPosition +currentDocumentPosition(Tokenizer * const tokP) { +/*---------------------------------------------------------------------------- + Return the document position (line & column) of the start of the current + token +-----------------------------------------------------------------------------*/ + struct docPosition retval; + + unsigned int curLine; + unsigned int curCol; + const char * cursor; + + curLine = 0; + curCol = 0; + + for (cursor = tokP->original; cursor < tokP->begin; ++cursor) { + ++curCol; + + if (*cursor == '\n') { + ++curLine; + curCol = 0; + } + } + retval.lineNum = curLine + 1; + retval.colNum = curCol + 1; + + return retval; +} + + + +static void +setParseErr(xmlrpc_env * const envP, + Tokenizer * const tokP, + const char * const format, + ...) { + + struct docPosition const pos = currentDocumentPosition(tokP); + + va_list args; + const char * msg; + + XMLRPC_ASSERT(envP != NULL); + XMLRPC_ASSERT(format != NULL); + + va_start(args, format); + + xmlrpc_vasprintf(&msg, format, args); + + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_PARSE_ERROR, + "JSON parse error at Line %u, Column %u: %s", + pos.lineNum, pos.colNum, msg); + + xmlrpc_strfree(msg); + + va_end(args); +} + + + +static void +finishStringToken(xmlrpc_env * const envP, + Tokenizer * const tokP) { + + ++tokP->end; + + while (*tokP->end != '"' && *tokP->end != '\0' && !envP->fault_occurred) { + if (*tokP->end == '\\') { + ++tokP->end; + switch (*tokP->end) { + case '"': + case '\\': + case '/': + case 'b': + case 'f': + case 'n': + case 'r': + case 't': + ++tokP->end; + break; + case 'u': { + const char * cur; + + ++tokP->end; + + cur = tokP->end; + + while (isxdigit(*cur) && cur - tokP->end < 4) + ++cur; + + if (cur - tokP->end < 4) + setParseErr(envP, tokP, + "hex unicode must contain 4 digits. " + "There are only %u here", cur - tokP->end); + else + tokP->end = cur; + } break; + + default: + setParseErr(envP, tokP, "unknown escape character " + "after backslash: '%c'", *tokP->end); + } + } else + ++tokP->end; + } + if (!envP->fault_occurred) { + if (*tokP->end == '\0') + setParseErr(envP, tokP, "JSON document ends in the middle " + "of a backslash escape sequence"); + else { + ++tokP->end; + tokP->size = (tokP->end - tokP->begin) - 1; + } + } +} + + + +static bool +isInteger(const char * const token, + unsigned int const tokSize) { + + if (tokSize < 1) + return false; + else { + unsigned int i; + + i = 0; + + if (token[0] == '-') + ++i; + + while (i < tokSize) { + if (!isdigit(token[i])) + return false; + ++i; + } + return true; + } +} + + + +static bool +isFloat(const char * const token, + unsigned int const tokSize) { + + unsigned int i; + bool seenPeriod; + bool seenDigit; + + seenPeriod = false; + seenDigit = false; + i = 0; + + if (tokSize >= 1 && token[0] == '-') + ++i; + + while (i < tokSize) { + char const c = token[i]; + + if (c == 'e') + return isInteger(&token[i], tokSize - i); + else if (c == '.') { + if (seenPeriod) { + /* It's a second period */ + return false; + } else { + seenPeriod = true; + } + } else if (isdigit(c)) + seenDigit = true; + else + return false; + ++i; + } + if (seenDigit) + return true; + else + return false; +} + + + +static bool +isWordChar(char const candidate) { +/*---------------------------------------------------------------------------- + Return true iff 'candidate' is a character that can be in a "word" token. + A word token is a multi-character token that is either a JSON keyword or a + number. +-----------------------------------------------------------------------------*/ + return (isalnum(candidate) || candidate == '.' || candidate == '-'); +} + + + +static void +finishAlphanumericWordToken(Tokenizer * const tokP) { + + ++tokP->end; + + while (isWordChar(*tokP->end)) + ++tokP->end; + + tokP->size = tokP->end - tokP->begin; +} + + + +static void +finishDelimiterToken(Tokenizer * const tokP) { + + ++tokP->end; + tokP->size = tokP->end - tokP->begin; +} + + + +static bool +atComment(Tokenizer * const tokP) { + + return (*tokP->begin == '/' && *(tokP->begin + 1) == '/'); +} + + + +static void +advancePastWhiteSpace(Tokenizer * const tokP) { + + while (isspace(*tokP->begin)) + ++tokP->begin; +} + + + +static void +advancePastComments(Tokenizer * const tokP) { +/*---------------------------------------------------------------------------- + Advance the pointer over any comments. +-----------------------------------------------------------------------------*/ + while (atComment(tokP)) { + /* A comment ends at a newline or end of document */ + while (*tokP->begin != '\n' && *tokP->begin != '\0') + ++tokP->begin; + } +} + + + +static void +advanceToNextToken(Tokenizer * const tokP) { +/*---------------------------------------------------------------------------- + Advance the pointer over any white space and comments to the next + token, or end of document, whichever comes first. +-----------------------------------------------------------------------------*/ + + while (*tokP->begin != '\0' && + (isspace(*tokP->begin) || atComment(tokP))) { + + advancePastWhiteSpace(tokP); + + advancePastComments(tokP); + } +} + + + +static void +getToken(xmlrpc_env * const envP, + Tokenizer * const tokP) { + + /* The token starts where the last one left off */ + tokP->begin = tokP->end; + + advanceToNextToken(tokP); + + if (*tokP->begin == '\0') { + /* End of document */ + tokP->end = tokP->begin; + tokP->type = typeEof; + tokP->size = tokP->end - tokP->begin; + } else { + tokP->end = tokP->begin; /* initial value */ + + if (*tokP->begin == '{') { + finishDelimiterToken(tokP); + tokP->type = typeOpenBrace; + } else if (*tokP->begin == '}') { + finishDelimiterToken(tokP); + tokP->type = typeCloseBrace; + } else if (*tokP->begin == '[') { + finishDelimiterToken(tokP); + tokP->type = typeOpenBracket; + } else if (*tokP->begin == ']') { + finishDelimiterToken(tokP); + tokP->type = typeCloseBracket; + } else if (*tokP->begin == ':') { + finishDelimiterToken(tokP); + tokP->type = typeColon; + } else if (*tokP->begin == ',') { + finishDelimiterToken(tokP); + tokP->type = typeComma; + } else if (*tokP->begin == '"') { + finishStringToken(envP, tokP); + + if (!envP->fault_occurred) + tokP->type = typeString; + } else { + if (isWordChar(*tokP->begin)) { + finishAlphanumericWordToken(tokP); + + if (isInteger(tokP->begin, tokP->size)) + tokP->type = typeInteger; + else if (isFloat(tokP->begin, tokP->size)) + tokP->type = typeFloat; + else if (xmlrpc_strneq(tokP->begin, "null", tokP->size)) + tokP->type = typeNull; + else if (xmlrpc_strneq(tokP->begin, "undefined", tokP->size)) + tokP->type = typeUndefined; + else if(xmlrpc_strneq(tokP->begin, "false", tokP->size)) + tokP->type = typeFalse; + else if(xmlrpc_strneq(tokP->begin, "true", tokP->size)) + tokP->type = typeTrue; + else + setParseErr(envP, tokP, "Invalid word token -- " + "Not a valid integer, floating point " + "number, 'null', 'true', or 'false'"); + } else { + setParseErr(envP, tokP, + "Not a valid token -- starts with '%c'; " + "a valid token starts with " + "one of []{}:,\"-. or digit or letter", + *tokP->begin); + } + } + } +} + + + +/*===========================================================================*/ + + + +static int +utf8Decode(uint32_t const c, + char * const out) { +/*--------------------------------------------------------------------------- + convert a unicode char to a utf8 char +---------------------------------------------------------------------------*/ + if (c <= 0x7F) { /* 0XXX XXXX one byte */ + out[0] = (char) c; + return 1; + } else if (c <= 0x7FF) { /* 110X XXXX two bytes */ + out[0] = (char)( 0xC0 | (c >> 6) ); + out[1] = (char)( 0x80 | (c & 0x3F) ); + return 2; + } else if (c <= 0xFFFF) { /* 1110 XXXX three bytes */ + out[0] = (char) (0xE0 | (c >> 12)); + out[1] = (char) (0x80 | ((c >> 6) & 0x3F)); + out[2] = (char) (0x80 | (c & 0x3F)); + return 3; + } else if (c <= 0x1FFFFF) { /* 1111 0XXX four bytes */ + out[0] = (char) (0xF0 | (c >> 18)); + out[1] = (char) (0x80 | ((c >> 12) & 0x3F)); + out[2] = (char) (0x80 | ((c >> 6) & 0x3F)); + out[3] = (char) (0x80 | (c & 0x3F)); + return 4; + } else + return 0; +} + + + +static void +getBackslashSequence(xmlrpc_env * const envP, + const char * const cur, + xmlrpc_mem_block * const memBlockP, + unsigned int * const nBytesConsumedP) { + + char buffer[5]; + unsigned int tsize; + + switch (*cur) { + case '"': + buffer[0] = '"'; + tsize = 1; + *nBytesConsumedP = 1; + break; + case '/': + buffer[0] = '/'; + tsize = 1; + *nBytesConsumedP = 1; + break; + case '\\': + buffer[0] = '\\'; + tsize = 1; + *nBytesConsumedP = 1; + break; + case 'b': + buffer[0] = '\b'; + tsize = 1; + *nBytesConsumedP = 1; + break; + case 'f': + buffer[0] = '\f'; + tsize = 1; + *nBytesConsumedP = 1; + break; + case 'n': + buffer[0] = '\n'; + tsize = 1; + *nBytesConsumedP = 1; + break; + case 'r': + buffer[0] = '\r'; + tsize = 1; + *nBytesConsumedP = 1; + break; + case 't': + buffer[0] = '\t'; + tsize = 1; + *nBytesConsumedP = 1; + break; + case 'u': { + long digit; + strncpy(buffer, cur + 1, 4); + digit = strtol(buffer, NULL, 16); + tsize = utf8Decode(digit, buffer); + *nBytesConsumedP = 5; /* uXXXX */ + break; + } + default: + xmlrpc_faultf(envP, "Invalid character after backslash " + "escape: '%c'", *cur); + *nBytesConsumedP = 0; /* quiet compiler warning */ + tsize = 0; /* quiet compiler warning */ + } + if (!envP->fault_occurred) + XMLRPC_MEMBLOCK_APPEND(char, envP, memBlockP, buffer, tsize ); +} + + + +static void +unescapeString(xmlrpc_env * const envP, + const char * const begin, + const char * const end, + xmlrpc_mem_block * const memBlockP) { + + XMLRPC_MEMBLOCK_INIT(char, envP, memBlockP, 0); + + if (!envP->fault_occurred) { + const char * cur; + const char * last; + + cur = begin; + last = cur; + + while (cur != end && !envP->fault_occurred) { + if (*cur == '\\') { + if (cur != last) { + XMLRPC_MEMBLOCK_APPEND( + char, envP, memBlockP, last, cur - last ); + if (!envP->fault_occurred) + last = cur; + } + if (!envP->fault_occurred) { + unsigned int nBytesConsumed; + + cur += 1; /* consume slash */ + + getBackslashSequence(envP, cur, memBlockP, + &nBytesConsumed); + + if (!envP->fault_occurred) { + cur += nBytesConsumed; + last = cur; + } + } + } else + ++cur; + } + if (!envP->fault_occurred) { + if (cur != last) { + XMLRPC_MEMBLOCK_APPEND(char, envP, + memBlockP, last, cur - last ); + } + } + if (!envP->fault_occurred) { + /* Append terminating NUL */ + XMLRPC_MEMBLOCK_APPEND(char, envP, memBlockP, "", 1); + } + if (envP->fault_occurred) + XMLRPC_MEMBLOCK_CLEAN(char, memBlockP); + } +} + + + +static xmlrpc_value * +makeUtf8String(xmlrpc_env * const envP, + const char * const begin, + const char * const end) { +/*---------------------------------------------------------------------------- + Copy a json string directly into a string value, and convert any json + escaping (\uXXXX) to something acceptable to the internal string handling. + + Try to do this in as few chunks as possible ! +-----------------------------------------------------------------------------*/ + xmlrpc_value * valP; + + xmlrpc_createXmlrpcValue(envP, &valP); + + if (!envP->fault_occurred) { + valP->_type = XMLRPC_TYPE_STRING; + valP->_wcs_block = NULL; + + if (!envP->fault_occurred) + unescapeString(envP, begin, end, &valP->_block); + + if (envP->fault_occurred) + xmlrpc_DECREF(valP); + } + return valP; +} + + + +static xmlrpc_value * +stringTokenValue(xmlrpc_env * const envP, + Tokenizer * const tokP) { + + xmlrpc_env env; + xmlrpc_value * valP; + + xmlrpc_env_init(&env); + + assert(tokP->end >= tokP->begin + 2); + assert(*tokP->begin == '"'); + assert(*(tokP->end-1) == '"'); + + valP = makeUtf8String(&env, tokP->begin + 1, tokP->end - 1); + + if (env.fault_occurred) { + setParseErr(envP, tokP, "Error in string token: %s", + env.fault_string); + } + xmlrpc_env_clean(&env); + + return valP; +} + + + +static xmlrpc_value * +integerTokenValue(xmlrpc_env * const envP, + Tokenizer * const tokP) { + + xmlrpc_env env; + char valueString[tokP->size + 1]; + xmlrpc_int64 value; + xmlrpc_value * valP; + + xmlrpc_env_init(&env); + + memcpy(valueString, tokP->begin, tokP->size); + valueString[tokP->size] = '\0'; + + xmlrpc_parse_int64(&env, valueString, &value); + + if (env.fault_occurred) + setParseErr(envP, tokP, "Error in integer token value '%s': %s", + tokP->begin, env.fault_string); + else + valP = xmlrpc_i8_new(envP, value); + + xmlrpc_env_clean(&env); + + return valP; +} + + + +/* Forward declarations for recursion: */ + +static xmlrpc_value * +parseValue(xmlrpc_env * const envP, + Tokenizer * const tokP); + +static xmlrpc_value * +parseList(xmlrpc_env * const envP, + Tokenizer * const tokP); + +static xmlrpc_value * +parseObject(xmlrpc_env * const envP, + Tokenizer * const tokP); + + + +static void +parseListElement(xmlrpc_env * const envP, + Tokenizer * const tokP, + xmlrpc_value * const listArrayP, + bool * const endOfListP) { + + xmlrpc_value * itemP; + + itemP = parseValue(envP, tokP); + + if (!envP->fault_occurred) { + xmlrpc_array_append_item(envP, listArrayP, itemP); + + if (!envP->fault_occurred) { + getToken(envP, tokP); + if (!envP->fault_occurred) { + if (tokP->type == typeComma) { + *endOfListP = false; + } else if (tokP->type == typeCloseBracket) + *endOfListP = true; + else + setParseErr(envP, tokP, + "Need comma or close bracket " + "after array item. Instead we have %s", + tokTypeName(tokP->type)); + } + } + xmlrpc_DECREF(itemP); + } +} + + + +static xmlrpc_value * +parseList(xmlrpc_env * const envP, + Tokenizer * const tokP) { + + xmlrpc_value * retval; + + XMLRPC_ASSERT_ENV_OK(envP); + + retval = xmlrpc_array_new(envP); + + if (!envP->fault_occurred) { + bool endOfList; + for (endOfList = false; !endOfList && !envP->fault_occurred; ) { + getToken(envP,tokP); + + if (!envP->fault_occurred) { + if (tokP->type == typeEof) + endOfList = true; + else if (tokP->type == typeCloseBracket) + endOfList = true; + else + parseListElement(envP, tokP, retval, &endOfList); + } + } + if (envP->fault_occurred) + xmlrpc_DECREF(retval); + } + return retval; +} + + + +static void +parseObjectMemberValue(xmlrpc_env * const envP, + Tokenizer * const tokP, + xmlrpc_value * const keyP, + xmlrpc_value * const objectP) { + + xmlrpc_value * valP; + + getToken(envP,tokP); + + if (!envP->fault_occurred) { + valP = parseValue(envP, tokP); + + if (!envP->fault_occurred) { + xmlrpc_struct_set_value_v(envP, objectP, keyP, valP); + + xmlrpc_DECREF(valP); + } + } +} + + + +static void +parseObjectMember(xmlrpc_env * const envP, + Tokenizer * const tokP, + xmlrpc_value * const objectP) { + + xmlrpc_env env; + xmlrpc_value * keyP; + + xmlrpc_env_init(&env); + + /* The current token is the string which is the member name: */ + assert(tokP->type = typeString); + assert(tokP->end >= tokP->begin + 2); + assert(*tokP->begin == '"'); + assert(*(tokP->end-1) == '"'); + + keyP = makeUtf8String(&env, tokP->begin + 1, tokP->end - 1); + + if (env.fault_occurred) + setParseErr(envP, tokP, "Error in what is supposed to be " + "the key of a member of an object: %s", + env.fault_string); + else { + getToken(envP, tokP); + + if (!envP->fault_occurred) { + if (tokP->type == typeColon) + parseObjectMemberValue(envP, tokP, keyP, objectP); + else + setParseErr(envP, tokP, + "Need a colon after member key " + "in object. Instead we have %s", + tokTypeName(tokP->type)); + } + xmlrpc_DECREF(keyP); + } + xmlrpc_env_clean(&env); +} + + + +static xmlrpc_value * +parseObject(xmlrpc_env * const envP, + Tokenizer * const tokP) { + + xmlrpc_value * retval; + + XMLRPC_ASSERT_ENV_OK(envP); + + retval = xmlrpc_struct_new(envP); + + if (!envP->fault_occurred) { + bool objectDone; + + objectDone = false; + while (!objectDone && !envP->fault_occurred) { + getToken(envP, tokP); + + if (!envP->fault_occurred) { + if (tokP->type == typeCloseBrace) { + objectDone = true; + } else if (tokP->type == typeString) { + parseObjectMember(envP, tokP, retval); + + if (!envP->fault_occurred) { + getToken(envP, tokP); + + if (!envP->fault_occurred) { + if (tokP->type == typeComma) { + /* member separator; keep going */ + } else if (tokP->type == typeCloseBrace) { + /* No more members in this object */ + objectDone = true; + } else + setParseErr( + envP, tokP, + "Need a comma or close brace after object " + "member. Instead we have %s", + tokTypeName(tokP->type)); + } + } + } else { + setParseErr(envP, tokP, + "Need a string (i.e. starting with " + "a quotation mark) as member key " + "in object, or closing brace to end the " + "object. Instead we have %s", + tokTypeName(tokP->type)); + } + } + } + if (envP->fault_occurred) + xmlrpc_DECREF(retval); + } + return retval; +} + + + + + +static xmlrpc_value * +parseValue(xmlrpc_env * const envP, + Tokenizer * const tokP) { + + xmlrpc_value * retval; + + XMLRPC_ASSERT_ENV_OK(envP); + + switch (tokP->type) { + + case typeOpenBracket: + retval = parseList(envP, tokP); + break; + + case typeOpenBrace: + retval = parseObject(envP, tokP); + break; + + case typeNull: + retval = xmlrpc_nil_new(envP); + break; + + case typeUndefined: + retval = xmlrpc_nil_new(envP); + break; + + case typeFalse: + retval = xmlrpc_bool_new(envP, (xmlrpc_bool)false); + break; + + case typeTrue: + retval = xmlrpc_bool_new(envP, (xmlrpc_bool)true); + break; + + case typeInteger: + retval = integerTokenValue(envP, tokP); + break; + + case typeFloat: + retval = xmlrpc_double_new(envP, strtod(tokP->begin, NULL)); + break; + + case typeString: + retval = stringTokenValue(envP, tokP); + break; + + default: + retval = NULL; + setParseErr(envP, tokP, "Invalid token " + "where a value is supposed to begin: %s. " + "Should be an open bracket, open brace, " + "'null', 'false', 'true', a number, or a string", + tokTypeName(tokP->type)); + } + return retval; +} + + + +xmlrpc_value * +xmlrpc_parse_json(xmlrpc_env * const envP, + const char * const str) { + + xmlrpc_value * retval = retval; + Tokenizer tok; + + XMLRPC_ASSERT_ENV_OK(envP); + + initializeTokenizer(&tok, str); + + getToken(envP, &tok); + + if (!envP->fault_occurred) { + retval = parseValue(envP, &tok); + + if (!envP->fault_occurred) { + getToken(envP, &tok); + + if (!envP->fault_occurred) { + if (tok.type != typeEof) + setParseErr(envP, &tok, "There is junk after the end of " + "the JSON value, to wit a %s token", + tokTypeName(tok.type)); + } + if (envP->fault_occurred) + xmlrpc_DECREF(retval); + } + } + + terminateTokenizer(&tok); + + return retval; +} + + + +/*============================================================================ + Serialize value to JSON +============================================================================*/ + +/* Borrowed from xmlrpc_serialize */ + +static void +formatOut(xmlrpc_env * const envP, + xmlrpc_mem_block * const outputP, + const char * const formatString, ... ) { + + va_list args; + char buffer[1024]; + int rc; + + XMLRPC_ASSERT_ENV_OK(envP); + + va_start(args, formatString); + + rc = XMLRPC_VSNPRINTF(buffer, sizeof(buffer), formatString, args); + + /* Old vsnprintf() (and Windows) fails with return value -1 if the full + string doesn't fit in the buffer. New vsnprintf() puts whatever will + fit in the buffer, and returns the length of the full string + regardless. For us, this truncation is a failure. + */ + + if (rc < 0) + xmlrpc_faultf(envP, "formatOut() overflowed internal buffer"); + else { + unsigned int const formattedLen = rc; + + if (formattedLen + 1 >= (sizeof(buffer))) + xmlrpc_faultf(envP, "formatOut() overflowed internal buffer"); + else + XMLRPC_MEMBLOCK_APPEND(char, envP, outputP, buffer, formattedLen); + } + va_end(args); +} + + + +static void +indent(xmlrpc_env * const envP, + unsigned int const level, + xmlrpc_mem_block * const outP) { + + unsigned int i; + + for (i = 0; i < level * 2 && !envP->fault_occurred; ++i) + XMLRPC_MEMBLOCK_APPEND(char, envP, outP, " ", 1); +} + + + +/* Forward declaration for recursion */ + +static void +serializeValue(xmlrpc_env * const envP, + xmlrpc_value * const valP, + unsigned int const level, + xmlrpc_mem_block * const outP); + + + +static void +appendEscapeSeq(xmlrpc_env * const envP, + xmlrpc_mem_block * const outP, + unsigned char const c) { +/*---------------------------------------------------------------------------- + Append to *outP the escaped representation of 'c'. + + This is e.g. "\t" for tab, or "\u001C" for something exotic. +-----------------------------------------------------------------------------*/ + unsigned int size; + char buffer[6]; + char slashChar; + /* Character that goes after the backslash, including 'u' for \uHHHH */ + + switch (c) { + case '"' : slashChar = '"'; break; /* U+0022 */ + case '\\': slashChar = '\\'; break; /* U+005C */ + case '\b': slashChar = 'b'; break; /* U+0008 */ + case '\f': slashChar = 'f'; break; /* U+000C */ + case '\n': slashChar = 'n'; break; /* U+000A */ + case '\r': slashChar = 'r'; break; /* U+000D */ + case '\t': slashChar = 't'; break; /* U+0009 */ + default: + slashChar = 'u'; + }; + + buffer[0] = '\\'; + buffer[1] = slashChar; + + if (slashChar == 'u') { + sprintf(&buffer[2], "%04x", c); + size = 6; /* \u1234 */ + } else + size = 2; + + XMLRPC_MEMBLOCK_APPEND(char, envP, outP, buffer, size); +} + + + +static void +makeJsonString(xmlrpc_env * const envP, + const char * const value, + size_t const length, + xmlrpc_mem_block * const outP) { +/*---------------------------------------------------------------------------- + Create a JSON representation of a string, appended to *outP. +-----------------------------------------------------------------------------*/ + const char * const begin = &value[0]; + const char * const end = begin + length; + + const char * cur; + const char * last; + + last = cur = begin; + + while (cur != end && !envP->fault_occurred) { + unsigned char const c = *cur; + + if (c < 0x1F || c == '"' || c == '\\') { + /* This characters needs to be escaped. Put a backslash escape + sequence in the output for this character, after copying all + the characters before it to the output. + */ + XMLRPC_MEMBLOCK_APPEND(char, envP, outP, last, cur - last); + + if (!envP->fault_occurred) { + appendEscapeSeq(envP, outP, c); + + ++cur; + last = cur; + } + } else + ++cur; + } + + /* Copy all characters since the last escaped character to the output */ + if (cur != last) + XMLRPC_MEMBLOCK_APPEND(char, envP, outP, last, cur - last); + + if (envP->fault_occurred) + XMLRPC_MEMBLOCK_CLEAN(char, outP); +} + + + +static void +makeJsonStringFromXmlRpc(xmlrpc_env * const envP, + const xmlrpc_value * const valP, + xmlrpc_mem_block * const outP) { +/*---------------------------------------------------------------------------- + Convert a string XML-RPC value to JSON, appended to *outP. +-----------------------------------------------------------------------------*/ + const char * value; + size_t length; + + xmlrpc_read_string_lp(envP, valP, &length, &value); + if (!envP->fault_occurred) { + makeJsonString(envP, value, length, outP); + + xmlrpc_strfree(value); + } +} + + + +static void +serializeInt(xmlrpc_env * const envP, + xmlrpc_value * const valP, + xmlrpc_mem_block * const outP) { + + xmlrpc_int value; + + xmlrpc_read_int(envP, valP, &value); + + formatOut(envP, outP, "%d", value); +} + + + +static void +serializeI8(xmlrpc_env * const envP, + xmlrpc_value * const valP, + xmlrpc_mem_block * const outP) { + + xmlrpc_int64 value; + + xmlrpc_read_i8(envP, valP, &value); + + formatOut(envP, outP, "%" XMLRPC_PRId64, value); +} + + + +static void +serializeBool(xmlrpc_env * const envP, + xmlrpc_value * const valP, + xmlrpc_mem_block * const outP) { + + xmlrpc_bool value; + xmlrpc_read_bool(envP, valP, &value); + + formatOut(envP, outP, "%s", value ? "true" : "false"); +} + + + +static void +serializeDouble(xmlrpc_env * const envP, + xmlrpc_value * const valP, + xmlrpc_mem_block * const outP) { + + xmlrpc_double value; + xmlrpc_read_double(envP, valP, &value); + + formatOut(envP, outP, "%e", value); +} + + + +static void +serializeDatetime(xmlrpc_env * const envP, + xmlrpc_value * const valP, + xmlrpc_mem_block * const outP) { + + /* ISO 8601 time string as JSON does not have a datetime type */ + + formatOut(envP, outP, "\"%u%02u%02uT%02u:%02u:%02u\"", + valP->_value.dt.Y, + valP->_value.dt.M, + valP->_value.dt.D, + valP->_value.dt.h, + valP->_value.dt.m, + valP->_value.dt.s); +} + + + +static void +serializeString(xmlrpc_env * const envP, + xmlrpc_value * const valP, + xmlrpc_mem_block * const outP) { + + formatOut(envP, outP, "\""); + + makeJsonStringFromXmlRpc(envP, valP, outP); + + formatOut(envP, outP, "\""); +} + + + +static void +serializeBitstring(xmlrpc_env * const envP, + xmlrpc_value * const valP, + xmlrpc_mem_block * const outP) { +/*---------------------------------------------------------------------------- + Append to *outP a JSON string whose value is the bit string *valP in + base64 ASCII. +-----------------------------------------------------------------------------*/ + const unsigned char * bytes; + size_t size; + + xmlrpc_read_base64(envP, valP, &size, &bytes); + + if (!envP->fault_occurred) { + xmlrpc_mem_block * const base64P = + xmlrpc_base64_encode(envP, bytes, size); + + if (!envP->fault_occurred) { + + formatOut(envP, outP, "\""); + + XMLRPC_MEMBLOCK_APPEND( + char, envP, outP, + XMLRPC_MEMBLOCK_CONTENTS(char, base64P), + XMLRPC_MEMBLOCK_SIZE(char, base64P)); + + if (!envP->fault_occurred) + formatOut(envP, outP, "\""); + + XMLRPC_MEMBLOCK_FREE(char, base64P); + } + free((unsigned char*)bytes); + } +} + + + +static void +serializeArray(xmlrpc_env * const envP, + xmlrpc_value * const valP, + unsigned int const level, + xmlrpc_mem_block * const outP) { + + unsigned int const size = xmlrpc_array_size(envP, valP); + + if (!envP->fault_occurred) { + unsigned int i; + + formatOut(envP, outP, "[\n"); + + for (i = 0; i < size && !envP->fault_occurred; ++i) { + xmlrpc_value * const itemP = + xmlrpc_array_get_item(envP, valP, i); + + if (!envP->fault_occurred) { + if (!envP->fault_occurred) { + serializeValue(envP, itemP, level + 1, outP); + + if (i < size - 1) + XMLRPC_MEMBLOCK_APPEND(char, envP, outP, ",\n", 2); + } + } + } + if (!envP->fault_occurred) { + XMLRPC_MEMBLOCK_APPEND(char, envP, outP, "\n", 1); + indent(envP, level, outP); + if (!envP->fault_occurred) { + XMLRPC_MEMBLOCK_APPEND(char, envP, outP, "]", 1); + } + } + } +} + + + +static void +serializeStructMember(xmlrpc_env * const envP, + xmlrpc_value * const memberKeyP, + xmlrpc_value * const memberValueP, + unsigned int const level, + xmlrpc_mem_block * const outP) { + + serializeValue(envP, memberKeyP, level, outP); + + if (!envP->fault_occurred) { + formatOut(envP, outP, ":"); + + if (!envP->fault_occurred) + serializeValue(envP, memberValueP, level, outP); + } +} + + + +static void +serializeStruct(xmlrpc_env * const envP, + xmlrpc_value * const valP, + unsigned int const level, + xmlrpc_mem_block * const outP) { + + if (!envP->fault_occurred) { + formatOut(envP, outP, "{\n"); + if (!envP->fault_occurred) { + unsigned int const size = xmlrpc_struct_size(envP, valP); + + if (!envP->fault_occurred) { + unsigned int i; + for (i = 0; i < size && !envP->fault_occurred; ++i) { + xmlrpc_value * memberKeyP; + xmlrpc_value * memberValueP; + + xmlrpc_struct_get_key_and_value(envP, valP, i, + &memberKeyP, + &memberValueP); + if (!envP->fault_occurred) { + serializeStructMember(envP, memberKeyP, memberValueP, + level + 1, outP); + + if (!envP->fault_occurred && i < size - 1) + XMLRPC_MEMBLOCK_APPEND(char, envP, outP, ",\n", 2); + } + } + if (!envP->fault_occurred) { + XMLRPC_MEMBLOCK_APPEND(char, envP, outP, "\n", 1); + indent(envP, level, outP); + XMLRPC_MEMBLOCK_APPEND(char, envP, outP, "}", 1); + } + } + } + } +} + + + +static void +serializeValue(xmlrpc_env * const envP, + xmlrpc_value * const valP, + unsigned int const level, + xmlrpc_mem_block * const outP) { + + XMLRPC_ASSERT_ENV_OK(envP); + + indent(envP, level, outP); + + switch (xmlrpc_value_type(valP)) { + case XMLRPC_TYPE_INT: + serializeInt(envP, valP, outP); + break; + + case XMLRPC_TYPE_I8: + serializeI8(envP, valP, outP); + break; + + case XMLRPC_TYPE_BOOL: + serializeBool(envP, valP, outP); + break; + + case XMLRPC_TYPE_DOUBLE: + serializeDouble(envP, valP, outP); + break; + + case XMLRPC_TYPE_DATETIME: + serializeDatetime(envP, valP, outP); + break; + + case XMLRPC_TYPE_STRING: + serializeString(envP, valP, outP); + break; + + case XMLRPC_TYPE_BASE64: + serializeBitstring(envP, valP, outP); + break; + + case XMLRPC_TYPE_ARRAY: + serializeArray(envP, valP, level, outP); + break; + + case XMLRPC_TYPE_STRUCT: + serializeStruct(envP, valP, level, outP); + break; + + case XMLRPC_TYPE_C_PTR: + xmlrpc_faultf(envP, "Tried to serialize a C pointer value."); + break; + + case XMLRPC_TYPE_NIL: + formatOut(envP, outP, "null"); + break; + + case XMLRPC_TYPE_DEAD: + xmlrpc_faultf(envP, "Tried to serialize a dead value."); + break; + + default: + xmlrpc_faultf(envP, "Invalid xmlrpc_value type: 0x%x", + xmlrpc_value_type(valP)); + } +} + + + +void +xmlrpc_serialize_json(xmlrpc_env * const envP, + xmlrpc_value * const valP, + xmlrpc_mem_block * const outP) { + + serializeValue(envP, valP, 0, outP); +} diff --git a/libs/xmlrpc-c/src/method.c b/libs/xmlrpc-c/src/method.c index cf58b26..467bbbe 100644 --- a/libs/xmlrpc-c/src/method.c +++ b/libs/xmlrpc-c/src/method.c @@ -10,6 +10,8 @@ Contributed to the public domain by its author. =========================================================================*/ +#define _XOPEN_SOURCE 600 /* Make sure strdup() is in */ + #include "xmlrpc_config.h" #include @@ -57,6 +59,7 @@ translateTypeSpecifierToName(xmlrpc_env * const envP, "Method registry contains invalid signature " "data. It contains the type specifier '%c'", typeSpecifier); + *typeNameP = NULL; /* quiet compiler warning */ } } @@ -175,9 +178,8 @@ parseOneSignature(xmlrpc_env * const envP, } if (envP->fault_occurred) free(signatureP); - else - *signaturePP = signatureP; } + *signaturePP = signatureP; } @@ -210,7 +212,7 @@ listSignatures(xmlrpc_env * const envP, cursorP = &sigListString[0]; while (!envP->fault_occurred && *cursorP != '\0') { - struct xmlrpc_signature * signatureP = NULL; + struct xmlrpc_signature * signatureP; parseOneSignature(envP, cursorP, &signatureP, &cursorP); @@ -293,6 +295,8 @@ makeSignatureList(xmlrpc_env * const envP, if (env.fault_occurred) xmlrpc_faultf(envP, "Can't interpret signature string '%s'. %s", signatureString, env.fault_string); + + xmlrpc_env_clean(&env); } @@ -304,6 +308,7 @@ xmlrpc_methodCreate(xmlrpc_env * const envP, void * const userData, const char * const signatureString, const char * const helpText, + size_t const stackSize, xmlrpc_methodInfo ** const methodPP) { xmlrpc_methodInfo * methodP; @@ -319,12 +324,15 @@ xmlrpc_methodCreate(xmlrpc_env * const envP, methodP->methodFnType1 = methodFnType1; methodP->methodFnType2 = methodFnType2; methodP->userData = userData; - methodP->helpText = strdup(helpText); + methodP->helpText = xmlrpc_strdupsol(helpText); + methodP->stackSize = stackSize; makeSignatureList(envP, signatureString, &methodP->signatureListP); - if (envP->fault_occurred) + if (envP->fault_occurred) { + xmlrpc_strfree(methodP->helpText); free(methodP); + } *methodPP = methodP; } diff --git a/libs/xmlrpc-c/src/method.h b/libs/xmlrpc-c/src/method.h index 2ceca75..f1d56cb 100644 --- a/libs/xmlrpc-c/src/method.h +++ b/libs/xmlrpc-c/src/method.h @@ -65,6 +65,10 @@ typedef struct { /* The method function, if it's type 2. Null if it's not */ void * userData; /* Passed to method function */ + size_t stackSize; + /* Amount of stack space 'methodFnType1' or 'methodFnType2' uses. + Zero means unspecified. + */ struct xmlrpc_signatureList * signatureListP; /* Stuff returned by system method system.methodSignature. Empty list doesn't mean there are no valid forms of calling the @@ -92,6 +96,7 @@ xmlrpc_methodCreate(xmlrpc_env * const envP, void * const userData, const char * const signatureString, const char * const helpText, + size_t const stackSize, xmlrpc_methodInfo ** const methodPP); void diff --git a/libs/xmlrpc-c/src/parse_datetime.c b/libs/xmlrpc-c/src/parse_datetime.c new file mode 100644 index 0000000..a6299d7 --- /dev/null +++ b/libs/xmlrpc-c/src/parse_datetime.c @@ -0,0 +1,466 @@ +#include "xmlrpc_config.h" + +#include +#include +#include +#include + +#if HAVE_REGEX +#include /* Missing from regex.h in GNU libc */ +#include +#endif + +#include "bool.h" + +#include "xmlrpc-c/base.h" +#include "xmlrpc-c/base_int.h" +#include "xmlrpc-c/util.h" + +#include "parse_datetime.h" + + + +#if HAVE_REGEX + +static unsigned int +digitStringValue(const char * const string, + regmatch_t const match) { +/*---------------------------------------------------------------------------- + Return the numerical value of the decimal whole number substring of + 'string' identified by 'match'. E.g. if 'string' is 'abc34d' and + 'match' says start at 3 and end at 5, we return 34. +-----------------------------------------------------------------------------*/ + unsigned int i; + unsigned int accum; + + assert(match.rm_so >= 0); + assert(match.rm_eo >= 0); + + for (i = match.rm_so, accum = 0; i < (unsigned)match.rm_eo; ++i) { + accum *= 10; + assert(isdigit(string[i])); + accum += string[i] - '0'; + } + return accum; +} +#endif /* HAVE_REGEX */ + + + +#if HAVE_REGEX + +static unsigned int +digitStringMillionths(const char * const string, + regmatch_t const match) { +/*---------------------------------------------------------------------------- + Return the number of millionths represented by the digits after the + decimal point in a decimal string, where thse digits are the substring + of 'string' identified by 'match'. E.g. if the substring is + 34, we return 340,000. +-----------------------------------------------------------------------------*/ + unsigned int i; + unsigned int accum; + + assert(match.rm_so >= 0); + assert(match.rm_eo >= 0); + + for (i = match.rm_so, accum = 0; i < (unsigned)match.rm_so+6; ++i) { + accum *= 10; + if (i < (unsigned)match.rm_eo) { + assert(isdigit(string[i])); + accum += string[i] - '0'; + } + } + return accum; +} +#endif /* HAVE_REGEX */ + + +#if HAVE_REGEX + +static void +subParseDtRegex_standard(regmatch_t * const matches, + const char * const datetimeString, + xmlrpc_datetime * const dtP) { + + dtP->Y = digitStringValue(datetimeString, matches[1]); + dtP->M = digitStringValue(datetimeString, matches[2]); + dtP->D = digitStringValue(datetimeString, matches[3]); + dtP->h = digitStringValue(datetimeString, matches[4]); + dtP->m = digitStringValue(datetimeString, matches[5]); + dtP->s = digitStringValue(datetimeString, matches[6]); + + if (matches[7].rm_so == -1) + dtP->u = 0; + else + dtP->u = digitStringMillionths(datetimeString, matches[7]); +} + + + +static void +subParseDtRegex_standardtzd(regmatch_t * const matches, + const char * const datetimeString, + xmlrpc_datetime * const dtP) { + + dtP->Y = digitStringValue(datetimeString, matches[1]); + dtP->M = digitStringValue(datetimeString, matches[2]); + dtP->D = digitStringValue(datetimeString, matches[3]); + dtP->h = digitStringValue(datetimeString, matches[4]); + dtP->m = digitStringValue(datetimeString, matches[5]); + dtP->s = digitStringValue(datetimeString, matches[6]); +} + +#endif /* HAVE_REGEX */ + + +#if HAVE_REGEX + +typedef void (*regparsefunc_t)(regmatch_t * const matches, + const char * const datetimeString, + xmlrpc_datetime * const dtP); + + +struct regexParser { + const char * const regex; + regparsefunc_t func; +}; + +static const struct regexParser iso8601Regex[] + + /* Each entry of this table is instructions for recognizing and parsing + some form of a "dateTime.iso8601" XML element. + + (Note that we recognize far more than just the XML-RPC standard + dateTime.iso8601). + */ + + = { + { + /* Examples: + YYYYMMDD[T]HHMMSS + YYYY-MM-DD[T]HH:MM:SS + YYYY-MM-DD[T]HH:MM:SS.ssss + */ + + "^([0-9]{4})\\-?([0-9]{2})\\-?([0-9]{2})T" + "([0-9]{2}):?([0-9]{2}):?([0-9]{2})\\.?([0-9]+)?$", + subParseDtRegex_standard + }, + + { + /* Examples: + YYYYMMDD[T]HHMMSS[Z] + YYYYMMDD[T]HHMMSS[+-]hh + YYYYMMDD[T]HHMMSS[+-]hhmm + */ + + "^([0-9]{4})\\-?([0-9]{2})\\-?([0-9]{2})T" + "([0-9]{2}):?([0-9]{2}):?([0-9]{2})[Z\\+\\-]([0-9]{2,4})?$", + subParseDtRegex_standardtzd + }, + { NULL, NULL } + }; +#endif /* HAVE_REGEX */ + + + +#if HAVE_REGEX +static void +parseDtRegex(xmlrpc_env * const envP, + const char * const datetimeString, + xmlrpc_datetime * const dtP) { + + unsigned int i; + const struct regexParser * parserP; + /* The parser that matches 'datetimeString'. Null if no match yet + found. + */ + regmatch_t matches[1024]; + + for (i = 0, parserP = NULL; iso8601Regex[i].regex && !parserP; ++i) { + const struct regexParser * const thisParserP = &iso8601Regex[i]; + + regex_t re; + int status; + + status = regcomp(&re, thisParserP->regex, REG_ICASE | REG_EXTENDED); + + /* Our regex is valid, so it must have compiled: */ + assert(status == 0); + { + int status; + + status = regexec(&re, datetimeString, ARRAY_SIZE(matches), + matches, 0); + + if (status == 0) { + assert(matches[0].rm_so != -1); /* Match of whole regex */ + + parserP = thisParserP; + } + regfree(&re); + } + } + + if (parserP) { + parserP->func(matches, datetimeString, dtP); + } else { + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_PARSE_ERROR, + "value '%s' is not of any form we recognize " + "for a element", + datetimeString); + } + +} +#endif /* HAVE_REGEX */ + + + +static __inline__ void +parseDtNoRegex(xmlrpc_env * const envP, + const char * const datetimeString, + xmlrpc_datetime * const dtP) { + + unsigned int const dtStrlen = strlen(datetimeString); + + char year[4+1]; + char month[2+1]; + char day[2+1]; + char hour[2+1]; + char minute[2+1]; + char second[2+1]; + + if (dtStrlen < 17 || dtStrlen == 18 || dtStrlen > 24) + xmlrpc_faultf(envP, "could not parse date, size incompatible: '%d'", + dtStrlen); + else { + year[0] = datetimeString[ 0]; + year[1] = datetimeString[ 1]; + year[2] = datetimeString[ 2]; + year[3] = datetimeString[ 3]; + year[4] = '\0'; + + month[0] = datetimeString[ 4]; + month[1] = datetimeString[ 5]; + month[2] = '\0'; + + day[0] = datetimeString[ 6]; + day[1] = datetimeString[ 7]; + day[2] = '\0'; + + assert(datetimeString[ 8] == 'T'); + + hour[0] = datetimeString[ 9]; + hour[1] = datetimeString[10]; + hour[2] = '\0'; + + assert(datetimeString[11] == ':'); + + minute[0] = datetimeString[12]; + minute[1] = datetimeString[13]; + minute[2] = '\0'; + + assert(datetimeString[14] == ':'); + + second[0] = datetimeString[15]; + second[1] = datetimeString[16]; + second[2] = '\0'; + + if (dtStrlen > 17) { + unsigned int const pad = 24 - dtStrlen; + unsigned int i; + + dtP->u = atoi(&datetimeString[18]); + for (i = 0; i < pad; ++i) + dtP->u *= 10; + } else + dtP->u = 0; + + dtP->Y = atoi(year); + dtP->M = atoi(month); + dtP->D = atoi(day); + dtP->h = atoi(hour); + dtP->m = atoi(minute); + dtP->s = atoi(second); + } +} + + + +static void +validateFirst17(xmlrpc_env * const envP, + const char * const dt) { +/*---------------------------------------------------------------------------- + Assuming 'dt' is at least 17 characters long, validate that the first + 17 characters are a valid XML-RPC datetime, e.g. + "20080628T16:35:02" +-----------------------------------------------------------------------------*/ + unsigned int i; + + for (i = 0; i < 8 && !envP->fault_occurred; ++i) + if (!isdigit(dt[i])) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_PARSE_ERROR, "Not a digit: '%c'", dt[i]); + + if (dt[8] != 'T') + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_PARSE_ERROR, "9th character is '%c', not 'T'", + dt[8]); + if (!isdigit(dt[9])) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_PARSE_ERROR, "Not a digit: '%c'", dt[9]); + if (!isdigit(dt[10])) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_PARSE_ERROR, "Not a digit: '%c'", dt[10]); + if (dt[11] != ':') + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_PARSE_ERROR, "Not a colon: '%c'", dt[11]); + if (!isdigit(dt[12])) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_PARSE_ERROR, "Not a digit: '%c'", dt[12]); + if (!isdigit(dt[13])) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_PARSE_ERROR, "Not a digit: '%c'", dt[13]); + if (dt[14] != ':') + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_PARSE_ERROR, "Not a colon: '%c'", dt[14]); + if (!isdigit(dt[15])) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_PARSE_ERROR, "Not a digit: '%c'", dt[15]); + if (!isdigit(dt[16])) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_PARSE_ERROR, "Not a digit: '%c'", dt[16]); +} + + + +static void +validateFractionalSeconds(xmlrpc_env * const envP, + const char * const dt) { +/*---------------------------------------------------------------------------- + Validate the fractional seconds part of the XML-RPC datetime string + 'dt', if any. That's the decimal point and everything following + it. +-----------------------------------------------------------------------------*/ + if (strlen(dt) > 17) { + if (dt[17] != '.') { + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_PARSE_ERROR, + "'%c' where only a period is valid", dt[17]); + } else { + if (dt[18] == '\0') + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_PARSE_ERROR, "Nothing after decimal point"); + else { + unsigned int i; + for (i = 18; dt[i] != '\0' && !envP->fault_occurred; ++i) { + if (!isdigit(dt[i])) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_PARSE_ERROR, + "Non-digit in fractional seconds: '%c'", dt[i]); + } + } + } + } +} + + + +static __inline__ void +validateFormatNoRegex(xmlrpc_env * const envP, + const char * const dt) { + + if (strlen(dt) < 17) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_PARSE_ERROR, + "Invalid length of %u of datetime. " + "Must be at least 17 characters", + (unsigned)strlen(dt)); + else { + validateFirst17(envP, dt); + + validateFractionalSeconds(envP, dt); + } +} + + + +static void +validateXmlrpcDatetimeSome(xmlrpc_env * const envP, + xmlrpc_datetime const dt) { +/*---------------------------------------------------------------------------- + Type xmlrpc_datetime is defined such that it can represent a nonexistent + datetime such as February 30. + + Validate that 'dt' doesn't have glaring invalidities such as Hour 25. + We leave the possibility of more subtle invalidity such as February 30. +-----------------------------------------------------------------------------*/ + + if (dt.M < 1 || dt.M > 12) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_PARSE_ERROR, + "Month of year value %u is not in the range 1-12", dt.M); + else if (dt.D < 1 || dt.D > 31) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_PARSE_ERROR, + "Day of month value %u is not in the range 1-31", dt.D); + else if (dt.h > 23) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_PARSE_ERROR, + "Hour of day value %u is not in the range 0-23", dt.h); + else if (dt.m > 59) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_PARSE_ERROR, + "Minute of hour value %u is not in the range 0-59", dt.m); + else if (dt.s > 59) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_PARSE_ERROR, + "Second of minute value %u is not in the range 0-59", dt.s); + else if (dt.u > 999999) + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_PARSE_ERROR, + "Microsecond of second value %u is not in the range 0-1M", dt.u); +} + + + +void +xmlrpc_parseDatetime(xmlrpc_env * const envP, + const char * const datetimeString, + xmlrpc_value ** const valuePP) { +/*---------------------------------------------------------------------------- + Parse the content of a XML-RPC XML element, e.g. + "20000301T00:00:00". + + 'str' is that content. + + 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. + + Note that Xmlrpc-c recognizes various extensions of the XML-RPC + element type. + + 'str' may not be valid XML-RPC (with extensions). In that case we fail + with fault code XMLRPC_PARSE_ERROR. +-----------------------------------------------------------------------------*/ + xmlrpc_datetime dt; + +#if HAVE_REGEX + parseDtRegex(envP, datetimeString, &dt); +#else + /* Note: validation is not as strong without regex */ + validateFormatNoRegex(envP, datetimeString); + if (!envP->fault_occurred) + parseDtNoRegex(envP, datetimeString, &dt); +#endif + + if (!envP->fault_occurred) { + validateXmlrpcDatetimeSome(envP, dt); + + if (!envP->fault_occurred) + *valuePP = xmlrpc_datetime_new(envP, dt); + } +} diff --git a/libs/xmlrpc-c/src/parse_datetime.h b/libs/xmlrpc-c/src/parse_datetime.h new file mode 100644 index 0000000..85207b7 --- /dev/null +++ b/libs/xmlrpc-c/src/parse_datetime.h @@ -0,0 +1,12 @@ +#ifndef PARSE_DATETIME_H_INCLUDED +#define PARSE_DATETIME_H_INCLUDED + +#include "xmlrpc-c/util.h" +#include "xmlrpc-c/base.h" + +void +xmlrpc_parseDatetime(xmlrpc_env * const envP, + const char * const str, + xmlrpc_value ** const valuePP); + +#endif diff --git a/libs/xmlrpc-c/src/parse_value.c b/libs/xmlrpc-c/src/parse_value.c index a00b2a1..b40cf47 100644 --- a/libs/xmlrpc-c/src/parse_value.c +++ b/libs/xmlrpc-c/src/parse_value.c @@ -13,8 +13,10 @@ #include "xmlrpc-c/base.h" #include "xmlrpc-c/base_int.h" #include "xmlrpc-c/string_int.h" +#include "xmlrpc-c/string_number.h" #include "xmlrpc-c/util.h" #include "xmlrpc-c/xmlparser.h" +#include "parse_datetime.h" #include "parse_value.h" @@ -72,12 +74,12 @@ parseArray(xmlrpc_env * const envP, arrayP = xmlrpc_array_new(envP); if (!envP->fault_occurred) { - unsigned int const childCount = xml_element_children_size(arrayElemP); + size_t const childCount = xml_element_children_size(arrayElemP); if (childCount != 1) setParseFault(envP, " element has %u children. Only one " - "makes sense.", childCount); + "makes sense.", (unsigned int)childCount); else { xml_element * const dataElemP = xml_element_children(arrayElemP)[0]; @@ -111,11 +113,11 @@ parseName(xmlrpc_env * const envP, xml_element * const nameElemP, xmlrpc_value ** const valuePP) { - unsigned int const childCount = xml_element_children_size(nameElemP); + size_t const childCount = xml_element_children_size(nameElemP); if (childCount > 0) setParseFault(envP, " element has %u children. " - "Should have none.", childCount); + "Should have none.", (unsigned int)childCount); else { const char * const cdata = xml_element_cdata(nameElemP); size_t const cdataSize = xml_element_cdata_size(nameElemP); @@ -181,12 +183,12 @@ parseMember(xmlrpc_env * const envP, xmlrpc_value ** const keyPP, xmlrpc_value ** const valuePP) { - unsigned int const childCount = xml_element_children_size(memberP); + size_t const childCount = xml_element_children_size(memberP); if (childCount != 2) setParseFault(envP, " element has %u children. Only one and " - "one make sense.", childCount); + "one make sense.", (unsigned int)childCount); else { xml_element * nameElemP = NULL; @@ -302,12 +304,12 @@ parseInt(xmlrpc_env * const envP, /* Look for out-of-range errors which didn't produce ERANGE. */ if (i < XMLRPC_INT32_MIN) setParseFault(envP, - " value %d is below the range allowed " + " value %ld is below the range allowed " "by XML-RPC (minimum is %d)", i, XMLRPC_INT32_MIN); else if (i > XMLRPC_INT32_MAX) setParseFault(envP, - " value %d is above the range allowed " + " value %ld is above the range allowed " "by XML-RPC (maximum is %d)", i, XMLRPC_INT32_MAX); else { @@ -581,39 +583,20 @@ parseI8(xmlrpc_env * const envP, " content '%s' starts with white space", str); else { xmlrpc_int64 i; - char * tail; + xmlrpc_env env; - errno = 0; - i = strtoll(str, &tail, 10); + xmlrpc_env_init(&env); - if (errno == ERANGE) - setParseFault(envP, " 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 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, " 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, " value %d is above the range allowed " - "by XML-RPC (maximum is %d)", - i, XMLRPC_INT64_MAX); - else { - if (tail[0] != '\0') - setParseFault(envP, - " value '%s' contains non-numerical " - "junk: '%s'", str, tail); - else - *valuePP = xmlrpc_i8_new(envP, i); - } - } + xmlrpc_parse_int64(&env, str, &i); + + if (env.fault_occurred) + setParseFault(envP, " XML element value '%s' is invalid " + "because it does not represent " + "a 64 bit integer. %s", env.fault_string); + else + *valuePP = xmlrpc_i8_new(envP, i); + + xmlrpc_env_clean(&env); } } @@ -640,33 +623,39 @@ parseSimpleValueCdata(xmlrpc_env * const envP, 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. + The "ex:XXX" element names are what the Apache XML-RPC facility + uses: http://ws.apache.org/xmlrpc/types.html. (Technically, it + isn't "ex" but an arbitrary prefix that identifies a namespace + declared earlier in the XML document -- this is an XML thing. + But we aren't nearly sophisticated enough to use real XML + namespaces, so we exploit the fact that XML-RPC actually uses + "ex"). + + "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")) + 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); + xmlrpc_parseDatetime(envP, cdata, valuePP); 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")) + xmlrpc_streq(elementName, "ex:nil")) *valuePP = xmlrpc_nil_new(envP); else if (xmlrpc_streq(elementName, "i8") || - xmlrpc_streq(elementName, "ex.i8")) + xmlrpc_streq(elementName, "ex:i8")) parseI8(envP, cdata, valuePP); else setParseFault(envP, "Unknown value type -- XML element is named " @@ -680,13 +669,13 @@ parseSimpleValue(xmlrpc_env * const envP, xml_element * const elemP, xmlrpc_value ** const valuePP) { - unsigned int const childCount = xml_element_children_size(elemP); + size_t childCount = xml_element_children_size(elemP); if (childCount > 0) setParseFault(envP, "The child of a element " "is neither nor , " "but has %u child elements of its own.", - childCount); + (unsigned int)childCount); else { const char * const elemName = xml_element_name(elemP); const char * const cdata = xml_element_cdata(elemP); @@ -724,7 +713,7 @@ xmlrpc_parseValue(xmlrpc_env * const envP, "<%s> element where expected", xml_element_name(elemP)); else { - unsigned int const childCount = xml_element_children_size(elemP); + size_t const childCount = xml_element_children_size(elemP); if (childCount == 0) { /* We have no type element, so treat the value as a string. */ @@ -733,7 +722,8 @@ xmlrpc_parseValue(xmlrpc_env * const envP, *valuePP = xmlrpc_string_new_lp(envP, cdata_size, cdata); } else if (childCount > 1) setParseFault(envP, " has %u child elements. " - "Only zero or one make sense.", childCount); + "Only zero or one make sense.", + (unsigned int)childCount); else { /* We should have a type tag inside our value tag. */ xml_element * const childP = xml_element_children(elemP)[0]; @@ -749,3 +739,6 @@ xmlrpc_parseValue(xmlrpc_env * const envP, } } } + + + diff --git a/libs/xmlrpc-c/src/registry.c b/libs/xmlrpc-c/src/registry.c index e7eddd3..b67944a 100644 --- a/libs/xmlrpc-c/src/registry.c +++ b/libs/xmlrpc-c/src/registry.c @@ -36,6 +36,19 @@ unsigned int const xmlrpc_server_version_minor = XMLRPC_VERSION_MINOR; unsigned int const xmlrpc_server_version_point = XMLRPC_VERSION_POINT; + +void +xmlrpc_server_version(unsigned int * const majorP, + unsigned int * const minorP, + unsigned int * const pointP) { + + *majorP = XMLRPC_VERSION_MAJOR; + *minorP = XMLRPC_VERSION_MINOR; + *pointP = XMLRPC_VERSION_POINT; +} + + + xmlrpc_registry * xmlrpc_registry_new(xmlrpc_env * const envP) { @@ -86,7 +99,8 @@ registryAddMethod(xmlrpc_env * const envP, xmlrpc_method2 method2, const char * const signatureString, const char * const help, - void * const userData) { + void * const userData, + size_t const stackSize) { const char * const helpString = help ? help : "No help is available for this method."; @@ -99,7 +113,7 @@ registryAddMethod(xmlrpc_env * const envP, XMLRPC_ASSERT(method1 != NULL || method2 != NULL); xmlrpc_methodCreate(envP, method1, method2, userData, - signatureString, helpString, &methodP); + signatureString, helpString, stackSize, &methodP); if (!envP->fault_occurred) { xmlrpc_methodListAdd(envP, registryP->methodListP, methodName, @@ -126,7 +140,7 @@ xmlrpc_registry_add_method_w_doc( XMLRPC_ASSERT(host == NULL); registryAddMethod(envP, registryP, methodName, method, NULL, - signatureString, help, serverInfo); + signatureString, help, serverInfo, 0); } @@ -156,7 +170,21 @@ xmlrpc_registry_add_method2(xmlrpc_env * const envP, void * const serverInfo) { registryAddMethod(envP, registryP, methodName, NULL, method, - signatureString, help, serverInfo); + signatureString, help, serverInfo, 0); +} + + + +void +xmlrpc_registry_add_method3( + xmlrpc_env * const envP, + xmlrpc_registry * const registryP, + const struct xmlrpc_method_info3 * const infoP) { + + registryAddMethod(envP, registryP, infoP->methodName, NULL, + infoP->methodFunction, + infoP->signatureString, infoP->help, infoP->serverInfo, + infoP->stackSize); } @@ -182,6 +210,43 @@ xmlrpc_registry_set_default_method( +/* This is our guess at what a method function requires when the user + doesn't say. +*/ +#define METHOD_FUNCTION_STACK 128*1024 + + + +static size_t +methodStackSize(const xmlrpc_methodInfo * const methodP) { + + return methodP->stackSize == + 0 ? METHOD_FUNCTION_STACK : methodP->stackSize; +} + + + +size_t +xmlrpc_registry_max_stackSize(xmlrpc_registry * const registryP) { +/*---------------------------------------------------------------------------- + Return the maximum amount of stack required by the methods in registry + *registryP. + + If there are no methods, return 0. +-----------------------------------------------------------------------------*/ + xmlrpc_methodNode * p; + size_t stackSize; + + for (p = registryP->methodListP->firstMethodP, stackSize = 0; + p; + p = p->nextP) { + + stackSize = MAX(stackSize, methodStackSize(p->methodP)); + } + return stackSize; +} + + void xmlrpc_registry_set_preinvoke_method( diff --git a/libs/xmlrpc-c/src/system_method.c b/libs/xmlrpc-c/src/system_method.c index e1f77c0..ad13878 100644 --- a/libs/xmlrpc-c/src/system_method.c +++ b/libs/xmlrpc-c/src/system_method.c @@ -287,6 +287,64 @@ static struct systemMethodReg const methodListMethods = { /*========================================================================= + system.methodExist +==========================================================================*/ + +static void +determineMethodExistence(xmlrpc_env * const envP, + const char * const methodName, + xmlrpc_registry * const registryP, + xmlrpc_value ** const existsPP) { + + xmlrpc_methodInfo * methodP; + + xmlrpc_methodListLookupByName(registryP->methodListP, methodName, + &methodP); + + *existsPP = xmlrpc_bool_new(envP, !!methodP); +} + + + +static xmlrpc_value * +system_methodExist(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) { + determineMethodExistence(envP, methodName, registryP, &retvalP); + + xmlrpc_strfree(methodName); + } + + return retvalP; +} + + + +static struct systemMethodReg const methodMethodExist = { + "system.methodExist", + &system_methodExist, + "s:b", + "Tell whether a method by a specified name exists on this server", +}; + + + +/*========================================================================= system.methodHelp =========================================================================*/ @@ -327,7 +385,7 @@ system_methodHelp(xmlrpc_env * const envP, 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) { @@ -338,9 +396,9 @@ system_methodHelp(xmlrpc_env * const envP, "for security reasons"); else getHelpString(envP, methodName, registryP, &retvalP); - } - xmlrpc_strfree(methodName); + xmlrpc_strfree(methodName); + } return retvalP; } @@ -409,8 +467,8 @@ buildSignatureValue(xmlrpc_env * const envP, if (envP->fault_occurred) xmlrpc_DECREF(sigValueP); - else - *sigValuePP = sigValueP; + + *sigValuePP = sigValueP; } @@ -471,6 +529,15 @@ getSignatureList(xmlrpc_env * const envP, +/* Microsoft Visual C in debug mode produces code that complains about + returning an undefined value from system_methodSignature(). It's a bogus + complaint, because this function is defined to return nothing meaningful + those cases. So we disable the check. +*/ +#pragma runtime_checks("u", off) + + + static xmlrpc_value * system_methodSignature(xmlrpc_env * const envP, xmlrpc_value * const paramArrayP, @@ -487,8 +554,6 @@ system_methodSignature(xmlrpc_env * const 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. */ @@ -522,10 +587,14 @@ system_methodSignature(xmlrpc_env * const envP, +#pragma runtime_checks("u", restore) + + + static struct systemMethodReg const methodMethodSignature = { "system.methodSignature", &system_methodSignature, - "s:s", + "A: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.", @@ -556,8 +625,6 @@ system_shutdown(xmlrpc_env * const envP, 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) @@ -607,9 +674,9 @@ static struct systemMethodReg const methodShutdown = { =========================================================================*/ static void -getCapabilities(xmlrpc_env * const envP, - xmlrpc_registry * const registryP ATTR_UNUSED, - xmlrpc_value ** const capabilitiesPP) { +constructCapabilities(xmlrpc_env * const envP, + xmlrpc_registry * const registryP ATTR_UNUSED, + xmlrpc_value ** const capabilitiesPP) { *capabilitiesPP = xmlrpc_build_value( @@ -648,12 +715,13 @@ system_capabilities(xmlrpc_env * const envP, envP, XMLRPC_INDEX_ERROR, "There are no parameters. You supplied %u", paramCount); else - getCapabilities(envP, registryP, &retvalP); + constructCapabilities(envP, registryP, &retvalP); return retvalP; } + static struct systemMethodReg const methodCapabilities = { "system.capabilities", &system_capabilities, @@ -664,6 +732,72 @@ static struct systemMethodReg const methodCapabilities = { +/*========================================================================= + system.getCapabilities +=========================================================================*/ + +/* This implements a standard. + See http://tech.groups.yahoo.com/group/xml-rpc/message/2897 . +*/ + +static void +listCapabilities(xmlrpc_env * const envP, + xmlrpc_registry * const registryP ATTR_UNUSED, + xmlrpc_value ** const capabilitiesPP) { + + *capabilitiesPP = + xmlrpc_build_value( + envP, "{s:{s:s,s:i}}", + "introspect", + "specUrl", + "http://xmlrpc-c.sourceforge.net/xmlrpc-c/introspection.html", + "specVersion", + 1 + ); +} + + + +static xmlrpc_value * +system_getCapabilities(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 + listCapabilities(envP, registryP, &retvalP); + + return retvalP; +} + + + +static struct systemMethodReg const methodGetCapabilities = { + "system.getCapabilities", + &system_getCapabilities, + "S:", + "Return the list of standard capabilities of XML-RPC server. " + "See http://tech.groups.yahoo.com/group/xml-rpc/message/2897" +}; + + + /*============================================================================ Installer of system methods ============================================================================*/ @@ -699,12 +833,15 @@ xmlrpc_installSystemMethods(xmlrpc_env * const envP, if (!envP->fault_occurred) registerSystemMethod(envP, registryP, methodListMethods); - if (!envP->fault_occurred) - registerSystemMethod(envP, registryP, methodMethodSignature); + if (!envP->fault_occurred) + registerSystemMethod(envP, registryP, methodMethodExist); if (!envP->fault_occurred) registerSystemMethod(envP, registryP, methodMethodHelp); + if (!envP->fault_occurred) + registerSystemMethod(envP, registryP, methodMethodSignature); + if (!envP->fault_occurred) registerSystemMethod(envP, registryP, methodMulticall); @@ -713,6 +850,9 @@ xmlrpc_installSystemMethods(xmlrpc_env * const envP, if (!envP->fault_occurred) registerSystemMethod(envP, registryP, methodCapabilities); + + if (!envP->fault_occurred) + registerSystemMethod(envP, registryP, methodGetCapabilities); } diff --git a/libs/xmlrpc-c/src/test/.cvsignore b/libs/xmlrpc-c/src/test/.cvsignore deleted file mode 100644 index b5e32d3..0000000 --- a/libs/xmlrpc-c/src/test/.cvsignore +++ /dev/null @@ -1,3 +0,0 @@ -Makefile -test -cgitest1 diff --git a/libs/xmlrpc-c/src/test/Makefile b/libs/xmlrpc-c/src/test/Makefile index 946a377..0215902 100644 --- a/libs/xmlrpc-c/src/test/Makefile +++ b/libs/xmlrpc-c/src/test/Makefile @@ -19,7 +19,7 @@ LDADD_CGI_SERVER = \ default: all -INCLUDES = -I$(BLDDIR) -I $(SRCDIR)/include -I$(SRCDIR)/lib/util/include \ +INCLUDES = -I$(BLDDIR) -Isrcdir/include -Isrcdir/lib/util/include \ PROGS = test cgitest1 @@ -28,6 +28,7 @@ all: $(PROGS) LDFLAGS = $(LADD) TEST_OBJS = \ + testtool.o \ test.o \ abyss.o \ cgi.o \ @@ -37,6 +38,7 @@ TEST_OBJS = \ serialize_value.o \ server_abyss.o \ value.o \ + value_datetime.o \ xml_data.o \ ifeq ($(MUST_BUILD_CLIENT),yes) @@ -49,6 +51,11 @@ endif 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 + test: \ $(XMLRPC_C_CONFIG) \ $(TEST_OBJS) $(LIBXMLRPC_A) $(LIBXMLRPC_UTIL_A) \ @@ -59,16 +66,16 @@ test: \ $(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) +CGITEST1_OBJS = cgitest1.o testtool.o -CFLAGS = $(CFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD) +cgitest1: $(CGITEST1_OBJS) $(LIBXMLRPC_SERVER_A) $(LIBXMLRPC_SERVER_CGI_A) \ + $(LIBXMLRPC_A) $(LIBXMLRPC_UTIL_A) $(LIBXMLRPC_XML) + $(CCLD) -o $@ $(CGITEST1_OBJS) $(LDFLAGS) $(LDADD_CGI_SERVER) OBJS = $(TEST_OBJS) cgitest1.o $(OBJS):%.o:%.c - $(CC) -c $(INCLUDES) $(CFLAGS) $< + $(CC) -c $(INCLUDES) $(CFLAGS_ALL) $< # Note the difference between 'check' and 'runtests'. 'check' means to check # our own correctness. 'runtests' means to run the tests that check our @@ -94,4 +101,4 @@ distclean: clean distclean-common .PHONY: dep dep: dep-common -include Makefile.depend +include depend.mk diff --git a/libs/xmlrpc-c/src/test/abyss.c b/libs/xmlrpc-c/src/test/abyss.c index 1e39f51..b86eaa8 100644 --- a/libs/xmlrpc-c/src/test/abyss.c +++ b/libs/xmlrpc-c/src/test/abyss.c @@ -15,11 +15,12 @@ #include "xmlrpc_config.h" #include "int.h" +#include "casprintf.h" #include "xmlrpc-c/base.h" #include "xmlrpc-c/server.h" #include "xmlrpc-c/abyss.h" -#include "test.h" +#include "testtool.h" #include "abyss.h" @@ -87,7 +88,7 @@ chanSwitchCreate(uint16_t const portNumber, static void channelCreateFd(int const fd, - TChannel ** const channelPP, + TChannel ** const channelPP, const char ** const errorP) { #ifdef WIN32 @@ -104,7 +105,7 @@ channelCreateFd(int const fd, static void testChanSwitchOsSocket(void) { - int rc; + XMLRPC_SOCKET rc; rc = socket(AF_INET, SOCK_STREAM, 0); if (rc < 0) { @@ -165,7 +166,7 @@ testChanSwitch(void) { static void testChannel(void) { - int rc; + XMLRPC_SOCKET rc; rc = socket(AF_INET, SOCK_STREAM, 0); if (rc < 0) { @@ -183,6 +184,8 @@ testChannel(void) { TEST(error); TEST(strstr(error, "not in connected")); + + strfree(error); } } @@ -191,7 +194,7 @@ testChannel(void) { static void testOsSocket(void) { - int rc; + XMLRPC_SOCKET rc; rc = socket(AF_INET, SOCK_STREAM, 0); if (rc < 0) { diff --git a/libs/xmlrpc-c/src/test/cgi.c b/libs/xmlrpc-c/src/test/cgi.c index 52c0c08..18dfa9b 100644 --- a/libs/xmlrpc-c/src/test/cgi.c +++ b/libs/xmlrpc-c/src/test/cgi.c @@ -5,7 +5,7 @@ #include "xmlrpc_config.h" -#include "test.h" +#include "testtool.h" #include "cgi.h" static const char cgiResponse1[] = diff --git a/libs/xmlrpc-c/src/test/cgitest1.c b/libs/xmlrpc-c/src/test/cgitest1.c index 7ce6909..ce758b1 100644 --- a/libs/xmlrpc-c/src/test/cgitest1.c +++ b/libs/xmlrpc-c/src/test/cgitest1.c @@ -16,7 +16,7 @@ #include "xmlrpc-c/server.h" #include "xmlrpc-c/server_cgi.h" -#include "test.h" +#include "testtool.h" int total_tests; diff --git a/libs/xmlrpc-c/src/test/client.c b/libs/xmlrpc-c/src/test/client.c index 140ffc0..e3b8bc7 100644 --- a/libs/xmlrpc-c/src/test/client.c +++ b/libs/xmlrpc-c/src/test/client.c @@ -10,10 +10,30 @@ #include "xmlrpc-c/client.h" #include "xmlrpc-c/transport.h" -#include "test.h" +#include "bool.h" +#include "testtool.h" #include "client.h" + +static void +testVersion(void) { + + unsigned int major, minor, point; + + xmlrpc_client_version(&major, &minor, &point); + +#ifndef WIN32 + /* xmlrpc_client_version_major, etc. are not exported from a Windows DLL */ + + TEST(major = xmlrpc_client_version_major); + TEST(minor = xmlrpc_client_version_minor); + TEST(point = xmlrpc_client_version_point); +#endif +} + + + static void testGlobalConst(void) { @@ -38,6 +58,22 @@ testGlobalConst(void) { +static xmlrpc_progress_fn myProgress; + +static void +myProgress(void * const userHandle, + struct xmlrpc_progress_data const data) { + + printf("Progress of %p: %f, %f, %f, %f\n", + userHandle, + data.call.total, + data.call.now, + data.response.total, + data.response.now); +} + + + static void testCreateCurlParms(void) { @@ -78,6 +114,33 @@ testCreateCurlParms(void) { TEST_NO_FAULT(&env); xmlrpc_client_destroy(clientP); + curlTransportParms1.ssl_cert = NULL; + curlTransportParms1.sslcerttype = NULL; + curlTransportParms1.sslcertpasswd = NULL; + curlTransportParms1.sslkey = NULL; + curlTransportParms1.sslkeytype = NULL; + curlTransportParms1.sslkeypasswd = NULL; + curlTransportParms1.sslengine = NULL; + curlTransportParms1.sslengine_default = false; + curlTransportParms1.sslversion = XMLRPC_SSLVERSION_DEFAULT; + curlTransportParms1.cainfo = NULL; + curlTransportParms1.capath = NULL; + curlTransportParms1.randomfile = NULL; + curlTransportParms1.egdsocket = NULL; + curlTransportParms1.ssl_cipher_list = NULL; + curlTransportParms1.timeout = 0; + curlTransportParms1.dont_advertise = 1; + curlTransportParms1.proxy = NULL; + curlTransportParms1.proxy_port = 0; + curlTransportParms1.proxy_type = XMLRPC_HTTPPROXY_HTTP; + curlTransportParms1.proxy_auth = XMLRPC_HTTPAUTH_NONE; + clientParms1.transportparm_size = XMLRPC_CXPSIZE(proxy_auth); + 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 */ } @@ -113,6 +176,8 @@ testCreateSeparateXport(void) { &clientP); TEST_NO_FAULT(&env); + xmlrpc_client_destroy(clientP); + clientParms1.transport = "curl"; clientParms1.transportparmsP = &curlTransportParms1; clientParms1.transportparm_size = 0; @@ -124,6 +189,8 @@ testCreateSeparateXport(void) { &clientP); TEST_NO_FAULT(&env); + xmlrpc_client_destroy(clientP); + clientParms1.transportP = transportP; xmlrpc_client_create(&env, 0, "", "", &clientParms1, XMLRPC_CPSIZE(transportP), @@ -150,6 +217,8 @@ testCreateSeparateXport(void) { TEST_NO_FAULT(&env); + xmlrpc_client_destroy(clientP); + xmlrpc_curl_transport_ops.destroy(transportP); xmlrpc_env_clean(&env); @@ -202,8 +271,9 @@ testCreateDestroy(void) { clientParms1.transportOpsP = NULL; clientParms1.transportP = NULL; clientParms1.dialect = xmlrpc_dialect_apache; + clientParms1.progressFn = &myProgress; xmlrpc_client_create(&env, 0, "testprog", "1.0", - &clientParms1, XMLRPC_CPSIZE(dialect), + &clientParms1, XMLRPC_CPSIZE(progressFn), &clientP); TEST_NO_FAULT(&env); xmlrpc_client_destroy(clientP); @@ -420,9 +490,11 @@ test_client(void) { printf("Running client tests."); + testVersion(); testGlobalConst(); testCreateDestroy(); testInitCleanup(); + printf("\n"); testServerInfo(); testSynchCall(); diff --git a/libs/xmlrpc-c/src/test/method_registry.c b/libs/xmlrpc-c/src/test/method_registry.c index da8d304..91fa700 100644 --- a/libs/xmlrpc-c/src/test/method_registry.c +++ b/libs/xmlrpc-c/src/test/method_registry.c @@ -10,7 +10,7 @@ #include "xmlrpc-c/base.h" #include "xmlrpc-c/server.h" -#include "test.h" +#include "testtool.h" #include "xml_data.h" #include "method_registry.h" @@ -26,6 +26,25 @@ static const char * const barHelp = "This is the help for Method test.bar."; + +static void +testVersion(void) { + + unsigned int major, minor, point; + + xmlrpc_server_version(&major, &minor, &point); + +#ifndef WIN32 + /* xmlrpc_server_version_major, etc. are not exported from a Windows DLL */ + + TEST(major = xmlrpc_server_version_major); + TEST(minor = xmlrpc_server_version_minor); + TEST(point = xmlrpc_server_version_point); +#endif +} + + + static xmlrpc_value * test_foo(xmlrpc_env * const envP, xmlrpc_value * const paramArrayP, @@ -297,6 +316,8 @@ test_system_methodSignature(xmlrpc_registry * const registryP) { TEST_NO_FAULT(&env); TEST(streq(type0, "int")); TEST(streq(type1, "int")); + strfree(type0); + strfree(type1); xmlrpc_DECREF(resultP); xmlrpc_DECREF(argArrayP); @@ -310,7 +331,7 @@ test_signature(void) { xmlrpc_env env; xmlrpc_registry * registryP; - uint i; + unsigned int i; xmlrpc_env_init(&env); @@ -409,16 +430,19 @@ static const char * const expectedMethodName[] = { The list we expect back from system.listMethods. -----------------------------------------------------------------------------*/ "system.listMethods", - "system.methodSignature", + "system.methodExist", "system.methodHelp", + "system.methodSignature", "system.multicall", "system.shutdown", "system.capabilities", + "system.getCapabilities", "test.foo", "test.bar" }; + static void test_system_listMethods(xmlrpc_registry * const registryP) { /*---------------------------------------------------------------------------- @@ -427,7 +451,7 @@ test_system_listMethods(xmlrpc_registry * const registryP) { xmlrpc_env env; xmlrpc_value * resultP; xmlrpc_value * argArrayP; - const char * methodName[8]; + const char * methodName[ARRAY_SIZE(expectedMethodName)]; unsigned int size; unsigned int i; @@ -449,13 +473,16 @@ test_system_listMethods(xmlrpc_registry * const registryP) { TEST(size == ARRAY_SIZE(expectedMethodName)); - xmlrpc_decompose_value(&env, resultP, "(ssssssss)", + xmlrpc_decompose_value(&env, resultP, "(ssssssssss)", &methodName[0], &methodName[1], &methodName[2], &methodName[3], &methodName[4], &methodName[5], - &methodName[6], &methodName[7]); + &methodName[6], &methodName[7], + &methodName[8], &methodName[9]); + + TEST_NO_FAULT(&env); - for (i = 0; i < ARRAY_SIZE(methodName); ++i) { + for (i = 0; i < ARRAY_SIZE(expectedMethodName); ++i) { TEST(streq(methodName[i], expectedMethodName[i])); strfree(methodName[i]); } @@ -472,18 +499,70 @@ test_system_listMethods(xmlrpc_registry * const registryP) { static void -test_system_methodHelp(xmlrpc_registry * const registryP) { +test_system_methodExist(xmlrpc_registry * const registryP) { /*---------------------------------------------------------------------------- - Test system.methodHelp + Test system.methodExist -----------------------------------------------------------------------------*/ xmlrpc_env env; xmlrpc_value * resultP; xmlrpc_value * argArrayP; - const char * helpString; + xmlrpc_bool exists; xmlrpc_env_init(&env); - printf(" Running system.methodHelp tests."); + printf(" Running system.methodExist tests."); + + argArrayP = xmlrpc_build_value(&env, "(s)", "test.foo"); + TEST_NO_FAULT(&env); + + doRpc(&env, registryP, "system.methodExist", argArrayP, NULL, &resultP); + TEST_NO_FAULT(&env); + + TEST(xmlrpc_value_type(resultP) == XMLRPC_TYPE_BOOL); + + xmlrpc_read_bool(&env, resultP, &exists); + TEST_NO_FAULT(&env); + + TEST(exists); + + xmlrpc_DECREF(resultP); + + xmlrpc_DECREF(argArrayP); + + + argArrayP = xmlrpc_build_value(&env, "(s)", "nosuchmethod"); + TEST_NO_FAULT(&env); + + doRpc(&env, registryP, "system.methodExist", argArrayP, NULL, &resultP); + TEST_NO_FAULT(&env); + + TEST(xmlrpc_value_type(resultP) == XMLRPC_TYPE_BOOL); + + xmlrpc_read_bool(&env, resultP, &exists); + TEST_NO_FAULT(&env); + + TEST(!exists); + + xmlrpc_DECREF(resultP); + + xmlrpc_DECREF(argArrayP); + + xmlrpc_env_clean(&env); + + printf("\n"); +} + + + +static void +testNoHelp(xmlrpc_registry * const registryP) { + + xmlrpc_env env; + xmlrpc_value * resultP; + xmlrpc_value * argArrayP; + const char * helpString; + + xmlrpc_env_init(&env); argArrayP = xmlrpc_build_value(&env, "(s)", "test.foo"); TEST_NO_FAULT(&env); @@ -498,10 +577,26 @@ test_system_methodHelp(xmlrpc_registry * const registryP) { TEST(streq(helpString, "No help is available for this method.")); + strfree(helpString); + xmlrpc_DECREF(resultP); xmlrpc_DECREF(argArrayP); + xmlrpc_env_clean(&env); +} + + + +static void +testExistentHelp(xmlrpc_registry * const registryP) { + + xmlrpc_env env; + xmlrpc_value * resultP; + xmlrpc_value * argArrayP; + const char * helpString; + + xmlrpc_env_init(&env); argArrayP = xmlrpc_build_value(&env, "(s)", "test.bar"); TEST_NO_FAULT(&env); @@ -516,11 +611,31 @@ test_system_methodHelp(xmlrpc_registry * const registryP) { TEST(streq(helpString, barHelp)); + strfree(helpString); + xmlrpc_DECREF(resultP); xmlrpc_DECREF(argArrayP); xmlrpc_env_clean(&env); +} + + + +static void +test_system_methodHelp(xmlrpc_registry * const registryP) { +/*---------------------------------------------------------------------------- + Test system.methodHelp +-----------------------------------------------------------------------------*/ + xmlrpc_env env; + + xmlrpc_env_init(&env); + + printf(" Running system.methodHelp tests."); + + testNoHelp(registryP); + + testExistentHelp(registryP); printf("\n"); } @@ -560,6 +675,53 @@ test_system_capabilities(xmlrpc_registry * const registryP) { TEST(streq(facility, "xmlrpc-c")); TEST(protocol_version == 2); + strfree(facility); + + xmlrpc_DECREF(resultP); + + xmlrpc_DECREF(argArrayP); + + xmlrpc_env_clean(&env); + + printf("\n"); +} + + + +static void +test_system_getCapabilities(xmlrpc_registry * const registryP) { +/*---------------------------------------------------------------------------- + Test system.getCapabilities +-----------------------------------------------------------------------------*/ + xmlrpc_env env; + xmlrpc_value * resultP; + xmlrpc_value * argArrayP; + const char * specUrl; + int specVersion; + + xmlrpc_env_init(&env); + + printf(" Running system.getCapabilities tests."); + + argArrayP = xmlrpc_array_new(&env); + TEST_NO_FAULT(&env); + + doRpc(&env, registryP, "system.getCapabilities", argArrayP, NULL, + &resultP); + TEST_NO_FAULT(&env); + + xmlrpc_decompose_value(&env, resultP, "{s:{s:s,s:i,*},*}", + "introspect", + "specUrl", &specUrl, + "specVersion", &specVersion); + TEST_NO_FAULT(&env); + + TEST(streq(specUrl, + "http://xmlrpc-c.sourceforge.net/xmlrpc-c/introspection.html")); + TEST(specVersion == 1); + + strfree(specUrl); + xmlrpc_DECREF(resultP); xmlrpc_DECREF(argArrayP); @@ -629,11 +791,12 @@ test_system_multicall(xmlrpc_registry * const registryP) { TEST_NO_FAULT(&env); TEST(foo1_result == 42); TEST(bar_code == 123); - TEST(strcmp(bar_string, "Test fault") == 0); + TEST(streq(bar_string, "Test fault")); TEST(nosuch_code == XMLRPC_NO_SUCH_METHOD_ERROR); TEST(foo2_result == 42); xmlrpc_DECREF(multiP); free(bar_string); + free(nosuch_string); /* Now for some invalid multi calls */ @@ -737,7 +900,7 @@ testCall(xmlrpc_registry * const registryP) { 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); + TEST(env2.fault_string && streq(env2.fault_string, "Test fault")); xmlrpc_env_clean(&env2); /* Call a non-existant method and check the result. */ @@ -813,11 +976,11 @@ test_apache_dialect(void) { char const expectedResp[] = XML_PROLOGUE - "\r\n" + "\r\n" "\r\n" "\r\n" - "8\r\n" - "\r\n" + "8\r\n" + "\r\n" "\r\n" "\r\n" "\r\n"; @@ -891,6 +1054,8 @@ test_method_registry(void) { xmlrpc_env_init(&env); + testVersion(); + printf("Running method registry tests."); /* Create a new registry. */ @@ -932,10 +1097,14 @@ test_method_registry(void) { test_system_listMethods(registryP); + test_system_methodExist(registryP); + test_system_methodHelp(registryP); test_system_capabilities(registryP); + test_system_getCapabilities(registryP); + test_signature(); test_disable_introspection(); diff --git a/libs/xmlrpc-c/src/test/parse_xml.c b/libs/xmlrpc-c/src/test/parse_xml.c index ff98ab2..0f3237d 100644 --- a/libs/xmlrpc-c/src/test/parse_xml.c +++ b/libs/xmlrpc-c/src/test/parse_xml.c @@ -8,7 +8,7 @@ #include "xmlrpc-c/base.h" #include "xmlrpc-c/xmlparser.h" -#include "test.h" +#include "testtool.h" #include "xml_data.h" #include "parse_xml.h" @@ -74,7 +74,7 @@ char const xmldata[] = "10\r\n" "10\r\n" "10\r\n" - "10\r\n" + "10\r\n" "10\r\n" "10.1\r\n" "-10.1\r\n" @@ -152,9 +152,12 @@ char const xmldata[] = "1\r\n" "19980717T14:08:55" "\r\n" + "" + "19980717T14:08:55.123456" + "\r\n" "YmFzZTY0IGRhdGE=\r\n" "\r\n" - "\r\n" + "\r\n" "\r\n" "\r\n"; @@ -164,7 +167,8 @@ char const xmldata[] = int arraySize; const char * str_hello; xmlrpc_bool b_false, b_true; - const char * datetime; + const char * datetime_sec; + const char * datetime_usec; unsigned char * b64_data; size_t b64_len; @@ -177,24 +181,27 @@ char const xmldata[] = arraySize = xmlrpc_array_size(&env, paramArrayP); TEST_NO_FAULT(&env); - TEST(arraySize == 7); + TEST(arraySize == 8); xmlrpc_decompose_value( - &env, paramArrayP, "(sbb86nn)", - &str_hello, &b_false, &b_true, &datetime, &b64_data, &b64_len); + &env, paramArrayP, "(sbb886nn)", + &str_hello, &b_false, &b_true, &datetime_sec, &datetime_usec, + &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(streq(datetime_sec, "19980717T14:08:55")); + TEST(streq(datetime_usec, "19980717T14:08:55.123456")); TEST(b64_len == 11); TEST(memcmp(b64_data, "base64 data", b64_len) == 0); free(b64_data); strfree(str_hello); - strfree(datetime); + strfree(datetime_sec); + strfree(datetime_usec); xmlrpc_DECREF(paramArrayP); strfree(methodName); @@ -496,7 +503,7 @@ testParseFaultResponse(void) { static void -test_parse_xml_call(void) { +testParseXmlCall(void) { xmlrpc_env env; const char *method_name; @@ -547,6 +554,38 @@ test_parse_xml_call(void) { +static void +testParseXmlValue(void) { + + const char * const xmlInt7 = "7"; + const char * const xmlBadVal1 = "hello"; + const char * const xmlBadVal2 = ""; + + xmlrpc_value * valueP; + + xmlrpc_env env; + + xmlrpc_env_init(&env); + + xmlrpc_parse_value_xml(&env, xmlInt7, strlen(xmlInt7), &valueP); + + TEST_NO_FAULT(&env); + + xmlrpc_DECREF(valueP); + + xmlrpc_parse_value_xml(&env, xmlBadVal1, strlen(xmlBadVal1), &valueP); + TEST_FAULT(&env, XMLRPC_PARSE_ERROR); + xmlrpc_env_clean(&env); + + xmlrpc_env_init(&env); + xmlrpc_parse_value_xml(&env, xmlBadVal2, strlen(xmlBadVal2), &valueP); + TEST_FAULT(&env, XMLRPC_PARSE_ERROR); + + xmlrpc_env_clean(&env); +} + + + void test_parse_xml(void) { @@ -557,7 +596,8 @@ test_parse_xml(void) { testParseGoodResponse(); testParseFaultResponse(); testParseBadResponse(); - test_parse_xml_call(); + testParseXmlCall(); + testParseXmlValue(); printf("\n"); printf("XML parsing tests done.\n"); } diff --git a/libs/xmlrpc-c/src/test/req_out_of_order.xml b/libs/xmlrpc-c/src/test/req_out_of_order.xml deleted file mode 100644 index 8b078a4..0000000 --- a/libs/xmlrpc-c/src/test/req_out_of_order.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - 2 - - - 2 - - - add - diff --git a/libs/xmlrpc-c/src/test/req_value_name.xml b/libs/xmlrpc-c/src/test/req_value_name.xml deleted file mode 100644 index b55d4f0..0000000 --- a/libs/xmlrpc-c/src/test/req_value_name.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - foo - - - - - 0 - child elements reversed! - - - - - diff --git a/libs/xmlrpc-c/src/test/sample_add_call.xml b/libs/xmlrpc-c/src/test/sample_add_call.xml deleted file mode 100644 index b11336a..0000000 --- a/libs/xmlrpc-c/src/test/sample_add_call.xml +++ /dev/null @@ -1,8 +0,0 @@ - - -sample.add - -5 -7 - - diff --git a/libs/xmlrpc-c/src/test/serialize.c b/libs/xmlrpc-c/src/test/serialize.c index 74fe86c..275aa78 100644 --- a/libs/xmlrpc-c/src/test/serialize.c +++ b/libs/xmlrpc-c/src/test/serialize.c @@ -6,7 +6,7 @@ #include "xmlrpc-c/base.h" -#include "test.h" +#include "testtool.h" #include "xml_data.h" #include "girstring.h" #include "serialize_value.h" @@ -176,8 +176,8 @@ test_serialize_apache_value(void) { char const serializedData[] = "\r\n" "7\r\n" - "8\r\n" - "\r\n" + "8\r\n" + "\r\n" ""; xmlrpc_env env; @@ -214,7 +214,7 @@ test_serialize_apache_params(void) { char const serializedData[] = "\r\n" "7\r\n" - "8\r\n" + "8\r\n" "\r\n"; xmlrpc_env env; @@ -251,9 +251,9 @@ test_serialize_apache_response(void) { char const serializedData[] = XML_PROLOGUE - "\r\n" + "\r\n" "\r\n" - "8\r\n" + "8\r\n" "\r\n" "\r\n"; diff --git a/libs/xmlrpc-c/src/test/serialize_value.c b/libs/xmlrpc-c/src/test/serialize_value.c index 3a59253..a8d17a3 100644 --- a/libs/xmlrpc-c/src/test/serialize_value.c +++ b/libs/xmlrpc-c/src/test/serialize_value.c @@ -6,7 +6,7 @@ #include "xmlrpc-c/base.h" -#include "test.h" +#include "testtool.h" #include "girstring.h" #include "serialize_value.h" @@ -173,6 +173,7 @@ test_serialize_double(void) { testOneDouble(1); testOneDouble(0.3); testOneDouble(4.9); + testOneDouble(9.9999999); testOneDouble(-8); testOneDouble(-.7); testOneDouble(-2.5); diff --git a/libs/xmlrpc-c/src/test/server_abyss.c b/libs/xmlrpc-c/src/test/server_abyss.c index 11e1476..24a8233 100644 --- a/libs/xmlrpc-c/src/test/server_abyss.c +++ b/libs/xmlrpc-c/src/test/server_abyss.c @@ -1,5 +1,6 @@ #include "unistdx.h" #include +#include "bool.h" #include "xmlrpc_config.h" @@ -8,16 +9,32 @@ #include "xmlrpc-c/abyss.h" #include "xmlrpc-c/server_abyss.h" -#include "test.h" +#include "testtool.h" #include "server_abyss.h" +static xmlrpc_call_processor myXmlProcessor; + +static void +myXmlProcessor(xmlrpc_env * const envP ATTR_UNUSED, + void * const processorArg ATTR_UNUSED, + const char * const callXml ATTR_UNUSED, + size_t const callXmlLen ATTR_UNUSED, + TSession * const abyssSessionP ATTR_UNUSED, + xmlrpc_mem_block ** const responseXmlPP ATTR_UNUSED) { + + printf("XML processor running\n"); +} + + + static void testSetHandlers(TServer * const abyssServerP) { xmlrpc_env env; xmlrpc_registry * registryP; + xmlrpc_server_abyss_handler_parms parms; xmlrpc_env_init(&env); @@ -25,11 +42,32 @@ testSetHandlers(TServer * const abyssServerP) { TEST_NO_FAULT(&env); TEST(registryP != NULL); + parms.xml_processor = &myXmlProcessor; + parms.xml_processor_arg = NULL; + parms.xml_processor_max_stack = 512; + parms.uri_path = "/RPC6"; + parms.chunk_response = true; + parms.allow_origin = "*"; + + xmlrpc_server_abyss_set_handler3( + &env, abyssServerP, &parms, XMLRPC_AHPSIZE(xml_processor_arg)); + TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR); /* Parms too short */ + xmlrpc_server_abyss_set_handler3( + &env, abyssServerP, &parms, XMLRPC_AHPSIZE(allow_origin)); + TEST_NO_FAULT(&env); + + xmlrpc_server_abyss_set_handler2(abyssServerP, "/RPC5", + &myXmlProcessor, NULL, 512, true); + xmlrpc_server_abyss_set_handler(&env, abyssServerP, "/RPC3", registryP); TEST_NO_FAULT(&env); xmlrpc_server_abyss_set_handlers2(abyssServerP, "/RPC4", registryP); + xmlrpc_server_abyss_set_handlers(abyssServerP, registryP); + + xmlrpc_server_abyss_set_default_handler(abyssServerP); + xmlrpc_registry_free(registryP); { @@ -57,6 +95,7 @@ testServerParms(void) { parms.dont_advertise = TRUE; parms.uri_path = "/RPC9"; parms.chunk_response = TRUE; + parms.allow_origin = "*"; }; @@ -108,6 +147,8 @@ testObject(void) { xmlrpc_server_abyss_restore_sig(oldHandlersP); TEST_NO_FAULT(&env); + free(oldHandlersP); + xmlrpc_server_abyss_destroy(serverP); xmlrpc_registry_free(registryP); diff --git a/libs/xmlrpc-c/src/test/test.c b/libs/xmlrpc-c/src/test/test.c index 1b9c2d3..d7d0d9c 100644 --- a/libs/xmlrpc-c/src/test/test.c +++ b/libs/xmlrpc-c/src/test/test.c @@ -17,9 +17,10 @@ #include "xmlrpc-c/base.h" #include "xmlrpc-c/server.h" +#include "xmlrpc-c/string_int.h" #include "bool.h" -#include "test.h" +#include "testtool.h" #include "value.h" #include "serialize.h" #include "parse_xml.h" @@ -76,8 +77,26 @@ static int test_int_array_3[8] = {1, 2, 3, 4, 5, 6, 7, 8}; **========================================================================= */ -static void test_env(void) -{ +static void +testVersion(void) { + + unsigned int major, minor, point; + + xmlrpc_version(&major, &minor, &point); + +#ifndef WIN32 + /* xmlrpc_version_major, etc. are not exported from a Windows DLL */ + + TEST(major = xmlrpc_version_major); + TEST(minor = xmlrpc_version_minor); + TEST(point = xmlrpc_version_point); +#endif +} + + + +static void +testEnv(void) { xmlrpc_env env, env2; /* Test xmlrpc_env_init. */ @@ -91,19 +110,19 @@ static void test_env(void) TEST(env.fault_occurred); TEST(env.fault_code == 1); TEST(env.fault_string != test_string_1); - TEST(strcmp(env.fault_string, test_string_1) == 0); + TEST(xmlrpc_streq(env.fault_string, test_string_1)); /* Change an existing fault. */ xmlrpc_env_set_fault(&env, 2, test_string_2); TEST(env.fault_occurred); TEST(env.fault_code == 2); - TEST(strcmp(env.fault_string, test_string_2) == 0); + TEST(xmlrpc_streq(env.fault_string, test_string_2)); /* Set a fault with a format string. */ xmlrpc_env_set_fault_formatted(&env, 3, "a%s%d", "bar", 9); TEST(env.fault_occurred); TEST(env.fault_code == 3); - TEST(strcmp(env.fault_string, "abar9") == 0); + TEST(xmlrpc_streq(env.fault_string, "abar9")); /* Test cleanup code (with help from memprof). */ xmlrpc_env_clean(&env); @@ -113,8 +132,10 @@ static void test_env(void) xmlrpc_env_clean(&env2); } -static void test_mem_block (void) -{ + + +static void +testMemBlock(void) { xmlrpc_env env; xmlrpc_mem_block* block; @@ -141,7 +162,7 @@ static void test_mem_block (void) xmlrpc_mem_block_resize(&env, block, 10000); TEST_NO_FAULT(&env); TEST(xmlrpc_mem_block_size(block) == 10000); - TEST(strcmp(xmlrpc_mem_block_contents(block), test_string_1) == 0); + TEST(xmlrpc_streq(xmlrpc_mem_block_contents(block), test_string_1)); /* Test cleanup code (with help from memprof). */ xmlrpc_mem_block_free(block); @@ -190,6 +211,8 @@ static void test_mem_block (void) xmlrpc_env_clean(&env); } + + static char *(base64_triplets[]) = { "", "", "\r\n", "a", "YQ==", "YQ==\r\n", @@ -204,8 +227,11 @@ static char *(base64_triplets[]) = { "ZmdoaWprbG1ub3BxcnN0dXZ3eHl6QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo=\r\n", NULL}; + + static void -test_base64_conversion(void) { +testBase64Conversion(void) { + xmlrpc_env env; char ** triplet; @@ -280,8 +306,9 @@ test_base64_conversion(void) { -static void test_bounds_checks (void) -{ +static void +testBoundsChecks(void) { + xmlrpc_env env; xmlrpc_value *array; int i1, i2, i3, i4; @@ -310,8 +337,9 @@ static void test_bounds_checks (void) -static void test_nesting_limit (void) -{ +static void +testNestingLimit(void) { + xmlrpc_env env; xmlrpc_value *val; @@ -346,7 +374,7 @@ static void test_nesting_limit (void) static void -test_xml_size_limit(void) { +testXmlSizeLimit(void) { xmlrpc_env env; const char * methodName; @@ -395,12 +423,13 @@ test_xml_size_limit(void) { ** We use these files to test strange-but-legal encodings, illegal-but- ** allowed-by-Xmlrpc-c encodings, etc. */ -#ifdef WIN32 -/* usually compiled in 'Windows' folder */ -#define TESTDATA_DIR ".." DIRECTORY_SEPARATOR "bin" DIRECTORY_SEPARATOR "data" -#else + +/* The test program is designed to be run with the 'test' source directory + (which also contains the test program itself) as the current + directory. Except on Windows, where the Bin directory (which also contains + the test program itself) is supposed to be the current directory. +*/ #define TESTDATA_DIR "data" -#endif static const char * goodRequests[] = { TESTDATA_DIR DIRECTORY_SEPARATOR "req_out_of_order.xml", @@ -649,9 +678,8 @@ test_utf8_coding(void) { TEST_NO_FAULT(&env); TEST(output != NULL); TEST(strlen(utf8) == XMLRPC_TYPED_MEM_BLOCK_SIZE(char, output)); - TEST(0 == - strncmp(utf8, XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, output), - strlen(utf8))); + TEST(xmlrpc_strneq(utf8, XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, output), + strlen(utf8))); xmlrpc_mem_block_free(output); } @@ -713,18 +741,19 @@ main(int argc, fprintf(stderr, "There are no arguments.\n"); retval = 1; } else { - test_env(); - test_mem_block(); - test_base64_conversion(); + testVersion(); + testEnv(); + testMemBlock(); + testBase64Conversion(); printf("\n"); test_value(); - test_bounds_checks(); + testBoundsChecks(); printf("\n"); test_serialize(); test_parse_xml(); test_method_registry(); - test_nesting_limit(); - test_xml_size_limit(); + testNestingLimit(); + testXmlSizeLimit(); testSampleFiles(); printf("\n"); test_server_cgi_maybe(); diff --git a/libs/xmlrpc-c/src/test/test.h b/libs/xmlrpc-c/src/test/test.h deleted file mode 100644 index 70a8371..0000000 --- a/libs/xmlrpc-c/src/test/test.h +++ /dev/null @@ -1,109 +0,0 @@ -#include -#include -#include - -#include "xmlrpc_config.h" -#include "xmlrpc-c/util.h" -#include "xmlrpc-c/util_int.h" - -extern int total_tests; -extern int total_failures; - - -/* This is a good place to set a breakpoint. */ -static __inline__ void -test_failure(const char * const file, - unsigned int const line, - const char * const label, - const char * const statement) { - - ++total_failures; - printf("\n%s:%u: test failure: %s (%s)\n", file, line, label, statement); - abort(); -} - - - -#define TEST(statement) \ -do { \ - ++total_tests; \ - if ((statement)) { \ - printf("."); \ - } else { \ - test_failure(__FILE__, __LINE__, "expected", #statement); \ - } \ - } while (0) - -#define TEST_NO_FAULT(env) \ - do { \ - ++total_tests; \ - if (!(env)->fault_occurred) { \ - printf("."); \ - } else { \ - test_failure(__FILE__, __LINE__, "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) - -; diff --git a/libs/xmlrpc-c/src/test/testtool.c b/libs/xmlrpc-c/src/test/testtool.c new file mode 100644 index 0000000..85d2e8c --- /dev/null +++ b/libs/xmlrpc-c/src/test/testtool.c @@ -0,0 +1,65 @@ +#include +#include + +#include "xmlrpc_config.h" +#include "xmlrpc-c/util.h" +#include "xmlrpc-c/util_int.h" + +#include "testtool.h" + /* Defines global variable, 'total_tests', 'total_failures' */ + + +/* This is a good place to set a breakpoint. */ +void +test_failure(const char * const file, + unsigned int const line, + const char * const label, + const char * const statement) { + + ++total_failures; + printf("\n%s:%u: test failure: %s (%s)\n", file, line, label, statement); + + /* We abort rather than exit so one can tell from a dump or debug session + who called us. + */ + abort(); +} + + + +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); +} + + + +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("."); +} + + diff --git a/libs/xmlrpc-c/src/test/testtool.h b/libs/xmlrpc-c/src/test/testtool.h new file mode 100644 index 0000000..8aeeebc --- /dev/null +++ b/libs/xmlrpc-c/src/test/testtool.h @@ -0,0 +1,80 @@ +#ifndef TESTTOOL_H_INCLUDED +#define TESTTOOL_H_INCLUDED + +#include +#include +#include + +#include "xmlrpc-c/util.h" +#include "xmlrpc-c/util_int.h" + +extern int total_tests; +extern int total_failures; + + +void +test_failure(const char * const file, + unsigned int const line, + const char * const label, + const char * const statement); + +void +test_fault(xmlrpc_env * const envP, + int const expectedCode, + const char * const fileName, + unsigned int const lineNumber); + +void +test_null_string(const char * const string, + const char * const fileName, + unsigned int const lineNumber); + +#define TEST(statement) \ +do { \ + ++total_tests; \ + if ((statement)) { \ + printf("."); \ + } else { \ + test_failure(__FILE__, __LINE__, "expected", #statement); \ + } \ + } while (0) + +#define TEST_NO_FAULT(env) \ + do { \ + ++total_tests; \ + if (!(env)->fault_occurred) { \ + printf("."); \ + } else { \ + test_failure(__FILE__, __LINE__, "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)) + +#define TEST_FAULT(envP, code) \ + do { test_fault(envP, code, __FILE__, __LINE__); } while(0) + +; + +#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) + +; + +#endif diff --git a/libs/xmlrpc-c/src/test/value.c b/libs/xmlrpc-c/src/test/value.c index bda938c..6ed6c47 100644 --- a/libs/xmlrpc-c/src/test/value.c +++ b/libs/xmlrpc-c/src/test/value.c @@ -13,7 +13,9 @@ #include "xmlrpc-c/base.h" #include "xmlrpc-c/string_int.h" -#include "test.h" +#include "testtool.h" +#include "value_datetime.h" + #include "value.h" @@ -158,197 +160,6 @@ test_value_double(void) { -static void -test_value_datetime_varytime(const char * const datestring, - time_t const datetime) { - - xmlrpc_value * v; - xmlrpc_env env; - const char * ds; - time_t dt; - - xmlrpc_env_init(&env); - - v = xmlrpc_datetime_new_str(&env, datestring); - TEST_NO_FAULT(&env); - TEST(XMLRPC_TYPE_DATETIME == xmlrpc_value_type(v)); - - xmlrpc_read_datetime_sec(&env, v, &dt); - TEST_NO_FAULT(&env); - TEST(dt == datetime); - - xmlrpc_DECREF(v); - - v = xmlrpc_datetime_new_sec(&env, datetime); - TEST_NO_FAULT(&env); - TEST(XMLRPC_TYPE_DATETIME == xmlrpc_value_type(v)); - - xmlrpc_read_datetime_str(&env, v, &ds); - TEST_NO_FAULT(&env); - 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_value_type(v) == XMLRPC_TYPE_DATETIME); - xmlrpc_decompose_value(&env, v, "8", &ds); - xmlrpc_DECREF(v); - TEST_NO_FAULT(&env); - TEST(streq(ds, datestring)); - strfree(ds); - - xmlrpc_env_clean(&env); -} - - - -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, @@ -711,7 +522,7 @@ test_value_string_wide_build(void) { xmlrpc_env_init(&env); /* Build with build_value w# */ - valueP = xmlrpc_build_value(&env, "w#", wcs_data, 3); + valueP = xmlrpc_build_value(&env, "w#", wcs_data, (size_t)3); TEST_NO_FAULT(&env); TEST(valueP != NULL); @@ -849,7 +660,7 @@ test_value_string_wide(void) { TEST(str != NULL); TEST(len == 4); TEST(str[len] == '\0'); - TEST(0 == strncmp(str, utf8_data, len)); + TEST(xmlrpc_strneq(str, utf8_data, len)); free((void*)str); } @@ -952,7 +763,7 @@ test_value_base64(void) { TEST_NO_FAULT(&env); TEST(len == sizeof(data2)); TEST(memeq(data, data1, sizeof(data2))); - strfree(data); + free((void *)data); xmlrpc_env_clean(&env); } @@ -992,6 +803,7 @@ test_value_array(void) { xmlrpc_value *v; xmlrpc_env env; size_t len; + xmlrpc_value * itemP; /* Basic array-building test. */ @@ -1005,6 +817,16 @@ test_value_array(void) { len = xmlrpc_array_size(&env, v); TEST_NO_FAULT(&env); TEST(len == 0); + + itemP = xmlrpc_int_new(&env, 7); + TEST_NO_FAULT(&env); + xmlrpc_array_append_item(&env, v, itemP); + TEST_NO_FAULT(&env); + len = xmlrpc_array_size(&env, v); + TEST_NO_FAULT(&env); + TEST(len == 1); + xmlrpc_DECREF(itemP); + xmlrpc_DECREF(v); v = xmlrpc_build_value(&env, "()"); @@ -1234,20 +1056,48 @@ test_value_array_nil(void) { static void +destroyMyCptr(void * const context, + void * const objectP) { +/*---------------------------------------------------------------------------- + This is a xmlrpc_cptr_dtor_fn. +-----------------------------------------------------------------------------*/ + int * const destroyConfirmationP = context; + int * const objectIntP = objectP; + + *destroyConfirmationP = *objectIntP; +} + + + +static void test_value_cptr(void) { + int destroyConfirmation; + xmlrpc_value * v; xmlrpc_env env; void * ptr; - - /* Test C pointer storage using 'p'. - We don't have cleanup functions (yet). - */ + int myObject; xmlrpc_env_init(&env); TEST(streq(xmlrpc_type_name(XMLRPC_TYPE_C_PTR), "C_PTR")); + myObject = 7; + + v = xmlrpc_cptr_new(&env, &myObject); + TEST_NO_FAULT(&env); + TEST(xmlrpc_value_type(v) == XMLRPC_TYPE_C_PTR); + xmlrpc_DECREF(v); + + v = xmlrpc_cptr_new_dtor(&env, &myObject, + &destroyMyCptr, &destroyConfirmation); + TEST_NO_FAULT(&env); + TEST(xmlrpc_value_type(v) == XMLRPC_TYPE_C_PTR); + destroyConfirmation = 3; + xmlrpc_DECREF(v); + TEST(destroyConfirmation == 7); // the destructor has set this + v = xmlrpc_build_value(&env, "p", (void*) 0x00000017); TEST_NO_FAULT(&env); TEST(XMLRPC_TYPE_C_PTR == xmlrpc_value_type(v)); @@ -1273,7 +1123,7 @@ test_value_nil(void) { v = xmlrpc_nil_new(&env); TEST_NO_FAULT(&env); - TEST(XMLRPC_TYPE_NIL == xmlrpc_value_type(v)); + TEST(xmlrpc_value_type(v) == XMLRPC_TYPE_NIL); xmlrpc_DECREF(v); v = xmlrpc_build_value(&env, "n"); @@ -1465,7 +1315,7 @@ test_value_parse_value(void) { valueP = xmlrpc_build_value(&env, "(idb8ss#6(i){s:i}np(i))", 7, 3.14, (xmlrpc_bool)1, datestring, - "hello world", "a\0b", 3, + "hello world", "a\0b", (size_t)3, "base64 data", strlen("base64 data"), 15, "member9", 9, &valueP, -5); @@ -1610,7 +1460,7 @@ test_struct_get_element(xmlrpc_value * const structP, static void testStructReadout(xmlrpc_value * const structP, - size_t const expectedSize) { + unsigned int const expectedSize) { xmlrpc_env env; xmlrpc_value * keyP; @@ -1753,6 +1603,10 @@ test_struct_decompose(xmlrpc_value * const testStructP) { "foo", &sval, "bar", &ival); TEST_NO_FAULT(&env); + TEST(ival == 1); + TEST(!bval); + TEST(streq(sval, "Hello!")); + free(sval); /* First value of wrong type */ xmlrpc_decompose_value(&env, testStructP, "{s:b,s:i,*}", diff --git a/libs/xmlrpc-c/src/test/value_datetime.c b/libs/xmlrpc-c/src/test/value_datetime.c new file mode 100644 index 0000000..6671713 --- /dev/null +++ b/libs/xmlrpc-c/src/test/value_datetime.c @@ -0,0 +1,424 @@ +#define _XOPEN_SOURCE 600 /* Make sure strdup() is in */ + +#include +#include +#include +#include + +#include "casprintf.h" +#include "girstring.h" + +#include "xmlrpc_config.h" + +#include "xmlrpc-c/base.h" +#include "xmlrpc-c/string_int.h" + +#include "testtool.h" + +#include "value_datetime.h" + + + +static const char * +truncateFracSec(const char * const datestring) { +/*---------------------------------------------------------------------------- + Return 'datestring', but with any fractional seconds chopped off. + E.g. if 'datestring' is "20000301T00:00:00.654321", + we return "20000301T00:00:00". +-----------------------------------------------------------------------------*/ + char * buffer; + unsigned int i; + + buffer = strdup(datestring); + + for (i = 0; i < strlen(buffer); ++i) { + if (buffer[i] == '.') + buffer[i] = '\0'; + } + return buffer; +} + + + +#if XMLRPC_HAVE_TIMEVAL + +static struct timeval +makeTv(time_t const secs, + unsigned int const usecs) { + + struct timeval retval; + + retval.tv_sec = secs; + retval.tv_usec = usecs; + + return retval; +} + +static bool +tvIsEqual(struct timeval const comparand, + struct timeval const comparator) { + return + comparand.tv_sec == comparator.tv_sec && + comparand.tv_usec == comparator.tv_usec; +} +#endif + + + +#if XMLRPC_HAVE_TIMESPEC + +static struct timespec +makeTs(time_t const secs, + unsigned int const usecs) { + + struct timespec retval; + + retval.tv_sec = secs; + retval.tv_nsec = usecs * 1000; + + return retval; +} + +static bool +tsIsEqual(struct timespec const comparand, + struct timespec const comparator) { + return + comparand.tv_sec == comparator.tv_sec && + comparand.tv_nsec == comparator.tv_nsec; +} +#endif + + + +static void +test_value_datetime_varytime(const char * const datestring, + time_t const datetime, + unsigned int const usec) { + + xmlrpc_value * v; + xmlrpc_env env; + const char * readBackString; + time_t readBackDt; + unsigned int readBackUsec; + const char * datestringSec; +#if XMLRPC_HAVE_TIMEVAL + struct timeval const dtTimeval = makeTv(datetime, usec); + struct timeval readBackTv; +#endif +#if XMLRPC_HAVE_TIMESPEC + struct timespec const dtTimespec = makeTs(datetime, usec); + struct timespec readBackTs; +#endif + + datestringSec = truncateFracSec(datestring); + + xmlrpc_env_init(&env); + + /* Test xmlrpc_datetime_new_str and time read functions*/ + v = xmlrpc_datetime_new_str(&env, datestring); + TEST_NO_FAULT(&env); + TEST(XMLRPC_TYPE_DATETIME == xmlrpc_value_type(v)); + + xmlrpc_read_datetime_sec(&env, v, &readBackDt); + TEST_NO_FAULT(&env); + TEST(readBackDt == datetime); + + xmlrpc_read_datetime_usec(&env, v, &readBackDt, &readBackUsec); + TEST_NO_FAULT(&env); + TEST(readBackDt == datetime); + TEST(readBackUsec == usec); + +#if XMLRPC_HAVE_TIMEVAL + xmlrpc_read_datetime_timeval(&env, v, &readBackTv); + TEST_NO_FAULT(&env); + TEST(tvIsEqual(dtTimeval, readBackTv)); +#endif + +#if XMLRPC_HAVE_TIMESPEC + xmlrpc_read_datetime_timespec(&env, v, &readBackTs); + TEST_NO_FAULT(&env); + TEST(tsIsEqual(dtTimespec, readBackTs)); +#endif + + xmlrpc_DECREF(v); + + /* Test xmlrpc_datetime_new_sec */ + v = xmlrpc_datetime_new_sec(&env, datetime); + TEST_NO_FAULT(&env); + TEST(XMLRPC_TYPE_DATETIME == xmlrpc_value_type(v)); + + xmlrpc_read_datetime_str(&env, v, &readBackString); + TEST_NO_FAULT(&env); + TEST(streq(readBackString, datestringSec)); + strfree(readBackString); + + xmlrpc_DECREF(v); + + /* Test xmlrpc_datetime_new_usec */ + v = xmlrpc_datetime_new_usec(&env, datetime, usec); + TEST_NO_FAULT(&env); + TEST(XMLRPC_TYPE_DATETIME == xmlrpc_value_type(v)); + + xmlrpc_read_datetime_str(&env, v, &readBackString); + TEST_NO_FAULT(&env); + TEST(streq(readBackString, datestring)); + strfree(readBackString); + + xmlrpc_DECREF(v); + +#if XMLRPC_HAVE_TIMEVAL + /* Test xmlrpc_datetime_new_timeval */ + v = xmlrpc_datetime_new_timeval(&env, dtTimeval); + TEST_NO_FAULT(&env); + TEST(XMLRPC_TYPE_DATETIME == xmlrpc_value_type(v)); + + xmlrpc_read_datetime_str(&env, v, &readBackString); + TEST_NO_FAULT(&env); + TEST(streq(readBackString, datestring)); + strfree(readBackString); + + xmlrpc_DECREF(v); +#endif + +#if XMLRPC_HAVE_TIMESPEC + /* Test xmlrpc_datetime_new_timespec */ + v = xmlrpc_datetime_new_timespec(&env, dtTimespec); + TEST_NO_FAULT(&env); + TEST(XMLRPC_TYPE_DATETIME == xmlrpc_value_type(v)); + + xmlrpc_read_datetime_str(&env, v, &readBackString); + TEST_NO_FAULT(&env); + TEST(streq(readBackString, datestring)); + strfree(readBackString); + + xmlrpc_DECREF(v); +#endif + + xmlrpc_env_clean(&env); + strfree(datestringSec); +} + + + +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_str_invalid1(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_value_datetime_str_invalid2(const char * const datestring) { + + xmlrpc_value * v; + xmlrpc_env env; + + xmlrpc_env_init(&env); + + v = xmlrpc_datetime_new_str(&env, datestring); + TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR); + + 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_value_type(v) == XMLRPC_TYPE_DATETIME); + xmlrpc_decompose_value(&env, v, "8", &ds); + xmlrpc_DECREF(v); + TEST_NO_FAULT(&env); + TEST(streq(ds, datestring)); + strfree(ds); + + xmlrpc_env_clean(&env); +} + + + + +static void +test_value_datetime_basic(void) { + + xmlrpc_value * v; + xmlrpc_env env; + xmlrpc_datetime dt; + xmlrpc_datetime readBackDt; + + xmlrpc_env_init(&env); + + dt.Y = 2001; + dt.M = 12; + dt.D = 25; + dt.h = 1; + dt.m = 2; + dt.s = 3; + dt.u = 4; + + v = xmlrpc_datetime_new(&env, dt); + + xmlrpc_read_datetime(&env, v, &readBackDt); + TEST_NO_FAULT(&env); + TEST(readBackDt.Y = dt.Y); + TEST(readBackDt.M = dt.M); + TEST(readBackDt.D = dt.D); + TEST(readBackDt.h = dt.h); + TEST(readBackDt.m = dt.m); + TEST(readBackDt.s = dt.s); + TEST(readBackDt.u = dt.u); + + xmlrpc_env_clean(&env); +} + + + +void +test_value_datetime(void) { + + const char * datestring = "19980717T14:08:55"; + time_t const datetime = 900684535; + + xmlrpc_env env; + + printf("\n Running datetime value tests"); + + xmlrpc_env_init(&env); + + TEST(streq(xmlrpc_type_name(XMLRPC_TYPE_DATETIME), "DATETIME")); + + test_value_datetime_basic(); + + /* Valid datetime, generated from XML-RPC string, time_t, and + time_t + microseconds + */ + + test_value_datetime_varytime(datestring, datetime, 0); + + /* test microseconds */ + test_value_datetime_varytime("20000301T00:00:00.654321", + 951868800, 654321); + test_value_datetime_varytime("20040229T23:59:59.123000", + 1078099199, 123000); + test_value_datetime_varytime("20000229T23:59:59.000123", + 951868799, 123); + + /* Leap years */ + test_value_datetime_varytime("20000229T23:59:59", 951868799, 0); + test_value_datetime_varytime("20000301T00:00:00", 951868800, 0); + test_value_datetime_varytime("20010228T23:59:59", 983404799, 0); + test_value_datetime_varytime("20010301T00:00:00", 983404800, 0); + test_value_datetime_varytime("20040229T23:59:59", 1078099199, 0); + test_value_datetime_varytime("20040301T00:00:00", 1078099200, 0); + + /* 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_str_invalid1("19700101T25:00:00"); + test_value_datetime_str_invalid1("19700101T10:61:01"); + test_value_datetime_str_invalid1("19700101T10:59:61"); + test_value_datetime_str_invalid1("19700001T10:00:00"); + test_value_datetime_str_invalid1("19701301T10:00:00"); + test_value_datetime_str_invalid1("19700132T10:00:00"); + test_value_datetime_str_invalid2("19700132T10:00:00."); + test_value_datetime_str_invalid2("19700132T10:00:00,123"); + + test_build_decomp_datetime(); + + xmlrpc_env_clean(&env); + + printf("\n"); + printf(" datetime value tests done.\n"); +} diff --git a/libs/xmlrpc-c/src/test/value_datetime.h b/libs/xmlrpc-c/src/test/value_datetime.h new file mode 100644 index 0000000..5a26f60 --- /dev/null +++ b/libs/xmlrpc-c/src/test/value_datetime.h @@ -0,0 +1,7 @@ +#ifndef VALUE_DATETIME_H_INCLUDED +#define VALUE_DATETIME_H_INCLUDED + +void +test_value_datetime(void); + +#endif diff --git a/libs/xmlrpc-c/src/test/xml_data.h b/libs/xmlrpc-c/src/test/xml_data.h index 4b34238..89b5e49 100644 --- a/libs/xmlrpc-c/src/test/xml_data.h +++ b/libs/xmlrpc-c/src/test/xml_data.h @@ -3,6 +3,9 @@ #define XML_PROLOGUE "\r\n" +#define APACHE_URL "http://ws.apache.org/xmlrpc/namespaces/extensions" +#define XMLNS_APACHE "xmlns:ex=\"" APACHE_URL "\"" + extern char const serialized_data[]; extern char const serialized_call[]; diff --git a/libs/xmlrpc-c/src/trace.c b/libs/xmlrpc-c/src/trace.c index 53d54f3..bb65945 100644 --- a/libs/xmlrpc-c/src/trace.c +++ b/libs/xmlrpc-c/src/trace.c @@ -36,7 +36,7 @@ nextLineSize(const char * const string, void xmlrpc_traceXml(const char * const label, const char * const xml, - unsigned int const xmlLength) { + size_t const xmlLength) { if (getenv("XMLRPC_TRACE_XML")) { size_t cursor; /* Index into xml[] */ @@ -60,3 +60,4 @@ xmlrpc_traceXml(const char * const label, } } + diff --git a/libs/xmlrpc-c/src/version.c b/libs/xmlrpc-c/src/version.c index c286966..07a2d43 100644 --- a/libs/xmlrpc-c/src/version.c +++ b/libs/xmlrpc-c/src/version.c @@ -5,3 +5,14 @@ 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; + +void +xmlrpc_version(unsigned int * const majorP, + unsigned int * const minorP, + unsigned int * const pointP) { + + *majorP = XMLRPC_VERSION_MAJOR; + *minorP = XMLRPC_VERSION_MINOR; + *pointP = XMLRPC_VERSION_POINT; +} + diff --git a/libs/xmlrpc-c/src/xmlrpc_array.c b/libs/xmlrpc-c/src/xmlrpc_array.c index a474546..0de210e 100644 --- a/libs/xmlrpc-c/src/xmlrpc_array.c +++ b/libs/xmlrpc-c/src/xmlrpc_array.c @@ -7,6 +7,7 @@ #include "xmlrpc_config.h" +#include #include #include @@ -24,7 +25,7 @@ xmlrpc_abort_if_array_bad(xmlrpc_value * const arrayP) { else if (arrayP->_type != XMLRPC_TYPE_ARRAY) abort(); else { - unsigned int const arraySize = + size_t const arraySize = XMLRPC_MEMBLOCK_SIZE(xmlrpc_value*, &arrayP->_block); xmlrpc_value ** const contents = XMLRPC_MEMBLOCK_CONTENTS(xmlrpc_value*, &arrayP->_block); @@ -32,7 +33,7 @@ xmlrpc_abort_if_array_bad(xmlrpc_value * const arrayP) { if (contents == NULL) abort(); else { - unsigned int index; + size_t index; for (index = 0; index < arraySize; ++index) { xmlrpc_value * const itemP = contents[index]; @@ -53,12 +54,12 @@ xmlrpc_destroyArrayContents(xmlrpc_value * const arrayP) { Dispose of the contents of an array (but not the array value itself). The value is not valid after this. -----------------------------------------------------------------------------*/ - unsigned int const arraySize = + size_t const arraySize = XMLRPC_MEMBLOCK_SIZE(xmlrpc_value*, &arrayP->_block); xmlrpc_value ** const contents = XMLRPC_MEMBLOCK_CONTENTS(xmlrpc_value*, &arrayP->_block); - unsigned int index; + size_t index; XMLRPC_ASSERT_ARRAY_OK(arrayP); @@ -73,25 +74,27 @@ xmlrpc_destroyArrayContents(xmlrpc_value * const arrayP) { int -xmlrpc_array_size(xmlrpc_env * const env, - const xmlrpc_value * const array) { +xmlrpc_array_size(xmlrpc_env * const envP, + const xmlrpc_value * const arrayP) { int retval; - /* Suppress a compiler warning about uninitialized variables. */ - retval = 0; + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT_VALUE_OK(arrayP); - XMLRPC_ASSERT_ENV_OK(env); - XMLRPC_ASSERT_VALUE_OK(array); - XMLRPC_TYPE_CHECK(env, array, XMLRPC_TYPE_ARRAY); + if (arrayP->_type != XMLRPC_TYPE_ARRAY) { + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_TYPE_ERROR, "Value is not an array"); + retval = -1; + } else { + size_t const size = + XMLRPC_MEMBLOCK_SIZE(xmlrpc_value *, &arrayP->_block); - retval = XMLRPC_TYPED_MEM_BLOCK_SIZE(xmlrpc_value*, &array->_block); + assert((size_t)(int)(size) == size); - cleanup: - if (env->fault_occurred) - return -1; - else - return retval; + retval = (int)size; + } + return retval; } diff --git a/libs/xmlrpc-c/src/xmlrpc_base64.c b/libs/xmlrpc-c/src/xmlrpc_base64.c index 2f54377..30f0c02 100644 --- a/libs/xmlrpc-c/src/xmlrpc_base64.c +++ b/libs/xmlrpc-c/src/xmlrpc_base64.c @@ -36,6 +36,7 @@ #include "xmlrpc_config.h" +#include "bool.h" #include "xmlrpc-c/base.h" #define CRLF "\015\012" @@ -89,178 +90,190 @@ static char table_a2b_base64[] = { #define BASE64_MAXBIN 57 /* Max binary chunk size (76 char line) */ #define BASE64_LINE_SZ 128 /* Buffer size for a single line. */ -static unsigned char table_b2a_base64[] = +static unsigned char const table_b2a_base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + static xmlrpc_mem_block * -xmlrpc_base64_encode_internal (xmlrpc_env *env, - unsigned char *bin_data, - size_t bin_len, - int want_newlines) -{ - size_t chunk_start, chunk_left; - unsigned char *ascii_data; +base64Encode(xmlrpc_env * const envP, + const unsigned char * const binData, + size_t const binLen, + bool const wantNewlines) { + + size_t chunkStart, chunkLeft; + unsigned char * asciiData; int leftbits; - unsigned char this_ch; + unsigned char thisCh; unsigned int leftchar; - xmlrpc_mem_block *output; - unsigned char line_buffer[BASE64_LINE_SZ]; + xmlrpc_mem_block * outputP; + unsigned char lineBuffer[BASE64_LINE_SZ]; + const unsigned char * cursor; /* Create a block to hold our lines when we finish them. */ - output = xmlrpc_mem_block_new(env, 0); - XMLRPC_FAIL_IF_FAULT(env); + outputP = xmlrpc_mem_block_new(envP, 0); + XMLRPC_FAIL_IF_FAULT(envP); /* Deal with empty data blocks gracefully. Yuck. */ - if (bin_len == 0) { - if (want_newlines) - XMLRPC_TYPED_MEM_BLOCK_APPEND(char, env, output, CRLF, 2); + if (binLen == 0) { + if (wantNewlines) + XMLRPC_MEMBLOCK_APPEND(char, envP, outputP, CRLF, 2); goto cleanup; } /* Process our binary data in line-sized chunks. */ - for (chunk_start=0; chunk_start < bin_len; chunk_start += BASE64_MAXBIN) { + for (chunkStart = 0, cursor = &binData[0]; + chunkStart < binLen; + chunkStart += BASE64_MAXBIN) { /* Set up our per-line state. */ - ascii_data = &line_buffer[0]; - chunk_left = bin_len - chunk_start; - if (chunk_left > BASE64_MAXBIN) - chunk_left = BASE64_MAXBIN; + asciiData = &lineBuffer[0]; + chunkLeft = binLen - chunkStart; + if (chunkLeft > BASE64_MAXBIN) + chunkLeft = BASE64_MAXBIN; leftbits = 0; leftchar = 0; - for(; chunk_left > 0; chunk_left--, bin_data++) { + for(; chunkLeft > 0; --chunkLeft, ++cursor) { /* Shift the data into our buffer */ - leftchar = (leftchar << 8) | *bin_data; + leftchar = (leftchar << 8) | *cursor; leftbits += 8; /* See if there are 6-bit groups ready */ while (leftbits >= 6) { - this_ch = (leftchar >> (leftbits-6)) & 0x3f; + thisCh = (leftchar >> (leftbits-6)) & 0x3f; leftbits -= 6; - *ascii_data++ = table_b2a_base64[this_ch]; + *asciiData++ = table_b2a_base64[thisCh]; } } if (leftbits == 2) { - *ascii_data++ = table_b2a_base64[(leftchar&3) << 4]; - *ascii_data++ = BASE64_PAD; - *ascii_data++ = BASE64_PAD; + *asciiData++ = table_b2a_base64[(leftchar&3) << 4]; + *asciiData++ = BASE64_PAD; + *asciiData++ = BASE64_PAD; } else if (leftbits == 4) { - *ascii_data++ = table_b2a_base64[(leftchar&0xf) << 2]; - *ascii_data++ = BASE64_PAD; + *asciiData++ = table_b2a_base64[(leftchar&0xf) << 2]; + *asciiData++ = BASE64_PAD; } /* Append a courtesy CRLF. */ - if (want_newlines) { - *ascii_data++ = CR; - *ascii_data++ = LF; + if (wantNewlines) { + *asciiData++ = CR; + *asciiData++ = LF; } /* Save our line. */ - XMLRPC_TYPED_MEM_BLOCK_APPEND(char, env, output, line_buffer, - ascii_data - &line_buffer[0]); - XMLRPC_FAIL_IF_FAULT(env); + XMLRPC_MEMBLOCK_APPEND(char, envP, outputP, lineBuffer, + asciiData - &lineBuffer[0]); + XMLRPC_FAIL_IF_FAULT(envP); } cleanup: - if (env->fault_occurred) { - if (output) - xmlrpc_mem_block_free(output); + if (envP->fault_occurred) { + if (outputP) + xmlrpc_mem_block_free(outputP); return NULL; } - return output; + return outputP; } + xmlrpc_mem_block * -xmlrpc_base64_encode (xmlrpc_env *env, unsigned char *bin_data, size_t bin_len) -{ - return xmlrpc_base64_encode_internal(env, bin_data, bin_len, 1); +xmlrpc_base64_encode(xmlrpc_env * const envP, + const unsigned char * const binData, + size_t const binLen) { + + return base64Encode(envP, binData, binLen, true); } + xmlrpc_mem_block * -xmlrpc_base64_encode_without_newlines (xmlrpc_env *env, - unsigned char *bin_data, - size_t bin_len) -{ - return xmlrpc_base64_encode_internal(env, bin_data, bin_len, 0); +xmlrpc_base64_encode_without_newlines(xmlrpc_env * const envP, + const unsigned char * const binData, + size_t const binLen) { + + return base64Encode(envP, binData, binLen, false); } + xmlrpc_mem_block * -xmlrpc_base64_decode (xmlrpc_env * const env, - const char * const ascii_data, - size_t const ascii_len) { +xmlrpc_base64_decode(xmlrpc_env * const envP, + const char * const asciiData, + size_t const acsiiLen) { - unsigned char *bin_data; + unsigned char * binData; int leftbits; - unsigned char this_ch; + unsigned char thisCh; unsigned int leftchar; size_t npad; - size_t bin_len, buffer_size; - xmlrpc_mem_block *output; - const char * next_char; - size_t remaining_len; + size_t binLen, bufferSize; + xmlrpc_mem_block * outputP; + const char * nextCharP; + size_t remainingLen; /* Create a block to hold our chunks when we finish them. ** We overestimate the size now, and fix it later. */ - buffer_size = ((ascii_len+3)/4)*3; - output = xmlrpc_mem_block_new(env, buffer_size); - XMLRPC_FAIL_IF_FAULT(env); + bufferSize = ((acsiiLen + 3) / 4) * 3; + outputP = xmlrpc_mem_block_new(envP, bufferSize); + XMLRPC_FAIL_IF_FAULT(envP); /* Set up our decoder state. */ leftbits = 0; leftchar = 0; npad = 0; - bin_data = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(unsigned char, output); - bin_len = 0; + binData = XMLRPC_MEMBLOCK_CONTENTS(unsigned char, outputP); + binLen = 0; - for (remaining_len = ascii_len, next_char = ascii_data; - remaining_len > 0; - --remaining_len, ++next_char) { + for (remainingLen = acsiiLen, nextCharP = asciiData; + remainingLen > 0; + --remainingLen, ++nextCharP) { /* Skip some punctuation. */ - this_ch = (*next_char & 0x7f); - if ( this_ch == '\r' || this_ch == '\n' || this_ch == ' ' ) + thisCh = (*nextCharP & 0x7f); + if (thisCh == '\r' || thisCh == '\n' || thisCh == ' ') continue; - if ( this_ch == BASE64_PAD ) - npad++; - this_ch = table_a2b_base64[(*next_char) & 0x7f]; + if (thisCh == BASE64_PAD) + ++npad; + thisCh = table_a2b_base64[(*nextCharP) & 0x7f]; /* XXX - We just throw away invalid characters. Is this right? */ - if ( this_ch == (unsigned char) -1 ) continue; + if (thisCh == (unsigned char) -1) + continue; - /* Shift it in on the low end, and see if there's - ** a byte ready for output. */ - leftchar = (leftchar << 6) | (this_ch); + /* Shift it in on the low end, and see if there's a byte ready for + output. + */ + leftchar = (leftchar << 6) | (thisCh); leftbits += 6; - if ( leftbits >= 8 ) { + if (leftbits >= 8) { leftbits -= 8; - XMLRPC_ASSERT(bin_len < buffer_size); - *bin_data++ = (leftchar >> leftbits) & 0xFF; + XMLRPC_ASSERT(binLen < bufferSize); + *binData++ = (leftchar >> leftbits) & 0xFF; leftchar &= ((1 << leftbits) - 1); - bin_len++; + ++binLen; } } /* Check that no bits are left. */ - if ( leftbits ) - XMLRPC_FAIL(env, XMLRPC_PARSE_ERROR, "Incorrect Base64 padding"); + if (leftbits) + XMLRPC_FAIL(envP, XMLRPC_PARSE_ERROR, "Incorrect Base64 padding"); /* Check to make sure we have a sane amount of padding. */ - if (npad > bin_len || npad > 2) - XMLRPC_FAIL(env, XMLRPC_PARSE_ERROR, "Malformed Base64 data"); + if (npad > binLen || npad > 2) + XMLRPC_FAIL(envP, XMLRPC_PARSE_ERROR, "Malformed Base64 data"); /* Remove any padding and set the correct size. */ - bin_len -= npad; - XMLRPC_TYPED_MEM_BLOCK_RESIZE(char, env, output, bin_len); - XMLRPC_ASSERT(!env->fault_occurred); - - cleanup: - if (env->fault_occurred) { - if (output) - xmlrpc_mem_block_free(output); + binLen -= npad; + XMLRPC_MEMBLOCK_RESIZE(char, envP, outputP, binLen); + XMLRPC_ASSERT(!envP->fault_occurred); + + cleanup: + if (envP->fault_occurred) { + if (outputP) + xmlrpc_mem_block_free(outputP); return NULL; } - return output; + return outputP; } diff --git a/libs/xmlrpc-c/src/xmlrpc_build.c b/libs/xmlrpc-c/src/xmlrpc_build.c index 19e2a55..b44f471 100644 --- a/libs/xmlrpc-c/src/xmlrpc_build.c +++ b/libs/xmlrpc-c/src/xmlrpc_build.c @@ -17,16 +17,6 @@ #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, @@ -35,11 +25,11 @@ getString(xmlrpc_env * const envP, xmlrpc_value ** const valPP) { const char * str; - unsigned int len; + size_t len; str = (const char*) va_arg(argsP->v, char*); - if (**formatP == '#') { - (*formatP)++; + if (*(*formatP) == '#') { + ++(*formatP); len = (size_t) va_arg(argsP->v, size_t); } else len = strlen(str); @@ -399,10 +389,12 @@ xmlrpc_build_value(xmlrpc_env * const envP, 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); + xmlrpc_faultf(envP, "Junk after the format specifier: '%s'. " + "The format string must describe exactly " + "one XML-RPC value " + "(but it might be a compound value " + "such as an array)", + suffix); if (envP->fault_occurred) xmlrpc_DECREF(retval); diff --git a/libs/xmlrpc-c/src/xmlrpc_builddecomp.c b/libs/xmlrpc-c/src/xmlrpc_builddecomp.c deleted file mode 100644 index e770652..0000000 --- a/libs/xmlrpc-c/src/xmlrpc_builddecomp.c +++ /dev/null @@ -1,973 +0,0 @@ -/* Copyright information is at end of file */ - -#include "xmlrpc_config.h" - -#include -#include -#include -#include - -#include "bool.h" -#include "xmlrpc-c/base.h" -#include "xmlrpc-c/base_int.h" - -/* Borrowed from Python 1.5.2. -** MPW pushes 'extended' for float and double types with varargs */ -#ifdef MPW -typedef extended va_double; -#else -typedef double va_double; -#endif - -/* Borrowed from Python 1.5.2. -** Python copies its va_list objects before using them in certain -** tricky fashions. We don't why Python does this, but since we're -** abusing our va_list objects in a similar fashion, we'll copy them -** too. */ -#if VA_LIST_IS_ARRAY -#define VA_LIST_COPY(dest,src) memcpy((dest), (src), sizeof(va_list)) -#else -#if __sun -#define VA_LIST_COPY(dest,src) va_copy((dest),(src)) -#else -#define VA_LIST_COPY(dest,src) ((dest) = (src)) -#endif -#endif - -/*========================================================================= -** 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_list * const args, - xmlrpc_value ** const valPP) { - - const char * str; - unsigned int len; - - str = (const char*) va_arg(*args, char*); - if (**formatP == '#') { - (*formatP)++; - len = (size_t) va_arg(*args, size_t); - } else - len = strlen(str); - - *valPP = xmlrpc_string_new_lp(envP, len, str); -} - - - -#ifdef HAVE_UNICODE_WCHAR -static void -mkWideString(xmlrpc_env * const envP, - wchar_t * const wcs, - size_t const wcs_len, - xmlrpc_value ** const valPP) { - - xmlrpc_value * valP; - char *contents; - wchar_t *wcs_contents; - int block_is_inited; - xmlrpc_mem_block *utf8_block; - char *utf8_contents; - size_t utf8_len; - - /* Error-handling preconditions. */ - valP = NULL; - utf8_block = NULL; - block_is_inited = 0; - - /* Initialize our XML-RPC value. */ - valP = (xmlrpc_value*) malloc(sizeof(xmlrpc_value)); - XMLRPC_FAIL_IF_NULL(valP, envP, XMLRPC_INTERNAL_ERROR, - "Could not allocate memory for wide string"); - valP->_refcount = 1; - valP->_type = XMLRPC_TYPE_STRING; - - /* More error-handling preconditions. */ - valP->_wcs_block = NULL; - - /* Build our wchar_t block first. */ - valP->_wcs_block = - XMLRPC_TYPED_MEM_BLOCK_NEW(wchar_t, envP, wcs_len + 1); - XMLRPC_FAIL_IF_FAULT(envP); - wcs_contents = - XMLRPC_TYPED_MEM_BLOCK_CONTENTS(wchar_t, valP->_wcs_block); - memcpy(wcs_contents, wcs, wcs_len * sizeof(wchar_t)); - wcs_contents[wcs_len] = '\0'; - - /* Convert the wcs block to UTF-8. */ - utf8_block = xmlrpc_wcs_to_utf8(envP, wcs_contents, wcs_len + 1); - XMLRPC_FAIL_IF_FAULT(envP); - utf8_contents = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, utf8_block); - utf8_len = XMLRPC_TYPED_MEM_BLOCK_SIZE(char, utf8_block); - - /* XXX - We need an extra memcopy to initialize _block. */ - XMLRPC_TYPED_MEM_BLOCK_INIT(char, envP, &valP->_block, utf8_len); - XMLRPC_FAIL_IF_FAULT(envP); - block_is_inited = 1; - contents = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, &valP->_block); - memcpy(contents, utf8_contents, utf8_len); - - cleanup: - if (utf8_block) - xmlrpc_mem_block_free(utf8_block); - if (envP->fault_occurred) { - if (valP) { - if (valP->_wcs_block) - xmlrpc_mem_block_free(valP->_wcs_block); - if (block_is_inited) - xmlrpc_mem_block_clean(&valP->_block); - free(valP); - } - } - *valPP = valP; -} -#endif /* HAVE_UNICODE_WCHAR */ - - - -static void -getWideString(xmlrpc_env * const envP, - const char ** const formatP, - va_list * const args, - xmlrpc_value ** const valPP) { -#ifdef HAVE_UNICODE_WCHAR - - wchar_t *wcs; - size_t len; - - wcs = (wchar_t*) va_arg(*args, wchar_t*); - if (**formatP == '#') { - (*formatP)++; - len = (size_t) va_arg(*args, size_t); - } else - len = wcslen(wcs); - - mkWideString(envP, wcs, len, valPP); - -#endif /* HAVE_UNICODE_WCHAR */ -} - - - -static void -getBase64(xmlrpc_env * const envP, - va_list * const args, - xmlrpc_value ** const valPP) { - - unsigned char * value; - size_t length; - - value = (unsigned char*) va_arg(*args, unsigned char*); - length = (size_t) va_arg(*args, size_t); - - *valPP = xmlrpc_base64_new(envP, length, value); -} - - - -static void -getValue(xmlrpc_env * const envP, - const char** const format, - va_list * args, - xmlrpc_value ** const valPP); - - - -static void -getArray(xmlrpc_env * const envP, - const char ** const formatP, - char const delimiter, - va_list * const args, - 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, args, &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_list * const args, - xmlrpc_value ** const keyPP, - xmlrpc_value ** const valuePP) { - - - /* Get the key */ - getValue(envP, formatP, args, 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, args, valuePP); - } - if (envP->fault_occurred) - xmlrpc_DECREF(*keyPP); - } -} - - - -static void -getStruct(xmlrpc_env * const envP, - const char ** const formatP, - char const delimiter, - va_list * const args, - 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, args, &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_list * const args, - 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 'args'. 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 'args' and return as *valP an integer whose - value is the argument we read. We advance *formatP to point to the - last 's' and advance 'args' 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(*args, xmlrpc_int32)); - break; - - case 'b': - *valPP = - xmlrpc_bool_new(envP, (xmlrpc_bool) va_arg(*args, xmlrpc_bool)); - break; - - case 'd': - *valPP = - xmlrpc_double_new(envP, (double) va_arg(*args, va_double)); - break; - - case 's': - getString(envP, formatP, args, valPP); - break; - - case 'w': - getWideString(envP, formatP, args, valPP); - break; - - /* The code 't' is reserved for a better, time_t based - implementation of dateTime conversion. - */ - case '8': - *valPP = - xmlrpc_datetime_new_str(envP, (char*) va_arg(*args, char*)); - break; - - case '6': - getBase64(envP, args, valPP); - break; - - case 'n': - *valPP = - xmlrpc_nil_new(envP); - break; - - case 'p': - /* We might someday want to use the code 'p!' to read in a - cleanup function for this pointer. - */ - *valPP = - xmlrpc_cptr_new(envP, (void*) va_arg(*args, void*)); - break; - - case 'A': - mkArrayFromVal(envP, (xmlrpc_value*) va_arg(*args, xmlrpc_value*), - valPP); - break; - - case 'S': - mkStructFromVal(envP, (xmlrpc_value*) va_arg(*args, xmlrpc_value*), - valPP); - break; - - case 'V': - *valPP = (xmlrpc_value*) va_arg(*args, xmlrpc_value*); - xmlrpc_INCREF(*valPP); - break; - - case '(': - getArray(envP, formatP, ')', args, valPP); - if (!envP->fault_occurred) { - XMLRPC_ASSERT(**formatP == ')'); - (*formatP)++; /* Skip over closing parenthesis */ - } - break; - - case '{': - getStruct(envP, formatP, '}', args, 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 args, - xmlrpc_value ** const valPP, - const char ** const tailP) { - - const char * formatCursor; - va_list args_copy; - - XMLRPC_ASSERT_ENV_OK(envP); - XMLRPC_ASSERT(format != NULL); - - if (strlen(format) == 0) - xmlrpc_env_set_fault_formatted( - envP, XMLRPC_INTERNAL_ERROR, "Format string is empty."); - else { - formatCursor = &format[0]; - VA_LIST_COPY(args_copy, args); - getValue(envP, &formatCursor, &args_copy, 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; -} - - - - - -/*========================================================================= -** Parsing XML-RPC values. -**========================================================================= -** Parse an XML-RPC value based on a format string. This code is heavily -** inspired by Py_BuildValue from Python 1.5.2. -*/ - -/* Prototype for recursive invocation: */ - -static void -decomposeValue(xmlrpc_env * const env, - xmlrpc_value * const val, - const char ** const format, - va_list * args, - xmlrpc_bool const oldstyleMemMgmt); - - - -static void -parsearray(xmlrpc_env * const env, - const xmlrpc_value * const array, - const char ** const format, - char const delimiter, - va_list * args, - xmlrpc_bool const oldstyleMemMgmt) { - - int size, i; - xmlrpc_value *item; - - /* Fetch the array size. */ - size = xmlrpc_array_size(env, array); - XMLRPC_FAIL_IF_FAULT(env); - - /* Loop over the items in the array. */ - for (i = 0; i < size; i++) { - /* Bail out if the caller didn't care about the rest of the items. */ - if (**format == '*') - break; - - item = xmlrpc_array_get_item(env, array, i); - XMLRPC_FAIL_IF_FAULT(env); - - XMLRPC_ASSERT(**format != '\0'); - if (**format == delimiter) - XMLRPC_FAIL(env, XMLRPC_INDEX_ERROR, "Too many items in array"); - decomposeValue(env, item, format, args, oldstyleMemMgmt); - XMLRPC_FAIL_IF_FAULT(env); - } - if (**format == '*') - (*format)++; - if (**format != delimiter) - XMLRPC_FAIL(env, XMLRPC_INDEX_ERROR, "Not enough items in array"); - - cleanup: - return; -} - - - -static void -parsestruct(xmlrpc_env * const env, - xmlrpc_value * const strct, - const char ** const format, - char const delimiter, - va_list * args, - xmlrpc_bool const oldstyleMemMgmt) { - - xmlrpc_value *key, *value; - char *keystr; - size_t keylen; - - /* Set up error handling preconditions. */ - key = NULL; - - /* Build the members of our struct. */ - while (**format != '*' && **format != delimiter && **format != '\0') { - - /* Get our key, and skip over the ':' character. Notice the - ** sudden call to getValue--we're going in the opposite direction. */ - getValue(env, format, args, &key); - XMLRPC_FAIL_IF_FAULT(env); - XMLRPC_ASSERT(**format == ':'); - (*format)++; - - /* Look up the value for our key. */ - xmlrpc_parse_value(env, key, "s#", &keystr, &keylen); - XMLRPC_FAIL_IF_FAULT(env); - value = xmlrpc_struct_get_value_n(env, strct, keystr, keylen); - XMLRPC_FAIL_IF_FAULT(env); - - /* Get our value, and skip over the ',' character (if present). */ - decomposeValue(env, value, format, args, oldstyleMemMgmt); - XMLRPC_FAIL_IF_FAULT(env); - XMLRPC_ASSERT(**format == ',' || **format == delimiter); - if (**format == ',') - (*format)++; - - /* Release our reference, and restore our invariant. */ - xmlrpc_DECREF(key); - key = NULL; - } - if (**format == '*') { - (*format)++; - if (**format != delimiter && **format != '\0') - XMLRPC_FAIL(env, XMLRPC_INTERNAL_ERROR, - "* can appear only at the end " - "of a structure format specifier"); - } else { - /* Here we're supposed to fail if he didn't extract all the - members. But we don't know how to determine whether he - specified all the members, so we always fail. - */ - XMLRPC_FAIL(env, XMLRPC_INTERNAL_ERROR, "You must specify '*' as the " - "last member of a structure in a format specifier " - "used for parsing an xmlrpc_value"); - } - XMLRPC_ASSERT(**format == delimiter || **format == '\0'); - -cleanup: - if (key) - xmlrpc_DECREF(key); -} - - -static void -readString(xmlrpc_env * const envP, - const xmlrpc_value * const valueP, - const char ** const stringValueP, - xmlrpc_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, - xmlrpc_bool const oldstyleMemMgmt) { - - if (oldstyleMemMgmt) { - xmlrpc_read_string_lp_old(envP, valueP, lengthP, stringValueP); - } else - xmlrpc_read_string_lp(envP, valueP, lengthP, stringValueP); -} - - - -#ifdef HAVE_UNICODE_WCHAR -static void -readStringW(xmlrpc_env * const envP, - xmlrpc_value * const valueP, - const wchar_t ** const stringValueP, - xmlrpc_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, - xmlrpc_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 -readDatetimeStr(xmlrpc_env * const envP, - const xmlrpc_value * const valueP, - const char ** const stringValueP, - xmlrpc_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, - xmlrpc_bool const oldstyleMemMgmt) { - - if (oldstyleMemMgmt) - xmlrpc_read_base64_old(envP, valueP, lengthP, byteStringValueP); - else - xmlrpc_read_base64(envP, valueP, lengthP, byteStringValueP); -} - - - -static void -decomposeValue(xmlrpc_env * const envP, - xmlrpc_value * const valueP, - const char ** const format, - va_list * args, - xmlrpc_bool const oldstyleMemMgmt) { - - char formatSpecChar; - - formatSpecChar = *(*format)++; - - switch (formatSpecChar) { - case 'i': { - xmlrpc_int32 * const int32ptr = - (xmlrpc_int32*) va_arg(*args, xmlrpc_int32*); - xmlrpc_read_int(envP, valueP, int32ptr); - } - break; - - case 'b': { - xmlrpc_bool * const boolptr = - (xmlrpc_bool*) va_arg(*args, xmlrpc_bool*); - xmlrpc_read_bool(envP, valueP, boolptr); - } - break; - - case 'd': { - double * const doubleptr = (double*) va_arg(*args, double*); - xmlrpc_read_double(envP, valueP, doubleptr); - } - break; - - case '8': { - /* The code 't' is reserved for a better, time_t based - implementation of dateTime conversion. - */ - const char ** const strptr = (const char**) va_arg(*args, char**); - readDatetimeStr(envP, valueP, strptr, oldstyleMemMgmt); - } - break; - - case 's': { - const char ** const strptr = (const char**) va_arg(*args, char**); - if (**format == '#') { - size_t * const sizeptr = (size_t*) va_arg(*args, size_t**); - (*format)++; - - readStringLp(envP, valueP, sizeptr, strptr, oldstyleMemMgmt); - } else - readString(envP, valueP, strptr, oldstyleMemMgmt); - } - break; - - case 'w': { -#ifdef HAVE_UNICODE_WCHAR - const wchar_t ** const wcsptr = - (const wchar_t**) va_arg(*args, wchar_t**); - if (**format == '#') { - size_t * const sizeptr = (size_t*) va_arg(*args, size_t**); - (*format)++; - readStringWLp(envP, valueP, sizeptr, wcsptr, oldstyleMemMgmt); - } else - readStringW(envP, valueP, wcsptr, oldstyleMemMgmt); -#else - xmlrpc_env_set_fault_formatted( - envP, XMLRPC_INTERNAL_ERROR, - "This XML-RPC For C/C++ library was built without Unicode " - "wide character capability. 'w' isn't available."); -#endif /* HAVE_UNICODE_WCHAR */ - } - break; - - case '6': { - const unsigned char ** const binptr = - (const unsigned char**) va_arg(*args, unsigned char**); - size_t * const sizeptr = (size_t*) va_arg(*args, size_t**); - readBase64(envP, valueP, sizeptr, binptr, oldstyleMemMgmt); - } - break; - - case 'n': { - xmlrpc_read_nil(envP, valueP); - } - break; - - case 'p': { - void ** const voidptrptr = (void**) va_arg(*args, void**); - xmlrpc_read_cptr(envP, valueP, voidptrptr); - } - break; - - case 'V': { - xmlrpc_value ** const valptr = - (xmlrpc_value**) va_arg(*args, xmlrpc_value**); - *valptr = 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, "Non-array type supplied for " - "'A' specifier"); - else { - xmlrpc_value ** const valptr = - (xmlrpc_value**) va_arg(*args, xmlrpc_value**); - *valptr = 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, "Non-struct type supplied for " - "'S' specifier"); - else { - xmlrpc_value ** const valptr = - (xmlrpc_value**) va_arg(*args, xmlrpc_value**); - *valptr = 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, "Non-array type supplied for " - "'()' specifier"); - else { - parsearray(envP, valueP, format, ')', args, oldstyleMemMgmt); - (*format)++; - } - break; - - case '{': - if (xmlrpc_value_type(valueP) != XMLRPC_TYPE_STRUCT) - xmlrpc_env_set_fault_formatted( - envP, XMLRPC_TYPE_ERROR, "Non-struct type supplied for " - "'{}' specifier"); - else { - parsestruct(envP, valueP, format, '}', args, oldstyleMemMgmt); - (*format)++; - } - break; - - default: - xmlrpc_env_set_fault_formatted( - envP, XMLRPC_INTERNAL_ERROR, "Invalid format character '%c'", - formatSpecChar); - } -} - - - -void -xmlrpc_decompose_value_va(xmlrpc_env * const envP, - xmlrpc_value * const value, - const char * const format, - va_list args) { - - const char *format_copy; - va_list args_copy; - - XMLRPC_ASSERT_ENV_OK(envP); - XMLRPC_ASSERT_VALUE_OK(value); - XMLRPC_ASSERT(format != NULL); - - format_copy = format; - VA_LIST_COPY(args_copy, args); - decomposeValue(envP, value, &format_copy, &args_copy, FALSE); - if (!envP->fault_occurred) { - XMLRPC_ASSERT(*format_copy == '\0'); - } -} - - - -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 value, - const char * const format, - va_list args) { - - const char *format_copy; - va_list args_copy; - - XMLRPC_ASSERT_ENV_OK(envP); - XMLRPC_ASSERT_VALUE_OK(value); - XMLRPC_ASSERT(format != NULL); - - format_copy = format; - VA_LIST_COPY(args_copy, args); - decomposeValue(envP, value, &format_copy, &args_copy, TRUE); - if (!envP->fault_occurred) { - XMLRPC_ASSERT(*format_copy == '\0'); - } -} - - - -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); -} - - - -/* 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. */ diff --git a/libs/xmlrpc-c/src/xmlrpc_client.c b/libs/xmlrpc-c/src/xmlrpc_client.c index 88f3dcf..e87c6f3 100644 --- a/libs/xmlrpc-c/src/xmlrpc_client.c +++ b/libs/xmlrpc-c/src/xmlrpc_client.c @@ -1,5 +1,7 @@ /* Copyright information is at end of file */ +#define _XOPEN_SOURCE 600 /* Make sure strdup() is in */ + #include "xmlrpc_config.h" #undef PACKAGE @@ -40,6 +42,7 @@ struct xmlrpc_client { struct xmlrpc_client_transport * transportP; struct xmlrpc_client_transport_ops transportOps; xmlrpc_dialect dialect; + xmlrpc_progress_fn * progressFn; }; @@ -54,17 +57,21 @@ struct xmlrpc_call_info { storage, and we need to keep this info in our own. */ + void * userHandle; + /* This is a handle for this call that is meaningful to our + user. + */ + xmlrpc_progress_fn * progressFn; struct { - /* This are arguments to pass to the completion function. It + /* These 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; + xmlrpc_response_handler * completionFn; /* The serialized XML data passed to this call. We keep this around @@ -187,6 +194,17 @@ 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; +void +xmlrpc_client_version(unsigned int * const majorP, + unsigned int * const minorP, + unsigned int * const pointP) { + + *majorP = XMLRPC_VERSION_MAJOR; + *minorP = XMLRPC_VERSION_MINOR; + *pointP = XMLRPC_VERSION_POINT; +} + + /*========================================================================= Client Create/Destroy @@ -201,15 +219,15 @@ getTransportOps( if (false) { } #if MUST_BUILD_WININET_CLIENT - else if (strcmp(transportName, "wininet") == 0) + else if (xmlrpc_streq(transportName, "wininet")) *opsPP = &xmlrpc_wininet_transport_ops; #endif #if MUST_BUILD_CURL_CLIENT - else if (strcmp(transportName, "curl") == 0) + else if (xmlrpc_streq(transportName, "curl")) *opsPP = &xmlrpc_curl_transport_ops; #endif #if MUST_BUILD_LIBWWW_CLIENT - else if (strcmp(transportName, "libwww") == 0) + else if (xmlrpc_streq(transportName, "libwww")) *opsPP = &xmlrpc_libwww_transport_ops; #endif else @@ -334,6 +352,7 @@ clientCreate( const struct xmlrpc_client_transport_ops * const transportOpsP, struct xmlrpc_client_transport * const transportP, xmlrpc_dialect const dialect, + xmlrpc_progress_fn * const progressFn, xmlrpc_client ** const clientPP) { XMLRPC_ASSERT_PTR_OK(transportOpsP); @@ -360,6 +379,7 @@ clientCreate( clientP->transportOps = *transportOpsP; clientP->transportP = transportP; clientP->dialect = dialect; + clientP->progressFn = progressFn; *clientPP = clientP; } @@ -370,15 +390,16 @@ clientCreate( 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) { + 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_progress_fn * const progressFn, + xmlrpc_client ** const clientPP) { const struct xmlrpc_client_transport_ops * transportOpsP; @@ -395,7 +416,7 @@ createTransportAndClient( bool const myTransportTrue = true; clientCreate(envP, myTransportTrue, transportOpsP, transportP, - dialect, clientPP); + dialect, progressFn, clientPP); if (envP->fault_occurred) transportOpsP->destroy(transportP); @@ -429,11 +450,15 @@ xmlrpc_client_create(xmlrpc_env * const envP, const struct xmlrpc_client_transport_ops * transportOpsP; xmlrpc_client_transport * transportP; xmlrpc_dialect dialect; - + xmlrpc_progress_fn * progressFn; + getTransportInfo(envP, clientparmsP, parmSize, &transportName, &transportparms, &transportOpsP, &transportP); getDialectFromClientParms(clientparmsP, parmSize, &dialect); + + progressFn = parmSize >= XMLRPC_CPSIZE(progressFn) ? + clientparmsP->progressFn : NULL; if (!envP->fault_occurred) { if (transportName) @@ -441,11 +466,13 @@ xmlrpc_client_create(xmlrpc_env * const envP, transportparms.parmsP, transportparms.size, flags, appname, appversion, dialect, + progressFn, clientPP); else { bool myTransportFalse = false; clientCreate(envP, myTransportFalse, - transportOpsP, transportP, dialect, clientPP); + transportOpsP, transportP, dialect, progressFn, + clientPP); } } } @@ -607,58 +634,139 @@ xmlrpc_client_call2(xmlrpc_env * const envP, 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_env argenv; - const char * suffix; +computeParamArray(xmlrpc_env * const envP, + const char * const format, + va_list args, + xmlrpc_value ** const paramArrayPP) { +/*---------------------------------------------------------------------------- + 'format' and 'args' specify the parameter list of an RPC, in the form + of an XML-RPC array value, with one element per RPC parameter. - 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); + 'format' is an XML-RPC value format string, e.g. "(ii{s:i,s:i})". + 'args' is the list of substitution values for that string + (6 values in this example, 4 integers and 2 strings). + + We return the XML-RPC value 'format' and 'args' represent, but throw an + error if they don't validly specify a single array. - /* Build our argument value. */ - xmlrpc_env_init(&argenv); - xmlrpc_build_value_va(&argenv, format, args, &argP, &suffix); - if (argenv.fault_occurred) + Note that it is a common user error to specify the format string as a + single or string of argument types, instead of as an array of argument + types. E.g. "i" or "ii" instead of "(i)" and "(ii)". So we try + especially hard to give an informative message for that case. +-----------------------------------------------------------------------------*/ + xmlrpc_env env; + xmlrpc_value * paramArrayP; + const char * suffix; + /* Stuff left over in format string after parameter array + specification. + */ + + xmlrpc_env_init(&env); + xmlrpc_build_value_va(&env, format, args, ¶mArrayP, &suffix); + if (env.fault_occurred) xmlrpc_env_set_fault_formatted( - envP, argenv.fault_code, "Invalid RPC arguments. " - "The format argument must indicate a single array, and the " + envP, env.fault_code, "Invalid RPC arguments. " + "The format argument must indicate a single array (each element " + "of which is one argument to the XML-RPC call), and the " "following arguments must correspond to that format argument. " "The failure is: %s", - argenv.fault_string); + env.fault_string); else { - XMLRPC_ASSERT_VALUE_OK(argP); + XMLRPC_ASSERT_VALUE_OK(paramArrayP); if (*suffix != '\0') - xmlrpc_faultf(envP, "Junk after the argument specifier: '%s'. " - "There must be exactly one argument.", + xmlrpc_faultf(envP, + "Junk after the parameter array specifier: '%s'. " + "The format string must specify exactly one value: " + "an array of RPC parameters", suffix); else { - xmlrpc_server_info * serverInfoP; + if (xmlrpc_value_type(paramArrayP) != XMLRPC_TYPE_ARRAY) + xmlrpc_faultf( + envP, + "You must specify the parameter list as an " + "XML-RPC array value, " + "each element of which is a parameter of the RPC. " + "But your format string specifies an XML-RPC %s, not " + "an array", + xmlrpc_type_name(xmlrpc_value_type(paramArrayP))); + } + if (env.fault_occurred) + xmlrpc_DECREF(paramArrayP); + else + *paramArrayPP = paramArrayP; + } + xmlrpc_env_clean(&env); +} + + + +void +xmlrpc_client_call_server2_va(xmlrpc_env * const envP, + struct xmlrpc_client * const clientP, + const xmlrpc_server_info * const serverInfoP, + const char * const methodName, + const char * const format, + va_list args, + xmlrpc_value ** const resultPP) { + + /* This function exists only for use by the global client function + xmlrpc_client_call_server(). + */ + + xmlrpc_value * paramArrayP; + /* The XML-RPC parameter list array */ + + computeParamArray(envP, format, args, ¶mArrayP); + + if (!envP->fault_occurred) { + xmlrpc_client_call2(envP, clientP, + serverInfoP, methodName, paramArrayP, + resultPP); + + xmlrpc_DECREF(paramArrayP); + } +} + + + +void +xmlrpc_client_call2f_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) { - serverInfoP = xmlrpc_server_info_new(envP, serverUrl); + xmlrpc_value * paramArrayP; + /* The XML-RPC parameter list array */ + + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT_PTR_OK(clientP); + XMLRPC_ASSERT_PTR_OK(serverUrl); + XMLRPC_ASSERT_PTR_OK(methodName); + XMLRPC_ASSERT_PTR_OK(format); + XMLRPC_ASSERT_PTR_OK(resultPP); + + computeParamArray(envP, format, args, ¶mArrayP); + + if (!envP->fault_occurred) { + 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); - } + if (!envP->fault_occurred) { + /* Perform the actual XML-RPC call. */ + xmlrpc_client_call2(envP, clientP, + serverInfoP, methodName, paramArrayP, + resultPP); + if (!envP->fault_occurred) + XMLRPC_ASSERT_VALUE_OK(*resultPP); + xmlrpc_server_info_free(serverInfoP); } - xmlrpc_DECREF(argP); + xmlrpc_DECREF(paramArrayP); } - xmlrpc_env_clean(&argenv); } @@ -674,9 +782,11 @@ xmlrpc_client_call2f(xmlrpc_env * const envP, va_list args; + XMLRPC_ASSERT_PTR_OK(format); + va_start(args, format); - clientCall2f_va(envP, clientP, serverUrl, - methodName, format, resultPP, args); + xmlrpc_client_call2f_va(envP, clientP, serverUrl, + methodName, format, resultPP, args); va_end(args); } @@ -693,10 +803,15 @@ callInfoSetCompletion(xmlrpc_env * const envP, const char * const methodName, xmlrpc_value * const paramArrayP, xmlrpc_response_handler completionFn, - void * const userData) { - + xmlrpc_progress_fn progressFn, + void * const userHandle) { +/*---------------------------------------------------------------------------- + Set the members of callinfo structure *callInfoP that are used for + the completion and progress calls from the transport to us. +-----------------------------------------------------------------------------*/ callInfoP->completionFn = completionFn; - callInfoP->completionArgs.userData = userData; + callInfoP->progressFn = progressFn; + callInfoP->userHandle = userHandle; callInfoP->completionArgs.serverUrl = strdup(serverUrl); if (callInfoP->completionArgs.serverUrl == NULL) xmlrpc_faultf(envP, "Couldn't get memory to store server URL"); @@ -722,7 +837,8 @@ callInfoCreate(xmlrpc_env * const envP, xmlrpc_dialect const dialect, const char * const serverUrl, xmlrpc_response_handler completionFn, - void * const userData, + xmlrpc_progress_fn progressFn, + void * const userHandle, struct xmlrpc_call_info ** const callInfoPP) { /*---------------------------------------------------------------------------- Create a call_info object. A call_info object represents an XML-RPC @@ -744,21 +860,17 @@ callInfoCreate(xmlrpc_env * const envP, makeCallXml(envP, methodName, paramArrayP, dialect, &callXmlP); if (!envP->fault_occurred) { - xmlrpc_traceXml("XML-RPC CALL", - XMLRPC_MEMBLOCK_CONTENTS(char, callXmlP), - XMLRPC_MEMBLOCK_SIZE(char, callXmlP)); - callInfoP->serialized_xml = callXmlP; - *callInfoPP = callInfoP; - callInfoSetCompletion(envP, callInfoP, serverUrl, methodName, - paramArrayP, completionFn, userData); + paramArrayP, + completionFn, progressFn, userHandle); if (envP->fault_occurred) free(callInfoP); } } + *callInfoPP = callInfoP; } @@ -804,6 +916,15 @@ xmlrpc_client_event_loop_finish_timeout(xmlrpc_client * const clientP, +/* Microsoft Visual C in debug mode produces code that complains about + passing an undefined value of 'resultP' to xmlrpc_parse_response2(). + It's a bogus complaint, because this function knows in those cases + that the value of 'resultP' is meaningless. So we disable the check. +*/ +#pragma runtime_checks("u", off) + + + static void asynchComplete(struct xmlrpc_call_info * const callInfoP, xmlrpc_mem_block * const responseXmlP, @@ -825,8 +946,6 @@ asynchComplete(struct xmlrpc_call_info * const callInfoP, xmlrpc_env_init(&env); - resultP = NULL; /* Just to quiet compiler warning */ - if (transportEnv.fault_occurred) xmlrpc_env_set_fault_formatted( &env, transportEnv.fault_code, @@ -855,7 +974,7 @@ asynchComplete(struct xmlrpc_call_info * const callInfoP, (*callInfoP->completionFn)(callInfoP->completionArgs.serverUrl, callInfoP->completionArgs.methodName, callInfoP->completionArgs.paramArrayP, - callInfoP->completionArgs.userData, + callInfoP->userHandle, &env, resultP); if (!env.fault_occurred) @@ -868,14 +987,32 @@ asynchComplete(struct xmlrpc_call_info * const callInfoP, +#pragma runtime_checks("u", restore) + + + +static void +progress(struct xmlrpc_call_info * const callInfoP, + struct xmlrpc_progress_data const progressData) { + + /* We wouldn't have asked the transport to call our progress + function if we didn't have a user progress function to call: + */ + assert(callInfoP->progressFn); + + callInfoP->progressFn(callInfoP->userHandle, progressData); +} + + + 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) { +xmlrpc_client_start_rpc(xmlrpc_env * const envP, + struct xmlrpc_client * const clientP, + const xmlrpc_server_info * const serverInfoP, + const char * const methodName, + xmlrpc_value * const paramArrayP, + xmlrpc_response_handler completionFn, + void * const userHandle) { struct xmlrpc_call_info * callInfoP; @@ -883,18 +1020,25 @@ xmlrpc_client_start_rpc(xmlrpc_env * const envP, XMLRPC_ASSERT_PTR_OK(clientP); XMLRPC_ASSERT_PTR_OK(serverInfoP); XMLRPC_ASSERT_PTR_OK(methodName); - XMLRPC_ASSERT_VALUE_OK(argP); + XMLRPC_ASSERT_VALUE_OK(paramArrayP); - callInfoCreate(envP, methodName, argP, clientP->dialect, - serverInfoP->serverUrl, completionFn, userData, + callInfoCreate(envP, methodName, paramArrayP, clientP->dialect, + serverInfoP->serverUrl, + completionFn, clientP->progressFn, userHandle, &callInfoP); - if (!envP->fault_occurred) + if (!envP->fault_occurred) { + xmlrpc_traceXml( + "XML-RPC CALL", + XMLRPC_MEMBLOCK_CONTENTS(char, callInfoP->serialized_xml), + XMLRPC_MEMBLOCK_SIZE(char, callInfoP->serialized_xml)); + clientP->transportOps.send_request( envP, clientP->transportP, serverInfoP, callInfoP->serialized_xml, - &asynchComplete, callInfoP); - + &asynchComplete, clientP->progressFn ? &progress : NULL, + callInfoP); + } if (envP->fault_occurred) callInfoDestroy(callInfoP); else { @@ -904,47 +1048,84 @@ xmlrpc_client_start_rpc(xmlrpc_env * const envP, +void +xmlrpc_client_start_rpcf_server_va( + xmlrpc_env * const envP, + xmlrpc_client * const clientP, + const xmlrpc_server_info * const serverInfoP, + const char * const methodName, + xmlrpc_response_handler responseHandler, + void * const userHandle, + const char * const format, + va_list args) { + + xmlrpc_value * paramArrayP; + /* The XML-RPC parameter list array */ + + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT_PTR_OK(clientP); + XMLRPC_ASSERT_PTR_OK(serverInfoP); + XMLRPC_ASSERT_PTR_OK(methodName); + XMLRPC_ASSERT_PTR_OK(format); + + computeParamArray(envP, format, args, ¶mArrayP); + + if (!envP->fault_occurred) { + xmlrpc_client_start_rpc(envP, clientP, + serverInfoP, methodName, paramArrayP, + responseHandler, userHandle); + + xmlrpc_DECREF(paramArrayP); + } +} + + + +void +xmlrpc_client_start_rpcf_va(xmlrpc_env * const envP, + xmlrpc_client * const clientP, + const char * const serverUrl, + const char * const methodName, + xmlrpc_response_handler responseHandler, + void * const userHandle, + const char * const format, + va_list args) { + + xmlrpc_server_info * serverInfoP; + + serverInfoP = xmlrpc_server_info_new(envP, serverUrl); + if (!envP->fault_occurred) { + xmlrpc_client_start_rpcf_server_va( + envP, clientP, + serverInfoP, methodName, + responseHandler, userHandle, + format, args); + + xmlrpc_server_info_free(serverInfoP); + } +} + + + void 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, + void * const userHandle, const char * const format, ...) { va_list args; - xmlrpc_value * paramArrayP; - const char * suffix; - XMLRPC_ASSERT_PTR_OK(serverUrl); XMLRPC_ASSERT_PTR_OK(format); - /* Build our argument array. */ va_start(args, format); - xmlrpc_build_value_va(envP, format, args, ¶mArrayP, &suffix); + xmlrpc_client_start_rpcf_va(envP, clientP, serverUrl, methodName, + responseHandler, + userHandle, format, args); 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); - } } diff --git a/libs/xmlrpc-c/src/xmlrpc_client_global.c b/libs/xmlrpc-c/src/xmlrpc_client_global.c index 7beba14..362b99f 100644 --- a/libs/xmlrpc-c/src/xmlrpc_client_global.c +++ b/libs/xmlrpc-c/src/xmlrpc_client_global.c @@ -122,38 +122,6 @@ xmlrpc_client_transport_call( -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, @@ -162,21 +130,19 @@ xmlrpc_client_call(xmlrpc_env * const envP, ...) { xmlrpc_value * resultP; - - xmlrpc_server_info * serverInfoP; - serverInfoP = xmlrpc_server_info_new(envP, serverUrl); - + validateGlobalClientExists(envP); + if (!envP->fault_occurred) { va_list args; + va_start(args, format); - clientCall_va(envP, serverInfoP, methodName, format, args, &resultP); + xmlrpc_client_call2f_va(envP, globalClientP, serverUrl, + methodName, format, &resultP, args); va_end(args); - xmlrpc_server_info_free(serverInfoP); } - return resultP; } @@ -184,18 +150,24 @@ xmlrpc_client_call(xmlrpc_env * const envP, xmlrpc_value * xmlrpc_client_call_server(xmlrpc_env * const envP, - const xmlrpc_server_info * const serverP, + const xmlrpc_server_info * const serverInfoP, 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); + validateGlobalClientExists(envP); + + if (!envP->fault_occurred) { + va_list args; + + va_start(args, format); + xmlrpc_client_call_server2_va(envP, globalClientP, serverInfoP, + methodName, format, args, &resultP); + va_end(args); + } return resultP; } @@ -300,25 +272,16 @@ xmlrpc_client_call_asynch(const char * const serverUrl, 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); - } + xmlrpc_client_start_rpcf_va(&env, globalClientP, + serverUrl, methodName, + responseHandler, userData, + format, args); + + va_end(args); } if (env.fault_occurred) (*responseHandler)(serverUrl, methodName, NULL, userData, &env, NULL); @@ -364,28 +327,21 @@ xmlrpc_client_call_server_asynch(xmlrpc_server_info * const serverInfoP, ...) { 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); + validateGlobalClientExists(&env); 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); + va_list args; + + xmlrpc_env_init(&env); + + va_start(args, format); + + xmlrpc_client_start_rpcf_server_va( + &env, globalClientP, serverInfoP, methodName, + responseHandler, userData, format, args); + + va_end(args); } if (env.fault_occurred) (*responseHandler)(serverInfoP->serverUrl, methodName, NULL, diff --git a/libs/xmlrpc-c/src/xmlrpc_data.c b/libs/xmlrpc-c/src/xmlrpc_data.c index 28827fe..9330c12 100644 --- a/libs/xmlrpc-c/src/xmlrpc_data.c +++ b/libs/xmlrpc-c/src/xmlrpc_data.c @@ -14,6 +14,17 @@ #include "xmlrpc-c/base_int.h" + +static void +destroyCptr(xmlrpc_value * const valueP) { + + if (valueP->_value.cptr.dtor) + valueP->_value.cptr.dtor(valueP->_value.cptr.dtorContext, + valueP->_value.cptr.objectP); +} + + + static void destroyValue(xmlrpc_value * const valueP) { @@ -29,7 +40,7 @@ destroyValue(xmlrpc_value * const valueP) { break; case XMLRPC_TYPE_DATETIME: - xmlrpc_mem_block_clean(&valueP->_block); + xmlrpc_destroyDatetime(valueP); break; case XMLRPC_TYPE_STRING: @@ -49,6 +60,7 @@ destroyValue(xmlrpc_value * const valueP) { break; case XMLRPC_TYPE_C_PTR: + destroyCptr(valueP); break; case XMLRPC_TYPE_NIL: @@ -220,9 +232,9 @@ xmlrpc_read_base64(xmlrpc_env * const envP, byteStringValue = malloc(size); if (byteStringValue == NULL) - xmlrpc_env_set_fault_formatted( - envP, XMLRPC_INTERNAL_ERROR, "Unable to allocate %u bytes " - "for byte string.", size); + xmlrpc_faultf(envP, + "Unable to allocate %u bytes for byte string.", + (unsigned)size); else { memcpy(byteStringValue, contents, size); *byteStringValueP = (const unsigned char *)byteStringValue; @@ -269,7 +281,7 @@ xmlrpc_read_cptr(xmlrpc_env * const envP, validateType(envP, valueP, XMLRPC_TYPE_C_PTR); if (!envP->fault_occurred) - *ptrValueP = valueP->_value.c_ptr; + *ptrValueP = valueP->_value.cptr.objectP; } @@ -431,13 +443,26 @@ xmlrpc_value * xmlrpc_cptr_new(xmlrpc_env * const envP, void * const value) { + return xmlrpc_cptr_new_dtor(envP, value, NULL, NULL); +} + + + +xmlrpc_value * +xmlrpc_cptr_new_dtor(xmlrpc_env * const envP, + void * const value, + xmlrpc_cptr_dtor_fn const dtor, + void * const dtorContext) { + xmlrpc_value * valP; xmlrpc_createXmlrpcValue(envP, &valP); if (!envP->fault_occurred) { valP->_type = XMLRPC_TYPE_C_PTR; - valP->_value.c_ptr = value; + valP->_value.cptr.objectP = value; + valP->_value.cptr.dtor = dtor; + valP->_value.cptr.dtorContext = dtorContext; } return valP; } diff --git a/libs/xmlrpc-c/src/xmlrpc_datetime.c b/libs/xmlrpc-c/src/xmlrpc_datetime.c index 832f4fb..a36925f 100644 --- a/libs/xmlrpc-c/src/xmlrpc_datetime.c +++ b/libs/xmlrpc-c/src/xmlrpc_datetime.c @@ -1,34 +1,30 @@ #include "xmlrpc_config.h" +#define _XOPEN_SOURCE 600 /* Make sure strdup() is in */ + #include #include #include #include #include +#include #if MSVCRT #include #endif #include "bool.h" +#include "mallocvar.h" +#include "xmlrpc-c/c_util.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 - 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 - parser and builder should call on routines in here to do that. - - time_t won't work because it can't represent times before 1970 or - after 2038. We need to figure out something better. -*/ - +#if HAVE_REGEX +#include +#endif #if MSVCRT @@ -112,19 +108,65 @@ validateDatetimeType(xmlrpc_env * const envP, void +xmlrpc_read_datetime(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + xmlrpc_datetime * const dtP) { + + validateDatetimeType(envP, valueP); + if (!envP->fault_occurred) { + *dtP = valueP->_value.dt; + } +} + + + +void xmlrpc_read_datetime_str(xmlrpc_env * const envP, const xmlrpc_value * const valueP, const char ** const stringValueP) { - +/*---------------------------------------------------------------------------- + This exists for backward compatibility. No normal modern program would + want to see a datetime value in this format. Note that the format isn't + even ISO 8601 -- it's a bizarre hybrid of two ISO 8601 formats. + + Do not extend this. + + This exists because Xmlrpc-c was at one time lazy and this was the only way + to extract the value. An xmlrpc_value in those days represented a datetime + with the actual XML-RPC wire format of a datetime, and this function simply + returned a copy of it. +-----------------------------------------------------------------------------*/ validateDatetimeType(envP, valueP); if (!envP->fault_occurred) { - const char * const contents = - XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block); - *stringValueP = strdup(contents); - if (*stringValueP == NULL) - xmlrpc_env_set_fault_formatted( - envP, XMLRPC_INTERNAL_ERROR, "Unable to allocate space " - "for datetime string"); + time_t secs; + unsigned int usecs; + + xmlrpc_read_datetime_usec(envP, valueP, &secs, &usecs); + + if (!envP->fault_occurred) { + struct tm brokenTime; + char dtString[64]; + + xmlrpc_gmtime(secs, &brokenTime); + + /* Note that this format is NOT ISO 8601 -- it's a bizarre + hybrid of two ISO 8601 formats. + */ + strftime(dtString, sizeof(dtString), "%Y%m%dT%H:%M:%S", + &brokenTime); + + if (usecs != 0) { + char usecString[64]; + assert(usecs < 1000000); + snprintf(usecString, sizeof(usecString), ".%06u", usecs); + STRSCAT(dtString, usecString); + } + + *stringValueP = strdup(dtString); + if (*stringValueP == NULL) + xmlrpc_faultf(envP, + "Unable to allocate memory for datetime string"); + } } } @@ -134,23 +176,164 @@ void xmlrpc_read_datetime_str_old(xmlrpc_env * const envP, const xmlrpc_value * const valueP, const char ** const stringValueP) { + + assert(valueP->_cache); validateDatetimeType(envP, valueP); if (!envP->fault_occurred) { - *stringValueP = XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block); + const char ** const readBufferP = valueP->_cache; + + if (!*readBufferP) + /* Nobody's asked for the internal buffer before. Set it up. */ + xmlrpc_read_datetime_str(envP, valueP, readBufferP); + + *stringValueP = *readBufferP; + } +} + + + +void +xmlrpc_read_datetime_usec(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + time_t * const secsP, + unsigned int * const usecsP) { + + validateDatetimeType(envP, valueP); + + if (!envP->fault_occurred) { + if (valueP->_value.dt.Y < 1970) + xmlrpc_faultf(envP, "Year (%u) is too early to represent as " + "a standard Unix time", + valueP->_value.dt.Y); + else { + struct tm brokenTime; + const char * error; + + brokenTime.tm_sec = valueP->_value.dt.s; + brokenTime.tm_min = valueP->_value.dt.m; + brokenTime.tm_hour = valueP->_value.dt.h; + brokenTime.tm_mday = valueP->_value.dt.D; + brokenTime.tm_mon = valueP->_value.dt.M - 1; + brokenTime.tm_year = valueP->_value.dt.Y - 1900; + + xmlrpc_timegm(&brokenTime, secsP, &error); + + if (error) { + /* Ideally, this wouldn't be possible - it wouldn't be + possible to create an xmlrpc_value that doesn't actually + represent a real datetime. But today, we're lazy and + don't fully validate incoming XML-RPC + elements, and we also have the legacy + xmlrpc_datetime_new_str() constructor to which the user + may feed garbage. + + We should tighten that up and then simply assert here that + xmlrpc_timegm() succeeded. + */ + xmlrpc_env_set_fault_formatted(envP, XMLRPC_PARSE_ERROR, + "A datetime received in an XML-RPC message " + "or generated with legacy Xmlrpc-c facilities " + "does not validly describe a datetime. %s", + error); + xmlrpc_strfree(error); + } else + *usecsP = valueP->_value.dt.u; + } } } +void +xmlrpc_read_datetime_sec(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + time_t * const timeValueP) { + + unsigned int usecs; + + xmlrpc_read_datetime_usec(envP, valueP, timeValueP, &usecs); +} + + + +#if XMLRPC_HAVE_TIMEVAL + +void +xmlrpc_read_datetime_timeval(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + struct timeval * const timeValueP) { + + time_t secs; + unsigned int usecs; + + xmlrpc_read_datetime_usec(envP, valueP, &secs, &usecs); + + timeValueP->tv_sec = secs; + timeValueP->tv_usec = usecs; +} +#endif + + + +#if XMLRPC_HAVE_TIMESPEC + +void +xmlrpc_read_datetime_timespec(xmlrpc_env * const envP, + const xmlrpc_value * const valueP, + struct timespec * const timeValueP) { + + time_t secs; + unsigned int usecs; + + xmlrpc_read_datetime_usec(envP, valueP, &secs, &usecs); + + timeValueP->tv_sec = secs; + timeValueP->tv_nsec = usecs * 1000; +} +#endif + + + +xmlrpc_value * +xmlrpc_datetime_new(xmlrpc_env * const envP, + xmlrpc_datetime const dt) { + + xmlrpc_value * valP; + + const char ** readBufferP; + + MALLOCVAR(readBufferP); + + if (!readBufferP) + xmlrpc_faultf(envP, "Couldn't get memory for the cache part of the " + "XML-RPC datetime value object"); + + else { + *readBufferP = NULL; + + xmlrpc_createXmlrpcValue(envP, &valP); + + if (!envP->fault_occurred) { + valP->_type = XMLRPC_TYPE_DATETIME; + + valP->_value.dt = dt; + + valP->_cache = readBufferP; + } + if (envP->fault_occurred) + free(readBufferP); + } + return valP; +} + + + static void -parseDateNumbers(const char * const t, - unsigned int * const YP, - unsigned int * const MP, - unsigned int * const DP, - unsigned int * const hP, - unsigned int * const mP, - unsigned int * const sP) { +parseDatetimeString(const char * const datetimeString, + xmlrpc_datetime * const dtP) { + + size_t const dtStrlen = strlen(datetimeString); char year[4+1]; char month[2+1]; @@ -159,177 +342,219 @@ parseDateNumbers(const char * const t, char minute[2+1]; char second[2+1]; - assert(strlen(t) == 17); + /* Because we require input to be valid: */ + assert(dtStrlen >= 17 && dtStrlen != 18 && dtStrlen <= 24); - year[0] = t[ 0]; - year[1] = t[ 1]; - year[2] = t[ 2]; - year[3] = t[ 3]; + year[0] = datetimeString[ 0]; + year[1] = datetimeString[ 1]; + year[2] = datetimeString[ 2]; + year[3] = datetimeString[ 3]; year[4] = '\0'; - month[0] = t[ 4]; - month[1] = t[ 5]; + month[0] = datetimeString[ 4]; + month[1] = datetimeString[ 5]; month[2] = '\0'; - day[0] = t[ 6]; - day[1] = t[ 7]; + day[0] = datetimeString[ 6]; + day[1] = datetimeString[ 7]; day[2] = '\0'; - assert(t[ 8] == 'T'); + assert(datetimeString[ 8] == 'T'); - hour[0] = t[ 9]; - hour[1] = t[10]; + hour[0] = datetimeString[ 9]; + hour[1] = datetimeString[10]; hour[2] = '\0'; - assert(t[11] == ':'); + assert(datetimeString[11] == ':'); - minute[0] = t[12]; - minute[1] = t[13]; + minute[0] = datetimeString[12]; + minute[1] = datetimeString[13]; minute[2] = '\0'; - assert(t[14] == ':'); + assert(datetimeString[14] == ':'); - second[0] = t[15]; - second[1] = t[16]; + second[0] = datetimeString[15]; + second[1] = datetimeString[16]; second[2] = '\0'; - *YP = atoi(year); - *MP = atoi(month); - *DP = atoi(day); - *hP = atoi(hour); - *mP = atoi(minute); - *sP = atoi(second); + if (dtStrlen > 17) { + size_t const pad = 24 - dtStrlen; + size_t i; + + dtP->u = atoi(&datetimeString[18]); + for (i = 0; i < pad; ++i) + dtP->u *= 10; + } else + dtP->u = 0; + + dtP->Y = atoi(year); + dtP->M = atoi(month); + dtP->D = atoi(day); + dtP->h = atoi(hour); + dtP->m = atoi(minute); + dtP->s = atoi(second); +} + + + +static void +validateFirst17(xmlrpc_env * const envP, + const char * const dt) { +/*---------------------------------------------------------------------------- + Assuming 'dt' is at least 17 characters long, validate that the first + 17 characters are a valid XML-RPC datetime, e.g. + "20080628T16:35:02" +-----------------------------------------------------------------------------*/ + unsigned int i; + + for (i = 0; i < 8 && !envP->fault_occurred; ++i) + if (!isdigit(dt[i])) + xmlrpc_faultf(envP, "Not a digit: '%c'", dt[i]); + + if (dt[8] != 'T') + xmlrpc_faultf(envP, "9th character is '%c', not 'T'", dt[8]); + if (!isdigit(dt[9])) + xmlrpc_faultf(envP, "Not a digit: '%c'", dt[9]); + if (!isdigit(dt[10])) + xmlrpc_faultf(envP, "Not a digit: '%c'", dt[10]); + if (dt[11] != ':') + xmlrpc_faultf(envP, "Not a colon: '%c'", dt[11]); + if (!isdigit(dt[12])) + xmlrpc_faultf(envP, "Not a digit: '%c'", dt[12]); + if (!isdigit(dt[13])) + xmlrpc_faultf(envP, "Not a digit: '%c'", dt[13]); + if (dt[14] != ':') + xmlrpc_faultf(envP, "Not a colon: '%c'", dt[14]); + if (!isdigit(dt[15])) + xmlrpc_faultf(envP, "Not a digit: '%c'", dt[15]); + if (!isdigit(dt[16])) + xmlrpc_faultf(envP, "Not a digit: '%c'", dt[16]); +} + + + +static void +validateFractionalSeconds(xmlrpc_env * const envP, + const char * const dt) { +/*---------------------------------------------------------------------------- + Validate the fractional seconds part of the XML-RPC datetime string + 'dt', if any. That's the decimal point and everything following + it. +-----------------------------------------------------------------------------*/ + if (strlen(dt) > 17) { + if (dt[17] != '.') { + xmlrpc_faultf(envP, "'%c' where only a period is valid", dt[17]); + } else { + if (dt[18] == '\0') + xmlrpc_faultf(envP, "Nothing after decimal point"); + else { + unsigned int i; + for (i = 18; dt[i] != '\0' && !envP->fault_occurred; ++i) { + if (!isdigit(dt[i])) + xmlrpc_faultf(envP, + "Non-digit in fractional seconds: '%c'", + dt[i]); + } + } + } + } } static void validateFormat(xmlrpc_env * const envP, - const char * const t) { + const char * const dt) { - if (strlen(t) != 17) - xmlrpc_faultf(envP, "%u characters instead of 15.", strlen(t)); - else if (t[8] != 'T') - xmlrpc_faultf(envP, "9th character is '%c', not 'T'", t[8]); + if (strlen(dt) < 17) + xmlrpc_faultf(envP, + "Invalid length of %u of datetime string. " + "Must be at least 17 characters", + (unsigned)strlen(dt)); else { - unsigned int i; - - for (i = 0; i < 8 && !envP->fault_occurred; ++i) - if (!isdigit(t[i])) - xmlrpc_faultf(envP, "Not a digit: '%c'", t[i]); - - if (!isdigit(t[9])) - xmlrpc_faultf(envP, "Not a digit: '%c'", t[9]); - if (!isdigit(t[10])) - xmlrpc_faultf(envP, "Not a digit: '%c'", t[10]); - if (t[11] != ':') - xmlrpc_faultf(envP, "Not a colon: '%c'", t[11]); - if (!isdigit(t[12])) - xmlrpc_faultf(envP, "Not a digit: '%c'", t[12]); - if (!isdigit(t[13])) - xmlrpc_faultf(envP, "Not a digit: '%c'", t[13]); - if (t[14] != ':') - xmlrpc_faultf(envP, "Not a colon: '%c'", t[14]); - if (!isdigit(t[15])) - xmlrpc_faultf(envP, "Not a digit: '%c'", t[15]); - if (!isdigit(t[16])) - xmlrpc_faultf(envP, "Not a digit: '%c'", t[16]); + validateFirst17(envP, dt); + + if (!envP->fault_occurred) + validateFractionalSeconds(envP, dt); } -} +} -static void -parseDatetime(xmlrpc_env * const envP, - const char * const t, - time_t * const timeValueP) { -/*---------------------------------------------------------------------------- - Parse a time in the format stored in an xmlrpc_value and return the - time that it represents. +/* Microsoft Visual C in debug mode produces code that complains about + returning an undefined value from xmlrpc_datetime_new_str(). It's a bogus + complaint, because this function is defined to return nothing meaningful + those cases. So we disable the check. +*/ +#pragma runtime_checks("u", off) - t[] is the input time string. We return the result as *timeValueP. - 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. +xmlrpc_value * +xmlrpc_datetime_new_str(xmlrpc_env * const envP, + const char * const datetimeString) { +/*---------------------------------------------------------------------------- + This exists only for backward compatibility. Originally, this was the + only way to create a datetime XML-RPC value, because we had a really + lazy implementation of XML-RPC serialization and parsing (basically, the + user did it!). - 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. + Do not extend this. The user should use more normal C representations + of datetimes. -----------------------------------------------------------------------------*/ - validateFormat(envP, t); + xmlrpc_value * retval; + validateFormat(envP, datetimeString); if (!envP->fault_occurred) { - unsigned int Y, M, D, h, m, s; - - parseDateNumbers(t, &Y, &M, &D, &h, &m, &s); - - 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; - - xmlrpc_timegm(&brokenTime, timeValueP, &error); + xmlrpc_datetime dt; - if (error) { - xmlrpc_env_set_fault(envP, XMLRPC_PARSE_ERROR, error); - xmlrpc_strfree(error); - } - } + parseDatetimeString(datetimeString, &dt); + + /* Note that parseDatetimeString() can generate an invalid datetime + value, e.g. Hour 25 or February 30. Ideally, we would catch that + here, but due to laziness, we simply accept the possibility of + invalid xmlrpc_datetime in xmlrpc_value and whoever uses the the + xmlrpc_value has to deal with it. + */ + retval = xmlrpc_datetime_new(envP, dt); } + + return retval; } -void -xmlrpc_read_datetime_sec(xmlrpc_env * const envP, - const xmlrpc_value * const valueP, - time_t * const timeValueP) { - - validateDatetimeType(envP, valueP); - if (!envP->fault_occurred) - parseDatetime(envP, - XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block), - timeValueP); -} +#pragma runtime_checks("u", restore) xmlrpc_value * -xmlrpc_datetime_new_str(xmlrpc_env * const envP, - const char * const value) { +xmlrpc_datetime_new_usec(xmlrpc_env * const envP, + time_t const secs, + unsigned int const usecs) { - xmlrpc_value * valP; + xmlrpc_value * valueP; - xmlrpc_createXmlrpcValue(envP, &valP); + if (usecs >= 1000000) + xmlrpc_faultf(envP, "Number of fractional microseconds must be less " + "than one million. You specified %u", usecs); + else { + struct tm brokenTime; + xmlrpc_datetime dt; - if (!envP->fault_occurred) { - valP->_type = XMLRPC_TYPE_DATETIME; + xmlrpc_gmtime(secs, &brokenTime); - XMLRPC_TYPED_MEM_BLOCK_INIT( - char, envP, &valP->_block, strlen(value) + 1); - if (!envP->fault_occurred) { - char * const contents = - XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, &valP->_block); - strcpy(contents, value); - } - if (envP->fault_occurred) - free(valP); + dt.s = brokenTime.tm_sec; + dt.m = brokenTime.tm_min; + dt.h = brokenTime.tm_hour; + dt.D = brokenTime.tm_mday; + dt.M = brokenTime.tm_mon + 1; + dt.Y = 1900 + brokenTime.tm_year; + dt.u = usecs; + + valueP = xmlrpc_datetime_new(envP, dt); } - return valP; + return valueP; } @@ -338,34 +563,42 @@ xmlrpc_value * xmlrpc_datetime_new_sec(xmlrpc_env * const envP, time_t const value) { - xmlrpc_value * valP; - - xmlrpc_createXmlrpcValue(envP, &valP); + return xmlrpc_datetime_new_usec(envP, value, 0); +} - if (!envP->fault_occurred) { - struct tm brokenTime; - char timeString[64]; - - valP->_type = XMLRPC_TYPE_DATETIME; - xmlrpc_gmtime(value, &brokenTime); - - /* Note that this format is NOT ISO 8601 -- it's a bizarre - hybrid of two ISO 8601 formats. - */ - strftime(timeString, sizeof(timeString), "%Y%m%dT%H:%M:%S", - &brokenTime); - - XMLRPC_TYPED_MEM_BLOCK_INIT( - char, envP, &valP->_block, strlen(timeString) + 1); - if (!envP->fault_occurred) { - char * const contents = - XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, &valP->_block); - - strcpy(contents, timeString); - } - if (envP->fault_occurred) - free(valP); - } - return valP; + +#if XMLRPC_HAVE_TIMEVAL + +xmlrpc_value * +xmlrpc_datetime_new_timeval(xmlrpc_env * const envP, + struct timeval const value) { + + return xmlrpc_datetime_new_usec(envP, value.tv_sec, value.tv_usec); +} +#endif + + + +#if XMLRPC_HAVE_TIMESPEC + +xmlrpc_value * +xmlrpc_datetime_new_timespec(xmlrpc_env * const envP, + struct timespec const value) { + + return xmlrpc_datetime_new_usec(envP, value.tv_sec, value.tv_nsec/1000); +} +#endif + + + +void +xmlrpc_destroyDatetime(xmlrpc_value * const datetimeP) { + + const char ** const readBufferP = datetimeP->_cache; + + if (*readBufferP) + xmlrpc_strfree(*readBufferP); + + free(datetimeP->_cache); } diff --git a/libs/xmlrpc-c/src/xmlrpc_decompose.c b/libs/xmlrpc-c/src/xmlrpc_decompose.c index eeb3414..6323a26 100644 --- a/libs/xmlrpc-c/src/xmlrpc_decompose.c +++ b/libs/xmlrpc-c/src/xmlrpc_decompose.c @@ -712,7 +712,7 @@ buildArrayDecompBranch(xmlrpc_env * const envP, 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.", + "a format string is %u.", (unsigned) ARRAY_SIZE(decompNodeP->store.Tarray.itemArray)); else { struct decompTreeNode * itemNodeP; @@ -850,7 +850,7 @@ buildStructDecompBranch(xmlrpc_env * const envP, xmlrpc_faultf(envP, "Too many structure members in format string. " "The most members you can specify in " - "a format string is %u.", + "a format string is %u.", (unsigned) ARRAY_SIZE(decompNodeP->store.Tstruct.mbrArray)); else { struct mbrDecomp * const mbrP = @@ -1059,9 +1059,8 @@ createDecompTree(xmlrpc_env * const envP, if (envP->fault_occurred) destroyDecompTree(decompRootP); - else - *decompRootPP = decompRootP; } + *decompRootPP = decompRootP; } diff --git a/libs/xmlrpc-c/src/xmlrpc_expat.c b/libs/xmlrpc-c/src/xmlrpc_expat.c index 9e6c37e..7b51d3e 100644 --- a/libs/xmlrpc-c/src/xmlrpc_expat.c +++ b/libs/xmlrpc-c/src/xmlrpc_expat.c @@ -108,27 +108,28 @@ xml_element_new (xmlrpc_env * const env, ** Blow away an existing element & all of its child elements. */ void -xml_element_free(xml_element * const elem) { +xml_element_free(xml_element * const elemP) { - xmlrpc_mem_block *children; - int size, i; - xml_element **contents; + xmlrpc_mem_block * childrenP; + size_t size, i; + xml_element ** contents; - XMLRPC_ASSERT_ELEM_OK(elem); + XMLRPC_ASSERT_ELEM_OK(elemP); - free(elem->_name); - elem->_name = XMLRPC_BAD_POINTER; - xmlrpc_mem_block_clean(&elem->_cdata); + free(elemP->_name); + elemP->_name = XMLRPC_BAD_POINTER; + XMLRPC_MEMBLOCK_CLEAN(xml_element *, &elemP->_cdata); /* Deallocate all of our children recursively. */ - children = &elem->_children; - contents = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(xml_element*, children); - size = XMLRPC_TYPED_MEM_BLOCK_SIZE(xml_element*, children); - for (i = 0; i < size; i++) + childrenP = &elemP->_children; + contents = XMLRPC_MEMBLOCK_CONTENTS(xml_element *, childrenP); + size = XMLRPC_MEMBLOCK_SIZE(xml_element *, childrenP); + for (i = 0; i < size; ++i) xml_element_free(contents[i]); - xmlrpc_mem_block_clean(&elem->_children); - free(elem); + XMLRPC_MEMBLOCK_CLEAN(xml_element *, &elemP->_children); + + free(elemP); } @@ -374,9 +375,8 @@ createParser(xmlrpc_env * const envP, xmlrpc_XML_SetCharacterDataHandler( parser, (XML_CharacterDataHandler) characterData); - - *parserP = parser; } + *parserP = parser; } diff --git a/libs/xmlrpc-c/src/xmlrpc_libxml2.c b/libs/xmlrpc-c/src/xmlrpc_libxml2.c index 9cba719..3df6231 100644 --- a/libs/xmlrpc-c/src/xmlrpc_libxml2.c +++ b/libs/xmlrpc-c/src/xmlrpc_libxml2.c @@ -240,8 +240,10 @@ typedef struct { */ static void -start_element (void *user_data, const xmlChar *name, const xmlChar **attrs) -{ +start_element(void * const user_data, + const xmlChar * const name, + const xmlChar ** const attrs ATTR_UNUSED) { + parse_context *context; xml_element *elem, *new_current; @@ -281,9 +283,12 @@ start_element (void *user_data, const xmlChar *name, const xmlChar **attrs) } } + + static void -end_element (void *user_data, const xmlChar *name) -{ +end_element(void * const user_data, + const xmlChar * const name ATTR_UNUSED) { + parse_context *context; XMLRPC_ASSERT(user_data != NULL && name != NULL); @@ -295,7 +300,7 @@ end_element (void *user_data, const xmlChar *name) /* 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(xmlrpc_streq(name, context->current->_name)); XMLRPC_ASSERT(context->current->_parent != NULL || context->current == context->root); diff --git a/libs/xmlrpc-c/src/xmlrpc_parse.c b/libs/xmlrpc-c/src/xmlrpc_parse.c index 43d9d54..848bfcd 100644 --- a/libs/xmlrpc-c/src/xmlrpc_parse.c +++ b/libs/xmlrpc-c/src/xmlrpc_parse.c @@ -1,5 +1,7 @@ /* Copyright information is at end of file. */ +#define _XOPEN_SOURCE 600 /* Make sure strdup() is in */ + #include "xmlrpc_config.h" #include @@ -32,6 +34,19 @@ invoke XMLRPC_FAIL if something looks wrong. */ +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); +} + + + #define CHECK_NAME(env,elem,name) \ do \ if (!xmlrpc_streq((name), xml_element_name(elem))) \ @@ -44,41 +59,29 @@ do \ if (xml_element_children_size(elem) != (count)) \ XMLRPC_FAIL3(env, XMLRPC_PARSE_ERROR, \ - "Expected <%s> to have %d children, found %d", \ + "Expected <%s> to have %u children, found %u", \ xml_element_name(elem), (count), \ - xml_element_children_size(elem)); \ + (unsigned)xml_element_children_size(elem)); \ while (0) static xml_element * -get_child_by_name (xmlrpc_env *env, xml_element *parent, char *name) -{ - size_t child_count, i; - xml_element **children; - - children = xml_element_children(parent); - child_count = xml_element_children_size(parent); - for (i = 0; i < child_count; i++) { - if (xmlrpc_streq(xml_element_name(children[i]), name)) - return children[i]; - } - - xmlrpc_env_set_fault_formatted(env, XMLRPC_PARSE_ERROR, - "Expected <%s> to have child <%s>", - xml_element_name(parent), name); - return NULL; -} +getChildByName (xmlrpc_env * const envP, + xml_element * const parentP, + const char * const name) { + size_t const childCount = xml_element_children_size(parentP); + xml_element ** const childrenP = xml_element_children(parentP); + unsigned int i; -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); + for (i = 0; i < childCount; ++i) { + if (xmlrpc_streq(xml_element_name(childrenP[i]), name)) + return childrenP[i]; + } + + setParseFault(envP, "Expected <%s> to have child <%s>", + xml_element_name(parentP), name); + return NULL; } @@ -94,10 +97,11 @@ 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 - element) to an xmlrpc_value of type array. Note that an - array is normally represented in XML by a element. We use - type xmlrpc_value to represent the parameter list just for convenience. + Convert an XML element representing a list of parameters (i.e. a + element) to an xmlrpc_value of type array. Note that an xmlrpc_value is + normally represented in XML by a element, not a element. + We use type xmlrpc_value to represent the parameter list just for + convenience. -----------------------------------------------------------------------------*/ xmlrpc_value *array, *item; int size, i; @@ -120,7 +124,8 @@ convert_params(xmlrpc_env * const envP, 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); + unsigned int const maxNest = (unsigned int) + xmlrpc_limit_get(XMLRPC_NESTING_LIMIT_ID); param = params[i]; CHECK_NAME(envP, param, "param"); @@ -155,7 +160,7 @@ convert_params(xmlrpc_env * const envP, static void parseCallXml(xmlrpc_env * const envP, const char * const xmlData, - size_t const xmlLen, + size_t const xmlDataLen, xml_element ** const callElemPP) { /*---------------------------------------------------------------------------- Parse the XML of an XML-RPC call. @@ -164,7 +169,7 @@ parseCallXml(xmlrpc_env * const envP, xmlrpc_env env; xmlrpc_env_init(&env); - xml_parse(&env, xmlData, xmlLen, &callElemP); + xml_parse(&env, xmlData, xmlDataLen, &callElemP); if (env.fault_occurred) xmlrpc_env_set_fault_formatted( envP, env.fault_code, "Call is not valid XML. %s", @@ -176,12 +181,11 @@ parseCallXml(xmlrpc_env * const envP, "Instead, we have a <%s> element.", xml_element_name(callElemP)); - if (!envP->fault_occurred) - *callElemPP = callElemP; - if (envP->fault_occurred) xml_element_free(callElemP); } + *callElemPP = callElemP; + xmlrpc_env_clean(&env); } @@ -229,7 +233,7 @@ parseCallChildren(xmlrpc_env * const envP, XMLRPC_ASSERT(xmlrpc_streq(xml_element_name(callElemP), "methodCall")); - nameElemP = get_child_by_name(envP, callElemP, "methodName"); + nameElemP = getChildByName(envP, callElemP, "methodName"); if (!envP->fault_occurred) { parseMethodNameElement(envP, nameElemP, methodNameP); @@ -239,7 +243,7 @@ parseCallChildren(xmlrpc_env * const envP, if (callChildCount > 1) { xml_element * paramsElemP; - paramsElemP = get_child_by_name(envP, callElemP, "params"); + paramsElemP = getChildByName(envP, callElemP, "params"); if (!envP->fault_occurred) *paramArrayPP = convert_params(envP, paramsElemP); @@ -272,7 +276,7 @@ parseCallChildren(xmlrpc_env * const envP, void xmlrpc_parse_call(xmlrpc_env * const envP, const char * const xmlData, - size_t const xmlLen, + size_t const xmlDataLen, const char ** const methodNameP, xmlrpc_value ** const paramArrayPP) { /*---------------------------------------------------------------------------- @@ -290,14 +294,14 @@ xmlrpc_parse_call(xmlrpc_env * const envP, 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)) + if (xmlDataLen > 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)); + (unsigned)xmlrpc_limit_get(XMLRPC_XML_SIZE_LIMIT_ID)); else { xml_element * callElemP; - parseCallXml(envP, xmlData, xmlLen, &callElemP); + parseCallXml(envP, xmlData, xmlDataLen, &callElemP); if (!envP->fault_occurred) { parseCallChildren(envP, callElemP, methodNameP, paramArrayPP); @@ -399,7 +403,7 @@ parseFaultElement(xmlrpc_env * const envP, int * const faultCodeP, const char ** const faultStringP) { - unsigned int const maxRecursion = + unsigned int const maxRecursion = (unsigned int) xmlrpc_limit_get(XMLRPC_NESTING_LIMIT_ID); XMLRPC_ASSERT(xmlrpc_streq(xml_element_name(faultElement), "fault")); @@ -533,7 +537,7 @@ xmlrpc_parse_response2(xmlrpc_env * const envP, 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; + xml_element * responseEltP; XMLRPC_ASSERT_ENV_OK(envP); XMLRPC_ASSERT(xmlData != NULL); @@ -547,27 +551,29 @@ xmlrpc_parse_response2(xmlrpc_env * const envP, 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); + (unsigned)xmlrpc_limit_get(XMLRPC_XML_SIZE_LIMIT_ID), + (unsigned)xmlDataLen); else { xmlrpc_env env; xmlrpc_env_init(&env); - xml_parse(&env, xmlData, xmlDataLen, &response); + xml_parse(&env, xmlData, xmlDataLen, &responseEltP); 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, + if (xmlrpc_streq(xml_element_name(responseEltP), + "methodResponse")) { + parseMethodResponseElt(envP, responseEltP, resultPP, faultCodeP, faultStringP); } else setParseFault(envP, "XML-RPC response must consist of a " " element. " "This has a <%s> instead.", - xml_element_name(response)); + xml_element_name(responseEltP)); - xml_element_free(response); + xml_element_free(responseEltP); } xmlrpc_env_clean(&env); } @@ -607,6 +613,57 @@ xmlrpc_parse_response(xmlrpc_env * const envP, +void +xmlrpc_parse_value_xml(xmlrpc_env * const envP, + const char * const xmlData, + size_t const xmlDataLen, + xmlrpc_value ** const valuePP) { +/*---------------------------------------------------------------------------- + Compute the xmlrpc_value represented by the XML document 'xmlData' (of + length 'xmlDataLen' characters), which must consist of a single + element. 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. + + This isn't generally useful in XML-RPC programs, because such programs + parse a whole XML-RPC call or response document, and never see the XML text + of just a element. But a program may do some weird form of XML-RPC + processing or just borrow Xmlrpc-c's value serialization facilities for + something unrelated to XML-RPC. In any case, it makes sense to have an + inverse of xmlrpc_serialize_value2(), which generates XML text from an + xmlrpc_value. +-----------------------------------------------------------------------------*/ + xmlrpc_env env; + + xml_element * valueEltP; + + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT(xmlData != NULL); + + xmlrpc_env_init(&env); + + xml_parse(&env, xmlData, xmlDataLen, &valueEltP); + + if (env.fault_occurred) { + setParseFault(envP, "Not valid XML. %s", env.fault_string); + } else { + if (xmlrpc_streq(xml_element_name(valueEltP), "value")) { + unsigned int const maxRecursion = (unsigned int) + xmlrpc_limit_get(XMLRPC_NESTING_LIMIT_ID); + xmlrpc_parseValue(envP, maxRecursion, valueEltP, valuePP); + } else + setParseFault(envP, "XML-RPC value XML document must consist of " + "a element. This has a <%s> instead.", + xml_element_name(valueEltP)); + xml_element_free(valueEltP); + } + xmlrpc_env_clean(&env); +} + + + /* Copyright (C) 2001 by First Peer, Inc. All rights reserved. ** ** Redistribution and use in source and binary forms, with or without diff --git a/libs/xmlrpc-c/src/xmlrpc_registry.c b/libs/xmlrpc-c/src/xmlrpc_registry.c deleted file mode 100644 index d320019..0000000 --- a/libs/xmlrpc-c/src/xmlrpc_registry.c +++ /dev/null @@ -1,830 +0,0 @@ -/* 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. */ - -#include "xmlrpc_config.h" - -#include -#include - -#include "xmlrpc-c/base.h" -#include "xmlrpc-c/server.h" -#include "xmlrpc-c/base_int.h" - -/*========================================================================= -** XML-RPC Server Method Registry -**========================================================================= -** A method registry maintains a list of functions, and handles -** dispatching. To build an XML-RPC server, just add a communications -** protocol. :-) -*/ - -static void -install_system_methods (xmlrpc_env *env, xmlrpc_registry *registry); - -xmlrpc_registry * -xmlrpc_registry_new(xmlrpc_env *env) { - - xmlrpc_value *methods; - xmlrpc_registry *registry; - int registry_valid; - - XMLRPC_ASSERT_ENV_OK(env); - - /* Error-handling preconditions. */ - methods = NULL; - registry = NULL; - registry_valid = 0; - - /* Allocate our memory. */ - methods = xmlrpc_struct_new(env); - XMLRPC_FAIL_IF_FAULT(env); - registry = (xmlrpc_registry*) malloc(sizeof(xmlrpc_registry)); - XMLRPC_FAIL_IF_NULL(registry, env, XMLRPC_INTERNAL_ERROR, - "Could not allocate memory for registry"); - - /* Set everything up. */ - registry->_introspection_enabled = 1; - registry->_methods = methods; - registry->_default_method = NULL; - registry->_preinvoke_method = NULL; - registry_valid = 1; - - /* Install our system methods. */ - install_system_methods(env, registry); - XMLRPC_FAIL_IF_FAULT(env); - - cleanup: - if (env->fault_occurred) { - if (registry_valid) { - xmlrpc_registry_free(registry); - } else { - if (methods) - xmlrpc_DECREF(methods); - if (registry) - free(registry); - } - return NULL; - } - return registry; -} - - - -void -xmlrpc_registry_free(xmlrpc_registry * registry) { - - XMLRPC_ASSERT_PTR_OK(registry); - XMLRPC_ASSERT(registry->_methods != XMLRPC_BAD_POINTER); - - xmlrpc_DECREF(registry->_methods); - registry->_methods = XMLRPC_BAD_POINTER; - if (registry->_default_method != NULL) - xmlrpc_DECREF(registry->_default_method); - if (registry->_preinvoke_method != NULL) - xmlrpc_DECREF(registry->_preinvoke_method); - free(registry); -} - - - -/*========================================================================= -** xmlrpc_registry_disable_introspection -**========================================================================= -** See xmlrpc.h for more documentation. -*/ - -void -xmlrpc_registry_disable_introspection(xmlrpc_registry * registry) { - XMLRPC_ASSERT_PTR_OK(registry); - registry->_introspection_enabled = 0; -} - - - -/*========================================================================= -** xmlrpc_registry_add_method -**========================================================================= -** See xmlrpc.h for more documentation. -*/ - -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_w_doc (env, registry, host, method_name, - method, user_data, "?", - "No help is available for this method."); -} - - - -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) { - xmlrpc_value *method_info; - - XMLRPC_ASSERT_ENV_OK(env); - XMLRPC_ASSERT_PTR_OK(registry); - XMLRPC_ASSERT(host == NULL); - XMLRPC_ASSERT_PTR_OK(method_name); - XMLRPC_ASSERT_PTR_OK(method); - - /* Error-handling preconditions. */ - method_info = NULL; - - /* Store our method and user data into our hash table. */ - method_info = xmlrpc_build_value(env, "(ppss)", (void*) method, user_data, - signature, help); - XMLRPC_FAIL_IF_FAULT(env); - xmlrpc_struct_set_value(env, registry->_methods, method_name, method_info); - XMLRPC_FAIL_IF_FAULT(env); - - cleanup: - if (method_info) - xmlrpc_DECREF(method_info); - -} - - - -/*========================================================================= -** xmlrpc_registry_set_default_method -**========================================================================= -** See xmlrpc.h for more documentation. -*/ - -void -xmlrpc_registry_set_default_method(xmlrpc_env *env, - xmlrpc_registry *registry, - xmlrpc_default_method handler, - void *user_data) { - xmlrpc_value *method_info; - - XMLRPC_ASSERT_ENV_OK(env); - XMLRPC_ASSERT_PTR_OK(registry); - XMLRPC_ASSERT_PTR_OK(handler); - - /* Error-handling preconditions. */ - method_info = NULL; - - /* Store our method and user data into our hash table. */ - method_info = xmlrpc_build_value(env, "(pp)", (void*) handler, user_data); - XMLRPC_FAIL_IF_FAULT(env); - - /* Dispose of any pre-existing default method and install ours. */ - if (registry->_default_method) - xmlrpc_DECREF(registry->_default_method); - registry->_default_method = method_info; - -cleanup: - if (env->fault_occurred) { - if (method_info) - xmlrpc_DECREF(method_info); - } -} - - - -/*========================================================================= -** xmlrpc_registry_set_preinvoke_method -**========================================================================= -** See xmlrpc.h for more documentation. -*/ - -void -xmlrpc_registry_set_preinvoke_method(xmlrpc_env *env, - xmlrpc_registry *registry, - xmlrpc_preinvoke_method handler, - void *user_data) { - xmlrpc_value *method_info; - - XMLRPC_ASSERT_ENV_OK(env); - XMLRPC_ASSERT_PTR_OK(registry); - XMLRPC_ASSERT_PTR_OK(handler); - - /* Error-handling preconditions. */ - method_info = NULL; - - /* Store our method and user data into our hash table. */ - method_info = xmlrpc_build_value(env, "(pp)", (void*) handler, user_data); - XMLRPC_FAIL_IF_FAULT(env); - - /* Dispose of any pre-existing preinvoke method and install ours. */ - if (registry->_preinvoke_method) - xmlrpc_DECREF(registry->_preinvoke_method); - registry->_preinvoke_method = method_info; - - cleanup: - if (env->fault_occurred) { - if (method_info) - xmlrpc_DECREF(method_info); - } -} - - - -/*========================================================================= -** dispatch_call -**========================================================================= -** An internal method which actually does the dispatch. This may get -** prettified and exported at some point in the future. -*/ - -static void -callPreinvokeMethodIfAny(xmlrpc_env * const envP, - xmlrpc_registry * const registryP, - const char * const methodName, - xmlrpc_value * const paramArrayP) { - - /* Get the preinvoke method, if it is set. */ - if (registryP->_preinvoke_method) { - xmlrpc_preinvoke_method preinvoke_method; - void * user_data; - - xmlrpc_parse_value(envP, registryP->_preinvoke_method, "(pp)", - &preinvoke_method, &user_data); - if (!envP->fault_occurred) - (*preinvoke_method)(envP, methodName, - paramArrayP, user_data); - } -} - - - -static void -callDefaultMethod(xmlrpc_env * const envP, - xmlrpc_value * const defaultMethodInfo, - const char * const methodName, - xmlrpc_value * const paramArrayP, - xmlrpc_value ** const resultPP) { - - xmlrpc_default_method default_method; - void * user_data; - - xmlrpc_parse_value(envP, defaultMethodInfo, "(pp)", - &default_method, &user_data); - - if (!envP->fault_occurred) - *resultPP = (*default_method)(envP, NULL, methodName, - paramArrayP, user_data); -} - - - -static void -callNamedMethod(xmlrpc_env * const envP, - xmlrpc_value * const methodInfo, - xmlrpc_value * const paramArrayP, - xmlrpc_value ** const resultPP) { - - xmlrpc_method method; - void * user_data; - - xmlrpc_parse_value(envP, methodInfo, "(pp*)", &method, &user_data); - if (!envP->fault_occurred) - *resultPP = (*method)(envP, paramArrayP, user_data); -} - - - -static void -dispatch_call(xmlrpc_env * const envP, - xmlrpc_registry * const registryP, - const char * const methodName, - xmlrpc_value * const paramArrayP, - xmlrpc_value ** const resultPP) { - - callPreinvokeMethodIfAny(envP, registryP, methodName, paramArrayP); - if (!envP->fault_occurred) { - xmlrpc_value * method_info; - - /* Look up the method info for the named method. */ - xmlrpc_struct_find_value(envP, registryP->_methods, - methodName, &method_info); - if (!envP->fault_occurred) { - if (method_info) { - callNamedMethod(envP, method_info, paramArrayP, resultPP); - xmlrpc_DECREF(method_info); - } else { - if (registryP->_default_method) - callDefaultMethod(envP, registryP->_default_method, - methodName, paramArrayP, - resultPP); - 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 -**========================================================================= -** -*/ - -xmlrpc_mem_block * -xmlrpc_registry_process_call(xmlrpc_env * const envP, - xmlrpc_registry * const registryP, - const char * const host ATTR_UNUSED, - const char * const xml_data, - size_t const xml_len) { - - xmlrpc_mem_block * output; - - XMLRPC_ASSERT_ENV_OK(envP); - XMLRPC_ASSERT_PTR_OK(xml_data); - - xmlrpc_traceXml("XML-RPC CALL", xml_data, xml_len); - - /* Allocate our output buffer. - ** If this fails, we need to die in a special fashion. */ - output = XMLRPC_MEMBLOCK_NEW(char, envP, 0); - if (!envP->fault_occurred) { - const char * methodName; - xmlrpc_value * paramArray; - xmlrpc_env fault; - - xmlrpc_env_init(&fault); - - xmlrpc_parse_call(&fault, xml_data, xml_len, - &methodName, ¶mArray); - - if (!fault.fault_occurred) { - xmlrpc_value * result; - - dispatch_call(&fault, registryP, methodName, paramArray, &result); - - if (!fault.fault_occurred) { - xmlrpc_serialize_response(envP, output, result); - - /* A comment here used to say that - xmlrpc_serialize_response() could fail and "leave - stuff in the buffer." Don't know what that means, - but it sounds like something that needs to be - fixed. The old code aborted the program here if - xmlrpc_serialize_repsonse() failed. 04.11.17 - */ - xmlrpc_DECREF(result); - } - xmlrpc_strfree(methodName); - xmlrpc_DECREF(paramArray); - } - if (!envP->fault_occurred && fault.fault_occurred) - xmlrpc_serialize_fault(envP, output, &fault); - - xmlrpc_env_clean(&fault); - - if (envP->fault_occurred) - XMLRPC_MEMBLOCK_FREE(char, output); - else - xmlrpc_traceXml("XML-RPC RESPONSE", - XMLRPC_MEMBLOCK_CONTENTS(char, output), - XMLRPC_MEMBLOCK_SIZE(char, output)); - } - return output; -} - - - -/*========================================================================= -** system.multicall -**========================================================================= -** Low-tech support for transparent, boxed methods. -*/ - -static char *multicall_help = -"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."; - -static xmlrpc_value * -call_one_method(xmlrpc_env *env, xmlrpc_registry *registry, - xmlrpc_value *method_info) { - - xmlrpc_value *result_val, *result; - char *method_name; - xmlrpc_value *param_array; - - /* Error-handling preconditions. */ - result = result_val = NULL; - - /* Extract our method name and parameters. */ - xmlrpc_parse_value(env, method_info, "{s:s,s:A,*}", - "methodName", &method_name, - "params", ¶m_array); - XMLRPC_FAIL_IF_FAULT(env); - - /* Watch out for a deep recursion attack. */ - if (strcmp(method_name, "system.multicall") == 0) - XMLRPC_FAIL(env, XMLRPC_REQUEST_REFUSED_ERROR, - "Recursive system.multicall strictly forbidden"); - - /* Perform the call. */ - dispatch_call(env, registry, method_name, param_array, &result_val); - XMLRPC_FAIL_IF_FAULT(env); - - /* Build our one-item result array. */ - result = xmlrpc_build_value(env, "(V)", result_val); - XMLRPC_FAIL_IF_FAULT(env); - - cleanup: - if (result_val) - xmlrpc_DECREF(result_val); - if (env->fault_occurred) { - if (result) - xmlrpc_DECREF(result); - return NULL; - } - return result; -} - - - -static xmlrpc_value * -system_multicall(xmlrpc_env *env, - xmlrpc_value *param_array, - void *user_data) { - - xmlrpc_registry *registry; - xmlrpc_value *methlist, *methinfo, *results, *result; - size_t size, i; - xmlrpc_env env2; - - XMLRPC_ASSERT_ENV_OK(env); - XMLRPC_ASSERT_VALUE_OK(param_array); - XMLRPC_ASSERT_PTR_OK(user_data); - - /* Error-handling preconditions. */ - results = result = NULL; - xmlrpc_env_init(&env2); - - /* Turn our arguments into something more useful. */ - registry = (xmlrpc_registry*) user_data; - xmlrpc_parse_value(env, param_array, "(A)", &methlist); - XMLRPC_FAIL_IF_FAULT(env); - - /* Create an empty result list. */ - results = xmlrpc_build_value(env, "()"); - XMLRPC_FAIL_IF_FAULT(env); - - /* Loop over our input list, calling each method in turn. */ - size = xmlrpc_array_size(env, methlist); - XMLRPC_ASSERT_ENV_OK(env); - for (i = 0; i < size; i++) { - methinfo = xmlrpc_array_get_item(env, methlist, i); - XMLRPC_ASSERT_ENV_OK(env); - - /* Call our method. */ - xmlrpc_env_clean(&env2); - xmlrpc_env_init(&env2); - result = call_one_method(&env2, registry, methinfo); - - /* Turn any fault into a structure. */ - if (env2.fault_occurred) { - XMLRPC_ASSERT(result == NULL); - result = - xmlrpc_build_value(env, "{s:i,s:s}", - "faultCode", (xmlrpc_int32) env2.fault_code, - "faultString", env2.fault_string); - XMLRPC_FAIL_IF_FAULT(env); - } - - /* Append this method result to our master array. */ - xmlrpc_array_append_item(env, results, result); - xmlrpc_DECREF(result); - result = NULL; - XMLRPC_FAIL_IF_FAULT(env); - } - - cleanup: - xmlrpc_env_clean(&env2); - if (result) - xmlrpc_DECREF(result); - if (env->fault_occurred) { - if (results) - xmlrpc_DECREF(results); - return NULL; - } - return results; -} - - - -/*========================================================================= -** system.listMethods -**========================================================================= -** List all available methods by name. -*/ - -static char *listMethods_help = -"Return an array of all available XML-RPC methods on this server."; - -static xmlrpc_value * -system_listMethods(xmlrpc_env *env, - xmlrpc_value *param_array, - void *user_data) { - - xmlrpc_registry *registry; - xmlrpc_value *method_names, *method_name, *method_info; - size_t size, i; - - XMLRPC_ASSERT_ENV_OK(env); - XMLRPC_ASSERT_VALUE_OK(param_array); - XMLRPC_ASSERT_PTR_OK(user_data); - - /* Error-handling preconditions. */ - method_names = NULL; - - /* Turn our arguments into something more useful. */ - registry = (xmlrpc_registry*) user_data; - xmlrpc_parse_value(env, param_array, "()"); - XMLRPC_FAIL_IF_FAULT(env); - - /* Make sure we're allowed to introspect. */ - if (!registry->_introspection_enabled) - XMLRPC_FAIL(env, XMLRPC_INTROSPECTION_DISABLED_ERROR, - "Introspection disabled for security reasons"); - - /* Iterate over all the methods in the registry, adding their names - ** to a list. */ - method_names = xmlrpc_build_value(env, "()"); - XMLRPC_FAIL_IF_FAULT(env); - size = xmlrpc_struct_size(env, registry->_methods); - XMLRPC_FAIL_IF_FAULT(env); - for (i = 0; i < size; i++) { - xmlrpc_struct_get_key_and_value(env, registry->_methods, i, - &method_name, &method_info); - XMLRPC_FAIL_IF_FAULT(env); - xmlrpc_array_append_item(env, method_names, method_name); - XMLRPC_FAIL_IF_FAULT(env); - } - - cleanup: - if (env->fault_occurred) { - if (method_names) - xmlrpc_DECREF(method_names); - return NULL; - } - return method_names; -} - - - -/*========================================================================= -** system.methodHelp -**========================================================================= -** Get the help string for a particular method. -*/ - -static char *methodHelp_help = -"Given the name of a method, return a help string."; - -static xmlrpc_value * -system_methodHelp(xmlrpc_env *env, - xmlrpc_value *param_array, - void *user_data) { - - xmlrpc_registry *registry; - char *method_name; - xmlrpc_value *ignored1, *ignored2, *ignored3, *help; - - XMLRPC_ASSERT_ENV_OK(env); - XMLRPC_ASSERT_VALUE_OK(param_array); - XMLRPC_ASSERT_PTR_OK(user_data); - - /* Turn our arguments into something more useful. */ - registry = (xmlrpc_registry*) user_data; - xmlrpc_parse_value(env, param_array, "(s)", &method_name); - XMLRPC_FAIL_IF_FAULT(env); - - /* Make sure we're allowed to introspect. */ - if (!registry->_introspection_enabled) - XMLRPC_FAIL(env, XMLRPC_INTROSPECTION_DISABLED_ERROR, - "Introspection disabled for security reasons"); - - /* Get our documentation string. */ - xmlrpc_parse_value(env, registry->_methods, "{s:(VVVV*),*}", - method_name, &ignored1, &ignored2, &ignored3, &help); - XMLRPC_FAIL_IF_FAULT(env); - - cleanup: - if (env->fault_occurred) - return NULL; - xmlrpc_INCREF(help); - return help; -} - - - -/*========================================================================= -** system.methodSignature -**========================================================================= -** Return an array of arrays describing possible signatures for this -** method. -** -** XXX - This is the ugliest function in the entire library. -*/ - -static char *methodSignature_help = -"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."; - -static char *bad_sig_str = -"Application has incorrect method signature information"; - -#define BAD_SIG(env) \ - XMLRPC_FAIL((env), XMLRPC_INTERNAL_ERROR, bad_sig_str); - -static xmlrpc_value * -system_methodSignature(xmlrpc_env *env, - xmlrpc_value *param_array, - void *user_data) { - - xmlrpc_registry *registry; - char *method_name; - xmlrpc_value *ignored1, *ignored2, *ignored3; - xmlrpc_value *item, *current, *result; - int at_sig_start; - char *sig, *code; - - XMLRPC_ASSERT_ENV_OK(env); - XMLRPC_ASSERT_VALUE_OK(param_array); - XMLRPC_ASSERT_PTR_OK(user_data); - - /* Error-handling preconditions. */ - item = current = result = NULL; - - /* Turn our arguments into something more useful. */ - registry = (xmlrpc_registry*) user_data; - xmlrpc_parse_value(env, param_array, "(s)", &method_name); - XMLRPC_FAIL_IF_FAULT(env); - - /* Make sure we're allowed to introspect. */ - if (!registry->_introspection_enabled) - XMLRPC_FAIL(env, XMLRPC_INTROSPECTION_DISABLED_ERROR, - "Introspection disabled for security reasons"); - - /* Get our signature string. */ - xmlrpc_parse_value(env, registry->_methods, "{s:(VVsV*),*}", - method_name, &ignored1, &ignored2, &sig, &ignored3); - XMLRPC_FAIL_IF_FAULT(env); - - if (sig[0] == '?' && sig[1] == '\0') { - /* No signature supplied. */ - result = xmlrpc_build_value(env, "s", "undef"); - XMLRPC_FAIL_IF_FAULT(env); - } else { - /* Build an array of arrays. */ - current = xmlrpc_build_value(env, "()"); - XMLRPC_FAIL_IF_FAULT(env); - result = xmlrpc_build_value(env, "(V)", current); - XMLRPC_FAIL_IF_FAULT(env); - at_sig_start = 1; - - do { - next_loop: - - /* Process the current code. */ - switch (*(sig++)) { - case 'i': code = "int"; break; - case 'b': code = "boolean"; break; - case 'd': code = "double"; break; - case 's': code = "string"; break; - case '8': code = "dateTime.iso8601"; break; - case '6': code = "base64"; break; - case 'S': code = "struct"; break; - case 'A': code = "array"; break; - - case ',': - /* Start a new signature array. */ - if (at_sig_start) - BAD_SIG(env); - xmlrpc_DECREF(current); - current = xmlrpc_build_value(env, "()"); - XMLRPC_FAIL_IF_FAULT(env); - xmlrpc_array_append_item(env, result, current); - XMLRPC_FAIL_IF_FAULT(env); - at_sig_start = 1; - goto next_loop; - - default: - BAD_SIG(env); - } - - /* Append the appropriate string to our current signature. */ - item = xmlrpc_build_value(env, "s", code); - XMLRPC_FAIL_IF_FAULT(env); - xmlrpc_array_append_item(env, current, item); - xmlrpc_DECREF(item); - item = NULL; - XMLRPC_FAIL_IF_FAULT(env); - - /* Advance to the next code, and skip over ':' if necessary. */ - if (at_sig_start) { - if (*sig != ':') - BAD_SIG(env); - sig++; - at_sig_start = 0; - } - - } while (*sig != '\0'); - } - - cleanup: - if (item) - xmlrpc_DECREF(item); - if (current) - xmlrpc_DECREF(current); - if (env->fault_occurred) { - if (result) - xmlrpc_DECREF(result); - return NULL; - } - return result; -} - - - -/*========================================================================= -** install_system_methods -**========================================================================= -** Install the standard methods under system.*. -** This particular function is highly experimental, and may disappear -** without warning. -*/ - -static void -install_system_methods(xmlrpc_env *env, xmlrpc_registry *registry) { - - xmlrpc_registry_add_method_w_doc(env, registry, NULL, - "system.listMethods", - &system_listMethods, registry, - "A:", listMethods_help); - XMLRPC_FAIL_IF_FAULT(env); - xmlrpc_registry_add_method_w_doc(env, registry, NULL, - "system.methodSignature", - &system_methodSignature, registry, - "A:s", methodSignature_help); - XMLRPC_FAIL_IF_FAULT(env); - xmlrpc_registry_add_method_w_doc(env, registry, NULL, - "system.methodHelp", - &system_methodHelp, registry, - "s:s", methodHelp_help); - XMLRPC_FAIL_IF_FAULT(env); - xmlrpc_registry_add_method_w_doc(env, registry, NULL, - "system.multicall", - &system_multicall, registry, - "A:A", multicall_help); - XMLRPC_FAIL_IF_FAULT(env); - - cleanup: - return; -} diff --git a/libs/xmlrpc-c/src/xmlrpc_serialize.c b/libs/xmlrpc-c/src/xmlrpc_serialize.c index 3ca64dd..78bbc10 100644 --- a/libs/xmlrpc-c/src/xmlrpc_serialize.c +++ b/libs/xmlrpc-c/src/xmlrpc_serialize.c @@ -4,9 +4,9 @@ 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. + everywhere else. We could use the C99 standard macro PRId64 for that, + but on at least one 64-bit-long GNU compiler, PRId64 is "ld", which is + considered to be incompatible with long long. So we have XMLRPC_PRId64. */ #include "xmlrpc_config.h" @@ -26,8 +26,9 @@ #include "double.h" #define CRLF "\015\012" -#define SMALL_BUFFER_SZ (128) #define XML_PROLOGUE ""CRLF +#define APACHE_URL "http://ws.apache.org/xmlrpc/namespaces/extensions" +#define XMLNS_APACHE "xmlns:ex=\"" APACHE_URL "\"" static void @@ -54,26 +55,31 @@ formatOut(xmlrpc_env * const envP, particular, do NOT use this routine to print XML-RPC string values! -----------------------------------------------------------------------------*/ va_list args; - char buffer[SMALL_BUFFER_SZ]; - int count; + char buffer[128]; + int rc; XMLRPC_ASSERT_ENV_OK(envP); va_start(args, formatString); - count = XMLRPC_VSNPRINTF(buffer, SMALL_BUFFER_SZ, formatString, args); + rc = XMLRPC_VSNPRINTF(buffer, sizeof(buffer), 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 NUL. */ + /* Old vsnprintf() (and Windows) fails with return value -1 if the full + string doesn't fit in the buffer. New vsnprintf() puts whatever will + fit in the buffer, and returns the length of the full string + regardless. For us, this truncation is a failure. + */ - if (count < 0 || count >= (SMALL_BUFFER_SZ - 1)) + if (rc < 0) xmlrpc_faultf(envP, "formatOut() overflowed internal buffer"); - else - XMLRPC_MEMBLOCK_APPEND(char, envP, outputP, buffer, count); + else { + unsigned int const formattedLen = rc; + if (formattedLen + 1 >= (sizeof(buffer))) + xmlrpc_faultf(envP, "formatOut() overflowed internal buffer"); + else + XMLRPC_MEMBLOCK_APPEND(char, envP, outputP, buffer, formattedLen); + } va_end(args); } @@ -271,6 +277,74 @@ xmlrpc_serialize_base64_data(xmlrpc_env * const envP, +static void +serializeDatetime(xmlrpc_env * const envP, + xmlrpc_mem_block * const outputP, + xmlrpc_value * const valueP) { +/*---------------------------------------------------------------------------- + Add to *outputP the content of a element to represent + the datetime value *valueP. I.e. + " ... ". +-----------------------------------------------------------------------------*/ + + addString(envP, outputP, ""); + if (!envP->fault_occurred) { + char dtString[64]; + + snprintf(dtString, sizeof(dtString), + "%u%02u%02uT%02u:%02u:%02u", + valueP->_value.dt.Y, + valueP->_value.dt.M, + valueP->_value.dt.D, + valueP->_value.dt.h, + valueP->_value.dt.m, + valueP->_value.dt.s); + + if (valueP->_value.dt.u != 0) { + char usecString[64]; + assert(valueP->_value.dt.u < 1000000); + snprintf(usecString, sizeof(usecString), ".%06u", + valueP->_value.dt.u); + STRSCAT(dtString, usecString); + } + addString(envP, outputP, dtString); + + if (!envP->fault_occurred) { + addString(envP, outputP, ""); + } + } +} + + + +static void +serializeStructMember(xmlrpc_env * const envP, + xmlrpc_mem_block * const outputP, + xmlrpc_value * const memberKeyP, + xmlrpc_value * const memberValueP, + xmlrpc_dialect const dialect) { + + addString(envP, outputP, ""); + + if (!envP->fault_occurred) { + serializeUtf8MemBlock(envP, outputP, &memberKeyP->_block); + + if (!envP->fault_occurred) { + addString(envP, outputP, ""CRLF); + + if (!envP->fault_occurred) { + xmlrpc_serialize_value2(envP, outputP, memberValueP, dialect); + + if (!envP->fault_occurred) { + addString(envP, outputP, ""CRLF); + } + } + } + } +} + + + static void serializeStruct(xmlrpc_env * const envP, xmlrpc_mem_block * const outputP, @@ -280,37 +354,25 @@ serializeStruct(xmlrpc_env * const envP, Add to *outputP the content of a element to represent the structure value *valueP. I.e. " ... ". -----------------------------------------------------------------------------*/ - size_t size; - size_t i; - xmlrpc_value * memberKeyP; - xmlrpc_value * memberValueP; - addString(envP, outputP, ""CRLF); - XMLRPC_FAIL_IF_FAULT(envP); - - 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, ""); - XMLRPC_FAIL_IF_FAULT(envP); - serializeUtf8MemBlock(envP, outputP, &memberKeyP->_block); - XMLRPC_FAIL_IF_FAULT(envP); - addString(envP, outputP, ""CRLF); - XMLRPC_FAIL_IF_FAULT(envP); - xmlrpc_serialize_value2(envP, outputP, memberValueP, dialect); - XMLRPC_FAIL_IF_FAULT(envP); - addString(envP, outputP, ""CRLF); - XMLRPC_FAIL_IF_FAULT(envP); - } - - addString(envP, outputP, ""); - XMLRPC_FAIL_IF_FAULT(envP); + if (!envP->fault_occurred) { + unsigned int const size = xmlrpc_struct_size(envP, structP); + if (!envP->fault_occurred) { + unsigned int i; + for (i = 0; i < size && !envP->fault_occurred; ++i) { + xmlrpc_value * memberKeyP; + xmlrpc_value * memberValueP; -cleanup: - return; + xmlrpc_struct_get_key_and_value(envP, structP, i, + &memberKeyP, &memberValueP); + if (!envP->fault_occurred) { + serializeStructMember(envP, outputP, + memberKeyP, memberValueP, dialect); + } + } + addString(envP, outputP, "
"); + } + } } @@ -366,7 +428,7 @@ formatValueContent(xmlrpc_env * const envP, case XMLRPC_TYPE_I8: { const char * const elemName = - dialect == xmlrpc_dialect_apache ? "ex.i8" : "i8"; + dialect == xmlrpc_dialect_apache ? "ex:i8" : "i8"; formatOut(envP, outputP, "<%s>%" PRId64 "", elemName, valueP->_value.i8, elemName); } break; @@ -391,13 +453,7 @@ formatValueContent(xmlrpc_env * const envP, } break; case XMLRPC_TYPE_DATETIME: - addString(envP, outputP, ""); - if (!envP->fault_occurred) { - serializeUtf8MemBlock(envP, outputP, &valueP->_block); - if (!envP->fault_occurred) { - addString(envP, outputP, ""); - } - } + serializeDatetime(envP, outputP, valueP); break; case XMLRPC_TYPE_STRING: @@ -436,7 +492,7 @@ formatValueContent(xmlrpc_env * const envP, case XMLRPC_TYPE_NIL: { const char * const elemName = - dialect == xmlrpc_dialect_apache ? "ex.nil" : "nil"; + dialect == xmlrpc_dialect_apache ? "ex:nil" : "nil"; formatOut(envP, outputP, "<%s/>", elemName); } break; @@ -502,9 +558,9 @@ xmlrpc_serialize_params2(xmlrpc_env * const envP, addString(envP, outputP, ""CRLF); if (!envP->fault_occurred) { /* Serialize each parameter. */ - size_t const paramCount = xmlrpc_array_size(envP, paramArrayP); + int const paramCount = xmlrpc_array_size(envP, paramArrayP); if (!envP->fault_occurred) { - size_t paramSeq; + int paramSeq; for (paramSeq = 0; paramSeq < paramCount && !envP->fault_occurred; ++paramSeq) { @@ -567,7 +623,9 @@ xmlrpc_serialize_call2(xmlrpc_env * const envP, addString(envP, outputP, XML_PROLOGUE); if (!envP->fault_occurred) { - addString(envP, outputP, ""CRLF""); + const char * const xmlns = + dialect == xmlrpc_dialect_apache ? " " XMLNS_APACHE : ""; + formatOut(envP, outputP, ""CRLF"", xmlns); if (!envP->fault_occurred) { xmlrpc_mem_block * encodedP; escapeForXml(envP, methodName, strlen(methodName), &encodedP); @@ -623,8 +681,10 @@ xmlrpc_serialize_response2(xmlrpc_env * const envP, addString(envP, outputP, XML_PROLOGUE); if (!envP->fault_occurred) { - addString(envP, outputP, - ""CRLF""CRLF""); + const char * const xmlns = + dialect == xmlrpc_dialect_apache ? " " XMLNS_APACHE : ""; + formatOut(envP, outputP, + ""CRLF""CRLF"", xmlns); if (!envP->fault_occurred) { xmlrpc_serialize_value2(envP, outputP, valueP, dialect); if (!envP->fault_occurred) { diff --git a/libs/xmlrpc-c/src/xmlrpc_server_abyss.c b/libs/xmlrpc-c/src/xmlrpc_server_abyss.c index 7cb1ae1..8471c4c 100644 --- a/libs/xmlrpc-c/src/xmlrpc_server_abyss.c +++ b/libs/xmlrpc-c/src/xmlrpc_server_abyss.c @@ -2,6 +2,8 @@ #include "xmlrpc_config.h" +#define _XOPEN_SOURCE 600 /* For strdup(), sigaction */ + #include #include #include @@ -39,17 +41,12 @@ struct xmlrpc_server_abyss { -/*========================================================================= -** die_if_fault_occurred -**========================================================================= -** If certain kinds of out-of-memory errors occur during server setup, -** we want to quit and print an error. -*/ +static void +dieIfFaultOccurred(xmlrpc_env * const envP) { -static void die_if_fault_occurred(xmlrpc_env *env) { - if (env->fault_occurred) { + if (envP->fault_occurred) { fprintf(stderr, "Unexpected XML-RPC fault: %s (%d)\n", - env->fault_string, env->fault_code); + envP->fault_string, envP->fault_code); exit(1); } } @@ -135,7 +132,7 @@ addAuthCookie(xmlrpc_env * const envP, xmlrpc_asprintf(&cookieResponse, "auth=%s", authCookie); - if (cookieResponse == xmlrpc_strsol) + if (xmlrpc_strnomem(cookieResponse)) xmlrpc_faultf(envP, "Insufficient memory to generate cookie " "response header."); else { @@ -148,11 +145,12 @@ addAuthCookie(xmlrpc_env * const envP, static void -sendXmlData(xmlrpc_env * const envP, - TSession * const abyssSessionP, - const char * const body, - size_t const len, - bool const chunked) { +sendResponse(xmlrpc_env * const envP, + TSession * const abyssSessionP, + const char * const body, + size_t const len, + bool const chunked, + ResponseAccessCtl const accessControl) { /*---------------------------------------------------------------------------- Generate an HTTP response containing body 'body' of length 'len' characters. @@ -191,17 +189,39 @@ sendXmlData(xmlrpc_env * const envP, else { uint32_t const abyssLen = (uint32_t)len; - ResponseContentType(abyssSessionP, "text/xml; charset=\"utf-8\""); + /* See discussion below of quotes around "utf-8" */ + ResponseContentType(abyssSessionP, "text/xml"); ResponseContentLength(abyssSessionP, abyssLen); + ResponseAccessControl(abyssSessionP, accessControl); - ResponseWriteStart(abyssSessionP); - ResponseWriteBody(abyssSessionP, body, abyssLen); - ResponseWriteEnd(abyssSessionP); + if (ResponseWriteStart(abyssSessionP)) + if (ResponseWriteBody(abyssSessionP, body, abyssLen)) + if (ResponseWriteEnd(abyssSessionP)) + return; + + xmlrpc_faultf(envP, "socket send() problem"); } } +/* From 0.9.10 (May 2001) through 1.17 (December 2008), the content-type + header said charset="utf-8" (i.e. with the value of 'charset' an HTTP quoted + string). Before 0.9.10, the header didn't have charset at all. + + We got a complaint in January 2009 that some client didn't understand that, + saying + + apache2: XML-RPC: xmlrpcmsg::parseResponse: invalid charset encoding of + received response: "UTF-8" + + And that removing the quotation marks fixes this. + + From what I can tell, the module is wrong to distinguish between the + two, but I don't think it hurts anything to use a basic HTTP token instead + of an HTTP quoted string here, so starting in 1.18, we do. */ + + static void sendError(TSession * const abyssSessionP, unsigned int const status, @@ -287,9 +307,8 @@ getBody(xmlrpc_env * const envP, } if (envP->fault_occurred) xmlrpc_mem_block_free(body); - else - *bodyP = body; } + *bodyP = body; } @@ -320,44 +339,6 @@ storeCookies(TSession * const httpRequestP, static void -validateContentType(TSession * const httpRequestP, - const char ** const errorP) { -/*---------------------------------------------------------------------------- - 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) - xmlrpc_asprintf(errorP, - "You did not supply a content-type HTTP header"); - else { - const char * const sempos = strchr(content_type, ';'); - unsigned int baselen; - /* Length of the base portion of the content type, e.g. - "text/xml" int "text/xml;charset=utf-8" - */ - - if (sempos) - baselen = sempos - content_type; - else - baselen = strlen(content_type); - - 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 - *errorP = NULL; - } -} - - - -static void processContentLength(TSession * const httpRequestP, size_t * const inputLenP, bool * const missingP, @@ -376,6 +357,7 @@ processContentLength(TSession * const httpRequestP, *errorP = NULL; } else { *missingP = FALSE; + *inputLenP = 0; /* quiet compiler warning */ if (content_length[0] == '\0') xmlrpc_asprintf(errorP, "The value in your content-length " "HTTP header value is a null string"); @@ -444,11 +426,13 @@ traceHandlerCalled(TSession * const abyssSessionP) { static void -processCall(TSession * const abyssSessionP, - size_t const contentSize, - xmlrpc_registry * const registryP, - bool const wantChunk, - const char * const trace) { +processCall(TSession * const abyssSessionP, + size_t const contentSize, + xmlrpc_call_processor xmlProcessor, + void * const xmlProcessorArg, + bool const wantChunk, + ResponseAccessCtl const accessControl, + const char * const trace) { /*---------------------------------------------------------------------------- Handle an RPC request. This is an HTTP request that has the proper form to be an XML-RPC call. @@ -469,26 +453,27 @@ processCall(TSession * const abyssSessionP, if (contentSize > xmlrpc_limit_get(XMLRPC_XML_SIZE_LIMIT_ID)) xmlrpc_env_set_fault_formatted( &env, XMLRPC_LIMIT_EXCEEDED_ERROR, - "XML-RPC request too large (%d bytes)", contentSize); + "XML-RPC request too large (%u bytes)", (unsigned)contentSize); else { xmlrpc_mem_block * body = NULL; /* Read XML data off the wire. */ getBody(&env, abyssSessionP, contentSize, trace, &body); if (!env.fault_occurred) { xmlrpc_mem_block * output; + /* Process the RPC. */ - xmlrpc_registry_process_call2( - &env, registryP, + xmlProcessor( + &env, xmlProcessorArg, XMLRPC_MEMBLOCK_CONTENTS(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), - wantChunk); + sendResponse(&env, abyssSessionP, + XMLRPC_MEMBLOCK_CONTENTS(char, output), + XMLRPC_MEMBLOCK_SIZE(char, output), + wantChunk, accessControl); XMLRPC_MEMBLOCK_FREE(char, output); } @@ -510,42 +495,137 @@ processCall(TSession * const abyssSessionP, -/**************************************************************************** - Abyss handlers (to be registered with and called by Abyss) -****************************************************************************/ +static void +processXmlrpcCall(xmlrpc_env * const envP, + void * const arg, + const char * const callXml, + size_t const callXmlLen, + TSession * const abyssSessionP, + xmlrpc_mem_block ** const responseXmlPP) { -static const char * trace_abyss; + xmlrpc_registry * const registryP = arg; + + xmlrpc_registry_process_call2(envP, registryP, + callXml, callXmlLen, abyssSessionP, + responseXmlPP); + +} +static const char * trace_abyss; + + struct uriHandlerXmlrpc { /*---------------------------------------------------------------------------- This is the part of an Abyss HTTP request handler (aka URI handler) that is specific to the Xmlrpc-c handler. -----------------------------------------------------------------------------*/ - xmlrpc_registry * registryP; - const char * uriPath; /* malloc'ed */ - bool chunkResponse; + xmlrpc_registry * registryP; + const char * uriPath; /* malloc'ed */ + bool chunkResponse; /* The handler should chunk its response whenever possible */ + xmlrpc_call_processor * xmlProcessor; + void * xmlProcessorArg; + ResponseAccessCtl accessControl; }; static void +termAccessControl(ResponseAccessCtl * const accessCtlP) { + + xmlrpc_strfreenull(accessCtlP->allowOrigin); +} + + + +static void termUriHandler(void * const arg) { struct uriHandlerXmlrpc * const uriHandlerXmlrpcP = arg; xmlrpc_strfree(uriHandlerXmlrpcP->uriPath); + termAccessControl(&uriHandlerXmlrpcP->accessControl); free(uriHandlerXmlrpcP); } static void -handleXmlrpcReq(URIHandler2 * const this, - TSession * const abyssSessionP, - abyss_bool * const handledP) { +handleXmlRpcCallReq(TSession * const abyssSessionP, + const TRequestInfo * const requestInfoP ATTR_UNUSED, + xmlrpc_call_processor xmlProcessor, + void * const xmlProcessorArg, + bool const wantChunk, + ResponseAccessCtl const accessControl) { +/*---------------------------------------------------------------------------- + Handle the HTTP request described by *requestInfoP, which arrived over + Abyss HTTP session *abyssSessionP, which is an XML-RPC call + (i.e. a POST request to /RPC2 or whatever other URI our server is + supposed to handle). + + Handle it by feeding the XML which is its content to 'xmlProcessor' + along with argument 'xmlProcessorArg'. +-----------------------------------------------------------------------------*/ + /* We used to reject the call if content-type was not present and + text/xml, on some security theory (a firewall may block text/xml with + the intent of blocking XML-RPC. Now, we believe that is silly, and we + have seen an incorrectly implemented client that says text/plain. + */ + const char * error; + + assert(requestInfoP->method == m_post); + + storeCookies(abyssSessionP, &error); + if (error) { + sendError(abyssSessionP, 400, error); + xmlrpc_strfree(error); + } else { + const char * error; + bool missing; + size_t contentSize; + + processContentLength(abyssSessionP, + &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, + xmlProcessor, xmlProcessorArg, + wantChunk, accessControl, + trace_abyss); + } + } +} + + + +static void +handleXmlRpcOptionsReq(TSession * const abyssSessionP, + ResponseAccessCtl const accessControl) { + + ResponseAddField(abyssSessionP, "Allow", "POST"); + + ResponseAccessControl(abyssSessionP, accessControl); + ResponseContentLength(abyssSessionP, 0); + ResponseStatus(abyssSessionP, 200); + if (ResponseWriteStart(abyssSessionP)) + ResponseWriteEnd(abyssSessionP); +} + + + +static void +handleIfXmlrpcReq(void * const handlerArg, + TSession * const abyssSessionP, + abyss_bool * const handledP) { /*---------------------------------------------------------------------------- Our job is to look at this HTTP request that the Abyss server is trying to process and see if we can handle it. If it's an XML-RPC @@ -557,9 +637,9 @@ handleXmlrpcReq(URIHandler2 * const this, Note that failing the request counts as handling it, and not handling it does not mean we failed it. - This is an Abyss HTTP Request handler -- type URIHandler2. + This is an Abyss HTTP Request handler -- type handleReqFn3. -----------------------------------------------------------------------------*/ - struct uriHandlerXmlrpc * const uriHandlerXmlrpcP = this->userdata; + struct uriHandlerXmlrpc * const uriHandlerXmlrpcP = handlerArg; const TRequestInfo * requestInfoP; @@ -571,54 +651,30 @@ handleXmlrpcReq(URIHandler2 * const this, /* Note that requestInfoP->uri is not the whole URI. It is just the "file name" part of it. */ - if (strcmp(requestInfoP->uri, uriHandlerXmlrpcP->uriPath) != 0) - /* It's for the path (e.g. "/RPC2") that we're supposed to + if (!xmlrpc_streq(requestInfoP->uri, uriHandlerXmlrpcP->uriPath)) + /* It's not for the path (e.g. "/RPC2") that we're supposed to handle. */ *handledP = FALSE; else { *handledP = TRUE; - if (requestInfoP->method != m_post) + switch (requestInfoP->method) { + case m_post: + handleXmlRpcCallReq(abyssSessionP, requestInfoP, + uriHandlerXmlrpcP->xmlProcessor, + uriHandlerXmlrpcP->xmlProcessorArg, + uriHandlerXmlrpcP->chunkResponse, + uriHandlerXmlrpcP->accessControl); + break; + case m_options: + handleXmlRpcOptionsReq(abyssSessionP, + uriHandlerXmlrpcP->accessControl); + break; + default: sendError(abyssSessionP, 405, "POST is the only HTTP method this server understands"); /* 405 = Method Not Allowed */ - else { - 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, &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) @@ -626,6 +682,10 @@ handleXmlrpcReq(URIHandler2 * const this, } +/* This doesn't include what the user's method function requires */ +#define HANDLE_XMLRPC_REQ_STACK 1024 + + /*========================================================================= ** xmlrpc_server_abyss_default_handler @@ -664,35 +724,115 @@ xmlrpc_server_abyss_default_handler(TSession * const sessionP) { static void -setHandler(xmlrpc_env * const envP, - TServer * const srvP, - const char * const uriPath, - xmlrpc_registry * const registryP, - bool const chunkResponse) { +setHandler(xmlrpc_env * const envP, + TServer * const srvP, + struct uriHandlerXmlrpc * const uriHandlerXmlrpcP, + size_t const xmlProcessorMaxStackSize) { - struct uriHandlerXmlrpc * uriHandlerXmlrpcP; - URIHandler2 uriHandler; abyss_bool success; trace_abyss = getenv("XMLRPC_TRACE_ABYSS"); - MALLOCVAR_NOFAIL(uriHandlerXmlrpcP); + { + size_t const stackSize = + HANDLE_XMLRPC_REQ_STACK + xmlProcessorMaxStackSize; + struct ServerReqHandler3 const handlerDesc = { + /* .term = */ &termUriHandler, + /* .handleReq = */ &handleIfXmlrpcReq, + /* .userdata = */ uriHandlerXmlrpcP, + /* .handleReqStackSize = */ stackSize + }; + ServerAddHandler3(srvP, &handlerDesc, &success); + } + if (!success) + xmlrpc_faultf(envP, "Abyss failed to register the Xmlrpc-c request " + "handler. ServerAddHandler3() failed."); - uriHandlerXmlrpcP->registryP = registryP; - uriHandlerXmlrpcP->uriPath = strdup(uriPath); - uriHandlerXmlrpcP->chunkResponse = chunkResponse; + if (envP->fault_occurred){ + free((void *)uriHandlerXmlrpcP->uriPath); + free(uriHandlerXmlrpcP); + } +} - 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 +interpretHttpAccessControl( + const xmlrpc_server_abyss_handler_parms * const parmsP, + unsigned int const parmSize, + ResponseAccessCtl * const accessCtlP) { + + if (parmSize >= XMLRPC_AHPSIZE(allow_origin) && parmsP->allow_origin) + accessCtlP->allowOrigin = xmlrpc_strdupsol(parmsP->allow_origin); + else + accessCtlP->allowOrigin = NULL; + + if (parmSize >= XMLRPC_AHPSIZE(access_ctl_expires) + && parmsP->access_ctl_expires) { + accessCtlP->expires = true; + + if (parmSize >= XMLRPC_AHPSIZE(access_ctl_max_age)) + accessCtlP->maxAge = parmsP->access_ctl_max_age; + else + accessCtlP->maxAge = 0; + } +} + + + +void +xmlrpc_server_abyss_set_handler3( + xmlrpc_env * const envP, + TServer * const srvP, + const xmlrpc_server_abyss_handler_parms * const parmsP, + unsigned int const parmSize) { + + struct uriHandlerXmlrpc * uriHandlerXmlrpcP; + size_t xmlProcessorMaxStackSize; + + MALLOCVAR_NOFAIL(uriHandlerXmlrpcP); + + if (!envP->fault_occurred) { + if (parmSize >= XMLRPC_AHPSIZE(xml_processor)) + uriHandlerXmlrpcP->xmlProcessor = parmsP->xml_processor; + else + xmlrpc_faultf(envP, "Parameter too short to contain the required " + "'xml_processor' member"); + } + if (!envP->fault_occurred) { + if (parmSize >= XMLRPC_AHPSIZE(xml_processor_arg)) + uriHandlerXmlrpcP->xmlProcessorArg = parmsP->xml_processor_arg; + else + xmlrpc_faultf(envP, "Parameter too short to contain the required " + "'xml_processor_arg' member"); + } + if (!envP->fault_occurred) { + if (parmSize >= XMLRPC_AHPSIZE(xml_processor_max_stack)) + xmlProcessorMaxStackSize = parmsP->xml_processor_max_stack; + else + xmlrpc_faultf(envP, "Parameter too short to contain the required " + "'xml_processor_max_stack' member"); + } + if (!envP->fault_occurred) { + if (parmSize >= XMLRPC_AHPSIZE(uri_path) && parmsP->uri_path) + uriHandlerXmlrpcP->uriPath = xmlrpc_strdupsol(parmsP->uri_path); + else + uriHandlerXmlrpcP->uriPath = xmlrpc_strdupsol("/RPC2"); + + if (parmSize >= XMLRPC_AHPSIZE(chunk_response) && + parmsP->chunk_response) + uriHandlerXmlrpcP->chunkResponse = parmsP->chunk_response; + else + uriHandlerXmlrpcP->chunkResponse = false; + + interpretHttpAccessControl(parmsP, parmSize, + &uriHandlerXmlrpcP->accessControl); + + if (envP->fault_occurred) + termAccessControl(&uriHandlerXmlrpcP->accessControl); + } + if (!envP->fault_occurred) + setHandler(envP, srvP, uriHandlerXmlrpcP, xmlProcessorMaxStackSize); if (envP->fault_occurred) free(uriHandlerXmlrpcP); @@ -701,36 +841,95 @@ setHandler(xmlrpc_env * const envP, void +xmlrpc_server_abyss_set_handler2( + TServer * const srvP, + const char * const uriPath, + xmlrpc_call_processor xmlProcessor, + void * const xmlProcessorArg, + size_t const xmlProcessorMaxStackSize, + xmlrpc_bool const chunkResponse) { + + xmlrpc_env env; + xmlrpc_server_abyss_handler_parms parms; + + xmlrpc_env_init(&env); + + parms.xml_processor = xmlProcessor; + parms.xml_processor_arg = xmlProcessorArg; + parms.xml_processor_max_stack = xmlProcessorMaxStackSize; + parms.uri_path = uriPath; + parms.chunk_response = chunkResponse; + + xmlrpc_server_abyss_set_handler3(&env, srvP, + &parms, XMLRPC_AHPSIZE(chunk_response)); + + if (env.fault_occurred) + abort(); + + xmlrpc_env_clean(&env); +} + + + +void xmlrpc_server_abyss_set_handler(xmlrpc_env * const envP, TServer * const srvP, const char * const uriPath, xmlrpc_registry * const registryP) { - setHandler(envP, srvP, uriPath, registryP, false); + xmlrpc_server_abyss_handler_parms parms; + + parms.xml_processor = &processXmlrpcCall; + parms.xml_processor_arg = registryP; + parms.xml_processor_max_stack = xmlrpc_registry_max_stackSize(registryP); + parms.uri_path = uriPath; + + xmlrpc_server_abyss_set_handler3(envP, srvP, + &parms, XMLRPC_AHPSIZE(uri_path)); } +void +xmlrpc_server_abyss_set_default_handler(TServer * const srvP) { + + ServerDefaultHandler(srvP, xmlrpc_server_abyss_default_handler); +} + + + static void -setHandlers(TServer * const srvP, - const char * const uriPath, - xmlrpc_registry * const registryP, - bool const chunkResponse) { +setHandlersRegistry(TServer * const srvP, + const char * const uriPath, + xmlrpc_registry * const registryP, + bool const chunkResponse, + const char * const allowOrigin, + bool const expires, + unsigned int const maxAge) { xmlrpc_env env; + xmlrpc_server_abyss_handler_parms parms; xmlrpc_env_init(&env); - trace_abyss = getenv("XMLRPC_TRACE_ABYSS"); - - setHandler(&env, srvP, uriPath, registryP, chunkResponse); + parms.xml_processor = &processXmlrpcCall; + parms.xml_processor_arg = registryP; + parms.xml_processor_max_stack = xmlrpc_registry_max_stackSize(registryP), + parms.uri_path = uriPath; + parms.chunk_response = chunkResponse; + parms.allow_origin = allowOrigin; + parms.access_ctl_expires = expires; + parms.access_ctl_max_age = maxAge; + + xmlrpc_server_abyss_set_handler3( + &env, srvP, &parms, XMLRPC_AHPSIZE(access_ctl_max_age)); if (env.fault_occurred) abort(); - ServerDefaultHandler(srvP, xmlrpc_server_abyss_default_handler); - xmlrpc_env_clean(&env); + + xmlrpc_server_abyss_set_default_handler(srvP); } @@ -740,7 +939,7 @@ xmlrpc_server_abyss_set_handlers2(TServer * const srvP, const char * const uriPath, xmlrpc_registry * const registryP) { - setHandlers(srvP, uriPath, registryP, false); + setHandlersRegistry(srvP, uriPath, registryP, false, NULL, false, 0); } @@ -749,7 +948,7 @@ void xmlrpc_server_abyss_set_handlers(TServer * const srvP, xmlrpc_registry * const registryP) { - setHandlers(srvP, "/RPC2", registryP, false); + setHandlersRegistry(srvP, "/RPC2", registryP, false, NULL, false, 0); } @@ -763,11 +962,6 @@ setAdditionalServerParms(const xmlrpc_server_abyss_parms * const parmsP, unsigned int const parmSize, TServer * const serverP) { - /* 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 (parmSize >= XMLRPC_APSIZE(keepalive_timeout) && parmsP->keepalive_timeout > 0) ServerSetKeepaliveTimeout(serverP, parmsP->keepalive_timeout); @@ -903,8 +1097,13 @@ createServerBare(xmlrpc_env * const envP, createServerBoundSocket(envP, socketFd, logFileName, serverP, chanSwitchPP); else { - ServerCreate(serverP, "XmlRpcServer", portNumber, DEFAULT_DOCS, - logFileName); + abyss_bool success; + + success = ServerCreate(serverP, "XmlRpcServer", portNumber, + DEFAULT_DOCS, logFileName); + + if (!success) + xmlrpc_faultf(envP, "Failed to create an Abyss server object"); *chanSwitchPP = NULL; } @@ -915,6 +1114,22 @@ createServerBare(xmlrpc_env * const envP, +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 bool chunkResponseParm(const xmlrpc_server_abyss_parms * const parmsP, unsigned int const parmSize) { @@ -927,18 +1142,35 @@ chunkResponseParm(const xmlrpc_server_abyss_parms * const parmsP, static const char * -uriPathParm(const xmlrpc_server_abyss_parms * const parmsP, +allowOriginParm(const xmlrpc_server_abyss_parms * const parmsP, + unsigned int const parmSize) { + + return + parmSize >= XMLRPC_APSIZE(allow_origin) ? + parmsP->allow_origin : NULL; +} + + + +static bool +expiresParm(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 + parmSize >= XMLRPC_APSIZE(access_ctl_expires) ? + parmsP->access_ctl_expires : false; +} - return uriPath; -} + + +static unsigned int +maxAgeParm(const xmlrpc_server_abyss_parms * const parmsP, + unsigned int const parmSize) { + + return + parmSize >= XMLRPC_APSIZE(access_ctl_max_age) ? + parmsP->access_ctl_max_age : 0; +} @@ -954,9 +1186,12 @@ createServer(xmlrpc_env * const envP, if (!envP->fault_occurred) { setAdditionalServerParms(parmsP, parmSize, abyssServerP); - setHandlers(abyssServerP, uriPathParm(parmsP, parmSize), - parmsP->registryP, - chunkResponseParm(parmsP, parmSize)); + setHandlersRegistry(abyssServerP, uriPathParm(parmsP, parmSize), + parmsP->registryP, + chunkResponseParm(parmsP, parmSize), + allowOriginParm(parmsP, parmSize), + expiresParm(parmsP, parmSize), + maxAgeParm(parmsP, parmSize)); ServerInit(abyssServerP); } @@ -1030,9 +1265,9 @@ xmlrpc_server_abyss_create(xmlrpc_env * const envP, 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 " + "That would mean the parameter size would be >= %u " "but you specified a size of %u", - XMLRPC_APSIZE(registryP), parmSize); + (unsigned)XMLRPC_APSIZE(registryP), parmSize); else { MALLOCVAR(serverP); @@ -1123,9 +1358,11 @@ sigchld(int const signalClass ATTR_UNUSED) { 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. + signal on to the Abyss server. And reaping the dead child. -----------------------------------------------------------------------------*/ #ifndef WIN32 + /* Reap zombie children / report to Abyss until there aren't any more. */ + bool childrenLeft; bool error; @@ -1270,7 +1507,7 @@ runServerDaemon(TServer * const serverP, static void -oldHighLevelAbyssRun(xmlrpc_env * const envP ATTR_UNUSED, +oldHighLevelAbyssRun(xmlrpc_env * const envP, const xmlrpc_server_abyss_parms * const parmsP, unsigned int const parmSize) { /*---------------------------------------------------------------------------- @@ -1285,31 +1522,38 @@ oldHighLevelAbyssRun(xmlrpc_env * const envP ATTR_UNUSED, flexible API. -----------------------------------------------------------------------------*/ TServer server; - runfirstFn runfirst; - void * runfirstArg; - - ServerCreate(&server, "XmlRpcServer", 8080, DEFAULT_DOCS, NULL); + abyss_bool success; - assert(parmSize >= XMLRPC_APSIZE(config_file_name)); + success = ServerCreate(&server, "XmlRpcServer", 8080, DEFAULT_DOCS, NULL); + + if (!success) + xmlrpc_faultf(envP, "Failed to create Abyss server object"); + else { + runfirstFn runfirst; + void * runfirstArg; + + assert(parmSize >= XMLRPC_APSIZE(config_file_name)); - ConfReadServerFile(parmsP->config_file_name, &server); + ConfReadServerFile(parmsP->config_file_name, &server); - assert(parmSize >= XMLRPC_APSIZE(registryP)); + assert(parmSize >= XMLRPC_APSIZE(registryP)); - setHandlers(&server, "/RPC2", parmsP->registryP, false); + setHandlersRegistry(&server, "/RPC2", parmsP->registryP, false, NULL, + false, 0); - ServerInit(&server); + ServerInit(&server); - if (parmSize >= XMLRPC_APSIZE(runfirst_arg)) { - runfirst = parmsP->runfirst; - runfirstArg = parmsP->runfirst_arg; - } else { - runfirst = NULL; - runfirstArg = NULL; - } - runServerDaemon(&server, runfirst, runfirstArg); + if (parmSize >= XMLRPC_APSIZE(runfirst_arg)) { + runfirst = parmsP->runfirst; + runfirstArg = parmsP->runfirst_arg; + } else { + runfirst = NULL; + runfirstArg = NULL; + } + runServerDaemon(&server, runfirst, runfirstArg); - ServerFree(&server); + ServerFree(&server); + } } @@ -1351,7 +1595,7 @@ xmlrpc_server_abyss(xmlrpc_env * const envP, 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 + xmlrpc_server_abyss_global_init() early in your program, when it is only one thread. -----------------------------------------------------------------------------*/ XMLRPC_ASSERT_ENV_OK(envP); @@ -1363,9 +1607,9 @@ xmlrpc_server_abyss(xmlrpc_env * const envP, 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 " + "That would mean the parameter size would be >= %u " "but you specified a size of %u", - XMLRPC_APSIZE(registryP), parmSize); + (unsigned)XMLRPC_APSIZE(registryP), parmSize); else { if (parmsP->config_file_name) oldHighLevelAbyssRun(envP, parmsP, parmSize); @@ -1416,10 +1660,11 @@ xmlrpc_server_abyss_init_registry(void) { xmlrpc_env_init(&env); builtin_registryP = xmlrpc_registry_new(&env); - die_if_fault_occurred(&env); + dieIfFaultOccurred(&env); xmlrpc_env_clean(&env); - setHandlers(&globalSrv, "/RPC2", builtin_registryP, false); + setHandlersRegistry(&globalSrv, "/RPC2", builtin_registryP, false, NULL, + false, 0); } @@ -1446,7 +1691,7 @@ xmlrpc_server_abyss_add_method(char * const method_name, xmlrpc_env_init(&env); xmlrpc_registry_add_method(&env, builtin_registryP, NULL, method_name, method, user_data); - die_if_fault_occurred(&env); + dieIfFaultOccurred(&env); xmlrpc_env_clean(&env); } @@ -1464,7 +1709,7 @@ xmlrpc_server_abyss_add_method_w_doc(char * const method_name, xmlrpc_registry_add_method_w_doc( &env, builtin_registryP, NULL, method_name, method, user_data, signature, help); - die_if_fault_occurred(&env); + dieIfFaultOccurred(&env); xmlrpc_env_clean(&env); } @@ -1474,16 +1719,23 @@ 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); + abyss_bool success; - xmlrpc_server_abyss_init_registry(); - /* Installs /RPC2 handler and default handler that use the - built-in registry. - */ + success = ServerCreate(&globalSrv, "XmlRpcServer", 8080, + DEFAULT_DOCS, NULL); - ServerInit(&globalSrv); + if (!success) + abort(); + else { + ConfReadServerFile(config_file, &globalSrv); + + xmlrpc_server_abyss_init_registry(); + /* Installs /RPC2 handler and default handler that use the + built-in registry. + */ + + ServerInit(&globalSrv); + } } diff --git a/libs/xmlrpc-c/src/xmlrpc_server_cgi.c b/libs/xmlrpc-c/src/xmlrpc_server_cgi.c index 2f6fe73..f8ab73a 100644 --- a/libs/xmlrpc-c/src/xmlrpc_server_cgi.c +++ b/libs/xmlrpc-c/src/xmlrpc_server_cgi.c @@ -38,6 +38,7 @@ #include "xmlrpc-c/base.h" #include "xmlrpc-c/server.h" +#include "xmlrpc-c/string_int.h" #include "xmlrpc-c/server_cgi.h" @@ -202,13 +203,19 @@ xmlrpc_server_cgi_process_call(xmlrpc_registry * const registryP) { length_str = getenv("CONTENT_LENGTH"); /* Perform some sanity checks. */ - if (!method || 0 != strcmp(method, "POST")) { + if (!method || !xmlrpc_streq(method, "POST")) { code = 405; message = "Method Not Allowed"; XMLRPC_FAIL(&env, XMLRPC_INTERNAL_ERROR, "Expected HTTP method POST"); } - if (!type || 0 != strcmp(type, "text/xml")) { + if (!type || !xmlrpc_strneq(type, "text/xml", strlen("text/xml"))) { + char *template = "Expected content type: \"text/xml\", received: \"%s\""; + size_t err_len = strlen(template) + strlen(type) + 1; + char *err = malloc(err_len); + + (void)snprintf(err, err_len, template, type); code = 400; message = "Bad Request"; - XMLRPC_FAIL(&env, XMLRPC_INTERNAL_ERROR, "Expected text/xml content"); + XMLRPC_FAIL(&env, XMLRPC_INTERNAL_ERROR, err); + free(err); } if (!length_str) { code = 411; message = "Length Required"; diff --git a/libs/xmlrpc-c/src/xmlrpc_server_info.c b/libs/xmlrpc-c/src/xmlrpc_server_info.c index 5cf44c3..2e06c02 100644 --- a/libs/xmlrpc-c/src/xmlrpc_server_info.c +++ b/libs/xmlrpc-c/src/xmlrpc_server_info.c @@ -16,6 +16,10 @@ transports. =============================================================================*/ +#define _XOPEN_SOURCE 600 /* Make sure strdup() is in */ + +#include + #include "bool.h" #include "mallocvar.h" @@ -229,6 +233,9 @@ xmlrpc_server_info_set_user(xmlrpc_env * const envP, } XMLRPC_MEMBLOCK_FREE(char, userNamePw64); } + if (serverInfoP->userNamePw) + xmlrpc_strfree(serverInfoP->userNamePw); + serverInfoP->userNamePw = userNamePw; } diff --git a/libs/xmlrpc-c/src/xmlrpc_server_w32httpsys.c b/libs/xmlrpc-c/src/xmlrpc_server_w32httpsys.c index cf0dad8..ce1587d 100644 --- a/libs/xmlrpc-c/src/xmlrpc_server_w32httpsys.c +++ b/libs/xmlrpc-c/src/xmlrpc_server_w32httpsys.c @@ -1,14 +1,15 @@ /* 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 - 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. + + 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 XML-RPC server program, it is safe to exclude the + xmlrpc_server_w32httpsys.c file from the xmlrpc project and you will not + have this dependency. 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. */ #ifndef UNICODE @@ -19,7 +20,18 @@ #define _UNICODE #endif -/* See compilation note above if this header is not found! */ +/* Declare that we require the Windows XP SP2 or better version of the + interface to Windows. + + Microsoft recommends + (http://msdn.microsoft.com/en-us/library/aa383745(VS.85).aspx) defining + NTDDI_VERSION instead of _WIN32_WINNT for this purpose, but as it was + invented recently, it's pretty useless. Windows header files from old + Windows SDKs won't know what to do with it. +*/ +#define _WIN32_WINNT 0x0502 + +/* See compilation note above if the compiler doesn't find this header file */ #include #include @@ -665,7 +677,8 @@ SendHttpResponse( ADD_KNOWN_HEADER(response, HttpHeaderContentType, "text/html"); - StringCchPrintfA(szServerHeader,20, "xmlrpc-c %s",XMLRPC_C_VERSION); + StringCchPrintfA(szServerHeader, sizeof(szServerHeader), "Xmlrpc-c/%s", + XMLRPC_C_VERSION); ADD_KNOWN_HEADER(response, HttpHeaderServer, szServerHeader); if(pEntityString) @@ -724,7 +737,8 @@ SendHttpResponseAuthRequired( ADD_KNOWN_HEADER(response, HttpHeaderWwwAuthenticate, "Basic realm=\"xmlrpc\""); - StringCchPrintfA(szServerHeader,20, "xmlrpc-c %s",XMLRPC_C_VERSION); + StringCchPrintfA(szServerHeader, sizeof(szServerHeader), "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 @@ -878,8 +892,8 @@ processRPCCall( ADD_KNOWN_HEADER(response, HttpHeaderContentType, "text/xml"); - StringCchPrintfA(szServerHeader,20, - "xmlrpc-c %s",XMLRPC_C_VERSION); + StringCchPrintfA(szServerHeader, sizeof(szServerHeader), + "Xmlrpc-c/%s", XMLRPC_C_VERSION); ADD_KNOWN_HEADER(response, HttpHeaderServer, szServerHeader); diff --git a/libs/xmlrpc-c/src/xmlrpc_string.c b/libs/xmlrpc-c/src/xmlrpc_string.c index 8bf299d..ac9a1f5 100644 --- a/libs/xmlrpc-c/src/xmlrpc_string.c +++ b/libs/xmlrpc-c/src/xmlrpc_string.c @@ -100,11 +100,11 @@ accessStringValue(xmlrpc_env * const envP, validateStringType(envP, valueP); if (!envP->fault_occurred) { - unsigned int const size = + size_t const size = XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block); const char * const contents = XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block); - unsigned int const len = size - 1; + size_t const len = size - 1; /* The memblock has a null character added to the end */ verifyNoNulls(envP, contents, len); @@ -141,7 +141,7 @@ xmlrpc_read_string(xmlrpc_env * const envP, MALLOCARRAY(stringValue, length + 1); if (stringValue == NULL) xmlrpc_faultf(envP, "Unable to allocate space " - "for %u-character string", length); + "for %u-character string", (unsigned)length); else { memcpy(stringValue, contents, length); stringValue[length] = '\0'; @@ -189,7 +189,7 @@ copyAndConvertLfToCrlf(xmlrpc_env * const envP, MALLOCARRAY(dst, dstLen + 1); if (dst == NULL) xmlrpc_faultf(envP, "Unable to allocate space " - "for %u-character string", dstLen + 1); + "for %u-character string", (unsigned)dstLen + 1); else { const char * p; /* source pointer */ char * q; /* destination pointer */ @@ -253,7 +253,7 @@ xmlrpc_read_string_lp(xmlrpc_env * const envP, validateStringType(envP, valueP); if (!envP->fault_occurred) { - unsigned int const size = + size_t const size = XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block); const char * const contents = XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block); @@ -263,7 +263,7 @@ xmlrpc_read_string_lp(xmlrpc_env * const envP, stringValue = malloc(size); if (stringValue == NULL) xmlrpc_faultf(envP, "Unable to allocate %u bytes for string.", - size); + (unsigned int)size); else { memcpy(stringValue, contents, size); *stringValueP = stringValue; @@ -282,7 +282,7 @@ xmlrpc_read_string_lp_crlf(xmlrpc_env * const envP, validateStringType(envP, valueP); if (!envP->fault_occurred) { - unsigned int const size = + size_t const size = XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block); /* Includes NUL */ const char * const contents = XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block); @@ -371,7 +371,7 @@ xmlrpc_read_string_w(xmlrpc_env * const envP, MALLOCARRAY(stringValue, length + 1); if (stringValue == NULL) xmlrpc_faultf(envP, "Unable to allocate space for %u-byte string", - length); + (unsigned)length); else { memcpy(stringValue, wcontents, length * sizeof(wchar_t)); stringValue[length] = '\0'; @@ -422,7 +422,7 @@ wCopyAndConvertLfToCrlf(xmlrpc_env * const envP, MALLOCARRAY(dst, dstLen + 1); if (dst == NULL) xmlrpc_faultf(envP, "Unable to allocate space " - "for %u-character string", dstLen + 1); + "for %u-character string", (unsigned)dstLen + 1); else { const wchar_t * p; /* source pointer */ wchar_t * q; /* destination pointer */ @@ -561,18 +561,6 @@ xmlrpc_read_string_w_lp_old(xmlrpc_env * const envP, 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, @@ -685,7 +673,7 @@ stringNew(xmlrpc_env * const envP, xmlrpc_value * valP; - validateUtf(envP, value, length); + xmlrpc_validate_utf8(envP, value, length); if (!envP->fault_occurred) { xmlrpc_createXmlrpcValue(envP, &valP); @@ -762,7 +750,7 @@ xmlrpc_string_new_va(xmlrpc_env * const envP, xmlrpc_vasprintf(&formattedString, format, args); - if (formattedString == xmlrpc_strsol) { + if (xmlrpc_strnomem(formattedString)) { xmlrpc_faultf(envP, "Out of memory building formatted string"); retvalP = NULL; /* defeat compiler warning */ } else diff --git a/libs/xmlrpc-c/src/xmlrpc_struct.c b/libs/xmlrpc-c/src/xmlrpc_struct.c index 40c59bb..0fde37b 100644 --- a/libs/xmlrpc-c/src/xmlrpc_struct.c +++ b/libs/xmlrpc-c/src/xmlrpc_struct.c @@ -1,30 +1,6 @@ -/* 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. */ - #include "xmlrpc_config.h" +#include #include #include #include @@ -95,22 +71,28 @@ xmlrpc_struct_new(xmlrpc_env * const envP) { */ int -xmlrpc_struct_size(xmlrpc_env* env, xmlrpc_value* strct) -{ +xmlrpc_struct_size(xmlrpc_env * const envP, + xmlrpc_value * const structP) { + int retval; - /* Suppress a compiler warning about uninitialized variables. */ - retval = 0; + XMLRPC_ASSERT_ENV_OK(envP); + XMLRPC_ASSERT_VALUE_OK(structP); - XMLRPC_ASSERT_ENV_OK(env); - XMLRPC_ASSERT_VALUE_OK(strct); + if (structP->_type != XMLRPC_TYPE_STRUCT) { + xmlrpc_env_set_fault_formatted( + envP, XMLRPC_TYPE_ERROR, "Value is not a struct. It is type #%d", + structP->_type); + retval = -1; + } else { + size_t const size = + XMLRPC_MEMBLOCK_SIZE(_struct_member, &structP->_block); - XMLRPC_TYPE_CHECK(env, strct, XMLRPC_TYPE_STRUCT); - retval = XMLRPC_MEMBLOCK_SIZE(_struct_member, &strct->_block); + assert((size_t)(int)size == size); + /* Because structs are defined to have few enough members */ - cleanup: - if (env->fault_occurred) - return -1; + retval = (int)size; + } return retval; } @@ -149,30 +131,42 @@ find_member(xmlrpc_value * const strctP, const char * const key, size_t const keyLen) { + int retval; size_t size, i; uint32_t searchHash; _struct_member * contents; /* array */ - xmlrpc_value * keyvalP; - const char * keystr; - size_t keystrSize; + bool found; + size_t foundIndex; /* Meaningful only when 'found' is true */ XMLRPC_ASSERT_VALUE_OK(strctP); XMLRPC_ASSERT(key != NULL); + foundIndex = 0; /* defeat used-before-set compiler warning */ /* Look for our key. */ 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) { + for (i = 0, found = false; i < size && !found; ++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; + xmlrpc_value * const keyvalP = contents[i].key; + const char * const keystr = + XMLRPC_MEMBLOCK_CONTENTS(char, &keyvalP->_block); + size_t const keystrSize = + XMLRPC_MEMBLOCK_SIZE(char, &keyvalP->_block)-1; + if (keystrSize == keyLen && memcmp(key, keystr, keyLen) == 0) { + found = true; + foundIndex = i; + } } } - return -1; + if (found) { + assert((size_t)(int)foundIndex == foundIndex); + /* Definition of structure says it has few enough members */ + retval = foundIndex; + } else + retval = -1; + + return retval; } @@ -588,3 +582,31 @@ xmlrpc_struct_get_key_and_value(xmlrpc_env * const envP, *valueP = NULL; } } + + + +/* 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. */ + diff --git a/libs/xmlrpc-c/src/xmlrpc_strutil.c b/libs/xmlrpc-c/src/xmlrpc_strutil.c deleted file mode 100644 index efbdca5..0000000 --- a/libs/xmlrpc-c/src/xmlrpc_strutil.c +++ /dev/null @@ -1,75 +0,0 @@ -#include -#include -#include -#include - -#include "xmlrpc_config.h" -#include "xmlrpc-c/base.h" -#include "xmlrpc-c/base_int.h" - - - -const char * -xmlrpc_makePrintable(const char * const input) { -/*---------------------------------------------------------------------------- - Convert an arbitrary string of bytes (null-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. ------------------------------------------------------------------------------*/ - char * output; - const unsigned int inputLength = strlen(input); - - output = malloc(inputLength*4+1); - - if (output != NULL) { - unsigned int inputCursor, outputCursor; - - for (inputCursor = 0, outputCursor = 0; - inputCursor < inputLength; - ++inputCursor) { - - if (isprint(input[inputCursor])) - output[outputCursor++] = input[inputCursor]; - 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 { - snprintf(&output[outputCursor], 4, "\\x%02x", - input[inputCursor]); - } - } - output[outputCursor++] = '\0'; - } - return output; -} - - - -const char * -xmlrpc_makePrintableChar(char const input) { - - 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; -} diff --git a/libs/xmlrpc-c/src/xmlrpc_support.c b/libs/xmlrpc-c/src/xmlrpc_support.c deleted file mode 100644 index c2fd1b6..0000000 --- a/libs/xmlrpc-c/src/xmlrpc_support.c +++ /dev/null @@ -1,394 +0,0 @@ -/* 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. */ - -#include "xmlrpc_config.h" - -#include -#include -#include -#include - -#include "xmlrpc-c/base.h" -#include "xmlrpc-c/base_int.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) - -#define ERROR_BUFFER_SZ (256) - - -/*========================================================================= -** Strings -**=======================================================================*/ - -void -xmlrpc_strfree(const char * const string) { - free((void*)string); -} - - -/*========================================================================= -** Assertions and Error Handling -**========================================================================= -** Support code for XMLRPC_ASSERT and xmlrpc_env. -*/ - -void xmlrpc_assertion_failed (char* file, int line) -{ - fprintf(stderr, "%s:%d: assertion failed\n", file, line); - abort(); -} - -static char* 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* env) -{ - XMLRPC_ASSERT(env != NULL); - - /* 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 (env->fault_string && env->fault_string != default_fault_string) - free(env->fault_string); - env->fault_string = XMLRPC_BAD_POINTER; -} - - - -void -xmlrpc_env_set_fault(xmlrpc_env * const env, - int const faultCode, - const char * const faultDescription) { - - XMLRPC_ASSERT(env != NULL); - XMLRPC_ASSERT(faultDescription != NULL); - - /* Clean up any leftover pointers. */ - xmlrpc_env_clean(env); - - env->fault_occurred = 1; - env->fault_code = faultCode; - - /* Try to copy the fault string. If this fails, use a default. */ - env->fault_string = (char*) malloc(strlen(faultDescription) + 1); - if (env->fault_string) - strcpy(env->fault_string, faultDescription); - else - env->fault_string = default_fault_string; -} - - - -static void -set_fault_formatted_v(xmlrpc_env * const envP, - int const code, - const char * const format, - va_list const args) { - - char buffer[ERROR_BUFFER_SZ]; - - vsnprintf(buffer, ERROR_BUFFER_SZ, format, args); - - /* vsnprintf is guaranteed to terminate the buffer, but we're paranoid. */ - buffer[ERROR_BUFFER_SZ - 1] = '\0'; - - /* Set the fault. */ - xmlrpc_env_set_fault(envP, code, buffer); -} - - - -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); - 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); - set_fault_formatted_v(envP, XMLRPC_INTERNAL_ERROR, format, args); - va_end(args); - -} - - - -void xmlrpc_fatal_error (char* file, int line, char* msg) -{ - fprintf(stderr, "%s:%d: %s\n", file, line, msg); - exit(1); -} - - -/*========================================================================= -** 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 limit_id, size_t value) -{ - XMLRPC_ASSERT(0 <= limit_id && limit_id <= XMLRPC_LAST_LIMIT_ID); - limits[limit_id] = value; -} - -size_t xmlrpc_limit_get (int limit_id) -{ - XMLRPC_ASSERT(0 <= limit_id && limit_id <= XMLRPC_LAST_LIMIT_ID); - return limits[limit_id]; -} - - -/*========================================================================= -** xmlrpc_mem_block -**========================================================================= -*/ - -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* block) -{ - XMLRPC_ASSERT(block != NULL); - XMLRPC_ASSERT(block->_block != NULL); - - xmlrpc_mem_block_clean(block); - free(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) -{ - XMLRPC_ASSERT_ENV_OK(env); - XMLRPC_ASSERT(block != NULL); - - block->_size = size; - if (size < BLOCK_ALLOC_MIN) - block->_allocated = BLOCK_ALLOC_MIN; - else - block->_allocated = size; - - block->_block = (void*) malloc(block->_allocated); - if (!block->_block) - xmlrpc_env_set_fault_formatted( - env, XMLRPC_INTERNAL_ERROR, - "Can't allocate %u-byte memory block", - block->_allocated); -} - -/* Deallocate the contents of the provided xmlrpc_mem_block, but not the -** block itself. */ -void xmlrpc_mem_block_clean (xmlrpc_mem_block* block) -{ - XMLRPC_ASSERT(block != NULL); - XMLRPC_ASSERT(block->_block != NULL); - - free(block->_block); - block->_block = XMLRPC_BAD_POINTER; -} - - - -/* Get the size of the xmlrpc_mem_block. */ -size_t -xmlrpc_mem_block_size(const xmlrpc_mem_block * const block) { - - XMLRPC_ASSERT(block != NULL); - return block->_size; -} - - - -/* Get the contents of the xmlrpc_mem_block. */ -void * -xmlrpc_mem_block_contents(const xmlrpc_mem_block * const block) { - - XMLRPC_ASSERT(block != NULL); - return block->_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) { - - size_t proposed_alloc; - void* new_block; - - XMLRPC_ASSERT_ENV_OK(env); - XMLRPC_ASSERT(block != NULL); - - /* Check to see if we already have enough space. Maybe we'll get lucky. */ - if (size <= block->_allocated) { - block->_size = size; - return; - } - - /* Calculate a new allocation size. */ -#ifdef EFENCE - proposed_alloc = size; -#else - proposed_alloc = block->_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(env, XMLRPC_INTERNAL_ERROR, "Memory block too large"); - - /* Allocate our new memory block. */ - new_block = (void*) malloc(proposed_alloc); - XMLRPC_FAIL_IF_NULL(new_block, env, XMLRPC_INTERNAL_ERROR, - "Can't resize memory block"); - - /* Copy over our data and update the xmlrpc_mem_block struct. */ - memcpy(new_block, block->_block, block->_size); - free(block->_block); - block->_block = new_block; - block->_size = size; - block->_allocated = proposed_alloc; - - cleanup: - return; -} - - - -void -xmlrpc_mem_block_append(xmlrpc_env * const env, - xmlrpc_mem_block * const block, - const void * const data, - size_t const len) { - - int size; - - XMLRPC_ASSERT_ENV_OK(env); - XMLRPC_ASSERT(block != NULL); - - size = block->_size; - xmlrpc_mem_block_resize(env, block, size + len); - XMLRPC_FAIL_IF_FAULT(env); - - memcpy(((unsigned char*) block->_block) + size, data, len); - - cleanup: - return; -} - - - -void -xmlrpc_traceXml(const char * const label, - const char * const xml, - unsigned int const xmlLength) { - - if (getenv("XMLRPC_TRACE_XML")) { - unsigned int nonPrintableCount; - unsigned int i; - - nonPrintableCount = 0; /* Initial value */ - - for (i = 0; i < xmlLength; ++i) { - if (!isprint(xml[i]) && xml[i] != '\n' && xml[i] != '\r') - ++nonPrintableCount; - } - if (nonPrintableCount > 0) - fprintf(stderr, "%s contains %u nonprintable characters.\n", - label, nonPrintableCount); - - fprintf(stderr, "%s:\n\n", label); - fprintf(stderr, "%.*s\n", (int)xmlLength, xml); - } -} diff --git a/libs/xmlrpc-c/src/xmlrpc_transport.c b/libs/xmlrpc-c/src/xmlrpc_transport.c deleted file mode 100644 index d1878e6..0000000 --- a/libs/xmlrpc-c/src/xmlrpc_transport.c +++ /dev/null @@ -1,143 +0,0 @@ -/* 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. */ - -#include "xmlrpc_config.h" - -#undef PACKAGE -#undef VERSION - -#include -#include -#include - -#ifdef WIN32 -#ifdef _DEBUG -# include -# define new DEBUG_NEW -# define malloc(size) _malloc_dbg( size, _NORMAL_BLOCK, __FILE__, __LINE__) -# undef THIS_FILE - static char THIS_FILE[] = __FILE__; -#endif -#endif /*WIN32*/ - -#include "pthreadx.h" -#include "xmlrpc.h" -#include "xmlrpc_client.h" - -#if defined (WIN32) -#include -#endif - -/* For debugging the xmlrpc_transport threading. */ -/* #define tdbg_printf printf */ -#define tdbg_printf (void *) - -/* Lacking from the abyss/thread.c implimentaion. */ -void wait_for_asynch_thread(pthread_t *thread) -{ -#if WIN32 - unsigned long milliseconds = INFINITE; - switch (WaitForSingleObject ( - *thread /* handle to object to wait for */, - milliseconds /* time-out interval in milliseconds*/) ) - { - /* One may want to handle these cases */ - case WAIT_OBJECT_0: - case WAIT_TIMEOUT: - break; - } -#else - void * result; - int success; - success = pthread_join (*thread, &result); -#endif -} - -/* MRB-WARNING: Only call when you have successfully -** acquired the Lock/Unlock mutex! */ -void unregister_asynch_thread (running_thread_list *list, pthread_t *thread) -{ - running_thread_info * pCur = NULL; - XMLRPC_ASSERT_PTR_OK(thread); - XMLRPC_ASSERT_PTR_OK(list); - - tdbg_printf("unregister_asynch_thread: &pthread_id = %08X *(%08X)\n", thread, *thread); - /* Removal */ - /* Lock (); */ - for (pCur = list->AsyncThreadHead; pCur != NULL; pCur = (running_thread_info *)pCur->Next) - { - if (pCur->_thread == *thread) - { - if (pCur == list->AsyncThreadHead) - list->AsyncThreadHead = pCur->Next; - if (pCur == list->AsyncThreadTail) - list->AsyncThreadTail = pCur->Last; - if (pCur->Last) - ((running_thread_info *)(pCur->Last))->Next = pCur->Next; - if (pCur->Next) - ((running_thread_info *)(pCur->Next))->Last = pCur->Last; - /* Free malloc'd running_thread_info */ - free (pCur); - return; - } - } - - /* This is a serious progmatic error, since the thread - ** should be in that list! */ - XMLRPC_ASSERT_PTR_OK(0x0000); - - /* Unlock (); */ -} - -/* MRB-WARNING: Only call when you have successfully -** acquired the Lock/Unlock mutex! */ -void register_asynch_thread (running_thread_list *list, pthread_t *thread) -{ - running_thread_info* info = (running_thread_info *) malloc(sizeof(running_thread_info)); - - XMLRPC_ASSERT_PTR_OK(thread); - XMLRPC_ASSERT_PTR_OK(list); - - tdbg_printf("register_asynch_thread: &pthread_id = %08X *(%08X)\n", thread, *thread); - - info->_thread = *thread; - - /* Insertion */ - /* Lock (); */ - if (list->AsyncThreadHead == NULL) - { - list->AsyncThreadHead = list->AsyncThreadTail = info; - list->AsyncThreadTail->Next = list->AsyncThreadHead->Next = NULL; - list->AsyncThreadTail->Last = list->AsyncThreadHead->Last = NULL; - } - else - { - info->Last = list->AsyncThreadTail; - list->AsyncThreadTail->Next = info; - list->AsyncThreadTail = list->AsyncThreadTail->Next; - list->AsyncThreadTail->Next = NULL; - } - /* Unlock (); */ -} diff --git a/libs/xmlrpc-c/src/xmlrpc_utf8.c b/libs/xmlrpc-c/src/xmlrpc_utf8.c deleted file mode 100644 index 390cc7b..0000000 --- a/libs/xmlrpc-c/src/xmlrpc_utf8.c +++ /dev/null @@ -1,376 +0,0 @@ -/* 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 "xmlrpc_config.h" - -#include "xmlrpc-c/base.h" - -#ifdef HAVE_UNICODE_WCHAR - -/*========================================================================= -** 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 . */ -static wchar_t utf8_min_char_for_length[4] = { - 0, /* Length 0: Not used (meaningless) */ - 0x0000, /* Length 1: Not used (special-cased) */ - 0x0080, /* Length 2 */ - 0x0800 /* Length 3 */ - -#if 0 - /* These are only useful on systems where wchar_t is 32-bits wide - ** and supports full UCS-4. */ - 0x00010000, /* Length 4 */ - 0x00200000, /* Length 5 */ - 0x04000000 /* Length 6 */ -#endif -}; - -/* 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) - -/* Maximum number of bytes needed to encode a supported character. */ -#define MAX_ENCODED_BYTES (3) - - -/*========================================================================= -** decode_utf8 -**========================================================================= -** Internal routine which decodes (or validates) a UTF-8 string. -** To validate, set io_buff and out_buff_len to NULL. To decode, allocate -** a sufficiently large buffer, pass it as io_buff, and pass a pointer as -** as out_buff_len. The data will be written to the buffer, and the -** length to out_buff_len. -** -** We assume that wchar_t holds a single UCS-2 character in native-endian -** byte ordering. -*/ - -static void -decode_utf8(xmlrpc_env * const env, - const char * const utf8_data, - size_t const utf8_len, - wchar_t * const io_buff, - size_t * const out_buff_len) { - - size_t i, length, out_pos; - char init, con1, con2; - wchar_t wc; - - XMLRPC_ASSERT_ENV_OK(env); - XMLRPC_ASSERT_PTR_OK(utf8_data); - XMLRPC_ASSERT((!io_buff && !out_buff_len) || - (io_buff && out_buff_len)); - - /* 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(env, XMLRPC_INVALID_UTF8_ERROR, - "Truncated UTF-8 sequence"); - - /* Decode a multibyte UTF-8 sequence. */ - switch (length) { - case 0: - XMLRPC_FAIL(env, XMLRPC_INVALID_UTF8_ERROR, - "Invalid UTF-8 initial byte"); - - case 2: - /* 110xxxxx 10xxxxxx */ - con1 = utf8_data[i+1]; - if (!IS_CONTINUATION(con1)) - XMLRPC_FAIL(env, 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(env, 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 */ - XMLRPC_FAIL(env, XMLRPC_INVALID_UTF8_ERROR, - "UCS-4 characters not supported"); - - 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(env, 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(env, XMLRPC_INVALID_UTF8_ERROR, - "UTF-16 surrogates may not appear in UTF-8 data"); - - /* Check for overlong sequences. */ - if (wc < utf8_min_char_for_length[length]) - XMLRPC_FAIL(env, XMLRPC_INVALID_UTF8_ERROR, - "Overlong UTF-8 sequence not allowed"); - } - - /* If we have a buffer, write our character to it. */ - if (io_buff) { - io_buff[out_pos++] = wc; - } - } - - /* Record the number of characters we found. */ - if (out_buff_len) - *out_buff_len = out_pos; - - cleanup: - if (env->fault_occurred) { - if (out_buff_len) - *out_buff_len = 0; - } -} - - - -/*========================================================================= -** xmlrpc_validate_utf8 -**========================================================================= -** Make sure that a UTF-8 string is valid. -*/ - -void -xmlrpc_validate_utf8 (xmlrpc_env * const env, - const char * const utf8_data, - size_t const utf8_len) { - - decode_utf8(env, utf8_data, utf8_len, NULL, NULL); -} - - -/*========================================================================= -** xmlrpc_utf8_to_wcs -**========================================================================= -** 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. -*/ - -xmlrpc_mem_block *xmlrpc_utf8_to_wcs (xmlrpc_env *env, - char *utf8_data, - size_t utf8_len) -{ - xmlrpc_mem_block *output; - size_t wcs_length; - - /* Error-handling preconditions. */ - output = NULL; - - /* 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. */ - output = XMLRPC_TYPED_MEM_BLOCK_NEW(wchar_t, env, utf8_len); - XMLRPC_FAIL_IF_FAULT(env); - - /* Decode the UTF-8 data. */ - decode_utf8(env, utf8_data, utf8_len, - XMLRPC_TYPED_MEM_BLOCK_CONTENTS(wchar_t, output), - &wcs_length); - XMLRPC_FAIL_IF_FAULT(env); - - /* Make sure we didn't overrun our buffer. */ - XMLRPC_ASSERT(wcs_length <= utf8_len); - - /* Correct the length of the memory block. */ - XMLRPC_TYPED_MEM_BLOCK_RESIZE(wchar_t, env, output, wcs_length); - XMLRPC_FAIL_IF_FAULT(env); - - cleanup: - if (env->fault_occurred) { - if (output) - xmlrpc_mem_block_free(output); - return NULL; - } - return output; -} - - -/*========================================================================= -** xmlrpc_utf8_to_wcs -**========================================================================= -** Encode a "wide character string" as UTF-8. -*/ - -xmlrpc_mem_block *xmlrpc_wcs_to_utf8 (xmlrpc_env *env, - wchar_t *wcs_data, - size_t wcs_len) -{ - size_t estimate, bytes_used, i; - xmlrpc_mem_block *output; - unsigned char *buffer; - wchar_t wc; - - XMLRPC_ASSERT_ENV_OK(env); - XMLRPC_ASSERT_PTR_OK(wcs_data); - - /* Error-handling preconditions. */ - output = NULL; - - /* Allocate a memory block large enough to hold any possible output. - ** We assume that every wchar might encode to the maximum length. */ - estimate = wcs_len * MAX_ENCODED_BYTES; - output = XMLRPC_TYPED_MEM_BLOCK_NEW(char, env, estimate); - XMLRPC_FAIL_IF_FAULT(env); - - /* Output our characters. */ - buffer = (unsigned char*) XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, output); - bytes_used = 0; - for (i = 0; i < wcs_len; i++) { - wc = wcs_data[i]; - if (wc <= 0x007F) { - buffer[bytes_used++] = wc & 0x7F; - } else if (wc <= 0x07FF) { - /* 110xxxxx 10xxxxxx */ - buffer[bytes_used++] = 0xC0 | (wc >> 6); - buffer[bytes_used++] = 0x80 | (wc & 0x3F); - } else if (wc <= 0xFFFF) { - /* 1110xxxx 10xxxxxx 10xxxxxx */ - buffer[bytes_used++] = 0xE0 | (wc >> 12); - buffer[bytes_used++] = 0x80 | ((wc >> 6) & 0x3F); - buffer[bytes_used++] = 0x80 | (wc & 0x3F); - } else { - XMLRPC_FAIL(env, XMLRPC_INTERNAL_ERROR, - "Don't know how to encode UCS-4 characters yet"); - } - } - - /* Make sure we didn't overrun our buffer. */ - XMLRPC_ASSERT(bytes_used <= estimate); - - /* Correct the length of the memory block. */ - XMLRPC_TYPED_MEM_BLOCK_RESIZE(char, env, output, bytes_used); - XMLRPC_FAIL_IF_FAULT(env); - - cleanup: - if (env->fault_occurred) { - if (output) - xmlrpc_mem_block_free(output); - return NULL; - } - return output; -} - -#endif /* HAVE_UNICODE_WCHAR */ diff --git a/libs/xmlrpc-c/srcdir.mk.in b/libs/xmlrpc-c/srcdir.mk.in new file mode 100644 index 0000000..d389df1 --- /dev/null +++ b/libs/xmlrpc-c/srcdir.mk.in @@ -0,0 +1 @@ +SRCDIR=@abs_srcdir@ diff --git a/libs/xmlrpc-c/tools/.cvsignore b/libs/xmlrpc-c/tools/.cvsignore deleted file mode 100644 index f3c7a7c..0000000 --- a/libs/xmlrpc-c/tools/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -Makefile diff --git a/libs/xmlrpc-c/tools/Makefile b/libs/xmlrpc-c/tools/Makefile index 621dbf9..c2eb347 100644 --- a/libs/xmlrpc-c/tools/Makefile +++ b/libs/xmlrpc-c/tools/Makefile @@ -7,15 +7,20 @@ SUBDIR := tools include $(BLDDIR)/config.mk -SUBDIRS = binmode-rpc-kit turbocharger +SUBDIRS = \ + binmode-rpc-kit \ + lib \ + turbocharger \ ifeq ($(MUST_BUILD_CLIENT),yes) SUBDIRS += xmlrpc xmlrpc_transport 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. + SUBDIRS += xml-rpc-api2cpp xml-rpc-api2txt xmlrpc_cpp_proxy + + ifeq ($(BUILD_XMLRPC_PSTREAM),yes) + SUBDIRS += xmlrpc_pstream + endif endif endif diff --git a/libs/xmlrpc-c/tools/Makefile.common b/libs/xmlrpc-c/tools/Makefile.common deleted file mode 100644 index 8b0cdce..0000000 --- a/libs/xmlrpc-c/tools/Makefile.common +++ /dev/null @@ -1,47 +0,0 @@ -# -*-makefile-*- <-- an Emacs control - -CLIENT_LDFLAGS = -ifeq ($(MUST_BUILD_LIBWWW_CLIENT),yes) - CLIENT_LDFLAGS += $(shell libwww-config --libs) -endif -ifeq ($(MUST_BUILD_CURL_CLIENT),yes) - CLIENT_LDFLAGS += $(shell curl-config --libs) -lpthread -endif -ifeq ($(MUST_BUILD_WININET_CLIENT),yes) - CLIENT_LDFLAGS += $(shell wininet-config --libs) -endif - -LIBEXPAT = $(BUILDDIR)/lib/expat/xmlparse/libxmlrpc_xmlparse.la \ - $(BUILDDIR)/lib/expat/xmltok/libxmlrpc_xmltok.la - -ifeq ($(ENABLE_LIBXML2_BACKEND),yes) - LIBXML = $(LIBXML2_LIBS) -else - LIBXML = $(LIBEXPAT) -endif - -LIBXMLRPC = $(BUILDDIR)/src/libxmlrpc.la -LIBXMLRPC_CPP = $(BUILDDIR)/src/cpp/libxmlrpc_cpp.a -LIBXMLRPC_CLIENT = $(BUILDDIR)/src/libxmlrpc_client.la -LIBXMLRPC_SERVER = $(BUILDDIR)/src/libxmlrpc_server.la - -XMLRPC_LIBS = $(LIBXMLRPC) $(LIBXMLRPC_CPP) $(LIBXMLRPC_CLIENT) \ - $(LIBXMLRPC_SERVER) $(LIBXML) - -UTIL_DIR = $(BUILDDIR)/lib/util - -BUILDABLE_UTILS = casprintf.o cmdline_parser.o getoptx.o - -$(BUILDABLE_UTILS:%=$(UTIL_DIR)/%): FORCE - $(MAKE) -C $(dir $@) $(notdir $@) - -include $(SRCDIR)/Makefile.common - -.PHONY: install -install: install-common - -.PHONY: check -check: - -.PHONY: FORCE -FORCE: diff --git a/libs/xmlrpc-c/tools/common.mk b/libs/xmlrpc-c/tools/common.mk index fe71e97..4c377fe 100644 --- a/libs/xmlrpc-c/tools/common.mk +++ b/libs/xmlrpc-c/tools/common.mk @@ -29,7 +29,7 @@ CLIENTPP_LDLIBS += -lxmlrpc_client++ -lxmlrpc_packetsocket -lxmlrpc++ include $(SRCDIR)/common.mk ifneq ($(OMIT_LIB_RULE),Y) -srcdir/tools/lib/dumpvalue.o: FORCE +blddir/tools/lib/dumpvalue.o: FORCE $(MAKE) -C $(dir $@) -f $(SRCDIR)/tools/lib/Makefile $(notdir $@) endif diff --git a/libs/xmlrpc-c/tools/lib/Makefile b/libs/xmlrpc-c/tools/lib/Makefile index 5b04eed..836d9c9 100644 --- a/libs/xmlrpc-c/tools/lib/Makefile +++ b/libs/xmlrpc-c/tools/lib/Makefile @@ -20,8 +20,6 @@ INCLUDES = \ -Isrcdir/include \ -Isrcdir/lib/util/include \ -CFLAGS = $(CFLAGS_COMMON) $(INCLUDES) $(CFLAGS_PERSONAL) $(CADD) - LIBOBJS = \ dumpvalue.o \ @@ -29,14 +27,14 @@ LIBOBJS = \ all: $(LIBOBJS) %.o:%.c - $(CC) -c $(CFLAGS) $< + $(CC) -c $(CFLAGS_ALL) $< # This common.mk dependency makes sure the symlinks get built before # this make file is used for anything. -$(SRCDIR)/tool/common.mk: srcdir blddir +$(SRCDIR)/tools/common.mk: srcdir blddir -include Makefile.depend +include depend.mk .PHONY: dep dep: dep-common diff --git a/libs/xmlrpc-c/tools/lib/dumpvalue.c b/libs/xmlrpc-c/tools/lib/dumpvalue.c index ebcc000..682c904 100644 --- a/libs/xmlrpc-c/tools/lib/dumpvalue.c +++ b/libs/xmlrpc-c/tools/lib/dumpvalue.c @@ -5,7 +5,7 @@ used for debugging purposes in other places. */ -//#define _GNU_SOURCE +#define _XOPEN_SOURCE 600 /* Make sure strdup() is in */ #include #include @@ -297,12 +297,12 @@ dumpStructMember(const char * const prefix, const char * prefix2; const char * blankPrefix; - casprintf(&prefix2, "%s Key: ", prefix); + casprintf(&blankPrefix, "%*s", blankCount, ""); + + casprintf(&prefix2, "%s Key: ", blankPrefix); dumpValue(prefix2, keyP); strfree(prefix2); - casprintf(&blankPrefix, "%*s", blankCount, ""); - casprintf(&prefix2, "%s Value: ", blankPrefix); dumpValue(prefix2, valueP); strfree(prefix2); @@ -407,13 +407,13 @@ dumpI8(const char * const prefix, 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); + printf("%s64-bit integer: %" XMLRPC_PRId64 "\n", prefix, value); xmlrpc_env_clean(&env); } diff --git a/libs/xmlrpc-c/tools/turbocharger/.cvsignore b/libs/xmlrpc-c/tools/turbocharger/.cvsignore deleted file mode 100644 index f3c7a7c..0000000 --- a/libs/xmlrpc-c/tools/turbocharger/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -Makefile diff --git a/libs/xmlrpc-c/tools/xml-rpc-api2cpp/.cvsignore b/libs/xmlrpc-c/tools/xml-rpc-api2cpp/.cvsignore deleted file mode 100644 index c194ee8..0000000 --- a/libs/xmlrpc-c/tools/xml-rpc-api2cpp/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -xml-rpc-api2cpp diff --git a/libs/xmlrpc-c/tools/xml-rpc-api2cpp/Makefile b/libs/xmlrpc-c/tools/xml-rpc-api2cpp/Makefile index dbe374f..0ad3907 100644 --- a/libs/xmlrpc-c/tools/xml-rpc-api2cpp/Makefile +++ b/libs/xmlrpc-c/tools/xml-rpc-api2cpp/Makefile @@ -10,23 +10,24 @@ default: all include $(BLDDIR)/config.mk -include $(SRCDIR)/tools/common.mk - -INCLUDES = -I$(BLDDIR) -I$(BLDDIR)/include -I$(SRCDIR)/include +PROGS := xml-rpc-api2cpp +PROGRAMS_TO_INSTALL := $(PROGS) +MAN_FILES_TO_INSTALL := xml-rpc-api2cpp.1 -CXXFLAGS = $(INCLUDES) $(CXXFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD) +all: $(PROGS) -LDFLAGS = $(LADD) +include $(SRCDIR)/tools/common.mk -LDLIBS = -L$(BLDDIR)/src/cpp -lxmlrpc_cpp -lxmlrpc_server $(CLIENT_LDLIBS) +# in Glibc 2.2 has a bug that results in inlining failure, +# so we disable warnings for that: +CFLAGS_LOCAL = -Wno-inline -PROGS := +INCLUDES = -I$(BLDDIR) -I$(BLDDIR)/include -Isrcdir/include -ifeq ($(MUST_BUILD_CLIENT),yes) - PROGS += xml-rpc-api2cpp -endif +LDFLAGS = $(LADD) -all: $(PROGS) +LDLIBS = -L$(BLDDIR)/src/cpp -lxmlrpc_cpp -L$(BLDDIR)/src -lxmlrpc_server \ + $(CLIENT_LDLIBS) OBJECTS = \ xml-rpc-api2cpp.o \ @@ -46,14 +47,14 @@ xml-rpc-api2cpp: \ $(CXXLD) -o $@ $(LDFLAGS) $(OBJECTS) $(LDLIBS) %.o:%.cpp - $(CXX) -c $(CXXFLAGS) $< + $(CXX) -c $(CXXFLAGS_ALL) $< # This common.mk dependency makes sure the symlinks get built before # this make file is used for anything. -$(SRCDIR)/common.mk: srcdir blddir +$(SRCDIR)/tools/common.mk: srcdir blddir -include Makefile.depend +include depend.mk .PHONY: clean clean: clean-common diff --git a/libs/xmlrpc-c/tools/xml-rpc-api2cpp/Makefile.depend b/libs/xmlrpc-c/tools/xml-rpc-api2cpp/Makefile.depend deleted file mode 100644 index e69de29..0000000 diff --git a/libs/xmlrpc-c/tools/xml-rpc-api2cpp/README b/libs/xmlrpc-c/tools/xml-rpc-api2cpp/README deleted file mode 100644 index 4dff2a3..0000000 --- a/libs/xmlrpc-c/tools/xml-rpc-api2cpp/README +++ /dev/null @@ -1,6 +0,0 @@ -This program generates C++ wrapper classes for XML-RPC servers. It talks -to xmlrpc-c and XML-RPC.NET servers without any problems, but tends to -choke when talking to mod_php-based servers. It looks like there is some -kind of pipelining problem. - -This code is an ongoing project. Please send feedback! diff --git a/libs/xmlrpc-c/tools/xml-rpc-api2txt b/libs/xmlrpc-c/tools/xml-rpc-api2txt deleted file mode 100755 index e771463..0000000 --- a/libs/xmlrpc-c/tools/xml-rpc-api2txt +++ /dev/null @@ -1,147 +0,0 @@ -#!/usr/bin/perl -w -# -# A handy little program to get the documentation of the available -# methods from an XML-RPC service (via XML-RPC Introspection) and -# print it out nicely formatted. -# -# (I wrote this in Perl because of all the spiffy report-generation -# features.) -# -# You'll need to get Ken MacLeod's Frontier::RPC2 module from CPAN to use -# this. -# -# Eric Kidd -# -# This script is part of xmlrpc-c, and may be used and distributed under -# the same terms as the rest of the package. - -use strict; - -# One global variable for use with Perl's format routines, and one for -# use inside an 'exec' block. -use vars qw/$helptext $method_list/; - -# Try to load our Perl XML-RPC bindings, but fail gracefully. -eval { - require Frontier::Client; -}; -if ($@) { - print STDERR <<"EOD"; -This script requires Ken MacLeod\'s Frontier::RPC2 module. You can get this -from CPAN or from his website at http://bitsko.slc.ut.us/~ken/xml-rpc/ . - -For installation instructions, see the XML-RPC HOWTO at: - http://www.linuxdoc.org/HOWTO/XML-RPC-HOWTO/index.html - -EOD - exit 1; -} - -# Parse our command-line arguments. -if (@ARGV != 1 || $ARGV[0] eq "--help") { - print STDERR "Usage: xml-rpc-api2txt serverURL\n"; - exit 1; -} - -my $server = Frontier::Client->new(url => $ARGV[0]); - -# Try (very carefully) to get our a list of methods from the server. -local $method_list; -eval { - $method_list = $server->call('system.listMethods'); -}; -if ($@) { - print STDERR <<"EOD"; -An error occurred while trying to talk to the XML-RPC server: - - $@ - -This may have been caused by several things--the server might not support -introspection, it might not be an XML-RPC server, or your network might be -down. Try the following: - - xml-rpc-api2txt http://xmlrpc-c.sourceforge.net/api/sample.php - -EOD - exit 1; -} - -# Enter the methods into a hashtable. -my @methods = sort @$method_list; -my %method_table; -foreach my $method (@methods) { - $method_table{$method} = {}; -} - -# Get more information for the hash table. Since we need to make lots and -# lots of very small XML-RPC calls, we'd like to use system.multicall to -# reduce the latency. -if (defined $method_table{'system.multicall'}) { - - # This is messy but fast. Everybody hates HTTP round-trip lag, right? - my @call; - foreach my $method (@methods) { - push @call, {methodName => 'system.methodSignature', - params => [$method]}; - push @call, {methodName => 'system.methodHelp', - params => [$method]}; - } - my @result = @{$server->call('system.multicall', \@call)}; - for (my $i = 0; $i < @methods; $i++) { - my $method = $methods[$i]; - $method_table{$method}->{'signatures'} = $result[2*$i]->[0]; - $method_table{$method}->{'help'} = $result[2*$i+1]->[0]; - } -} else { - - # This is easy but slow (especially over backbone links). - foreach my $method (@methods) { - my $signature = $server->call('system.methodSignature', $method); - my $help = $server->call('system.methodHelp', $method); - $method_table{$method}->{'signatures'} = $signature; - $method_table{$method}->{'help'} = $help; - } -} - -# Now, we need to dump the API. -print <<"EOD"; -XML-RPC API for $ARGV[0] - -See http://www.linuxdoc.org/HOWTO/XML-RPC-HOWTO/index.html for instructions -on using XML-RPC with Perl, Python, Java, C, C++, PHP, etc. -EOD -foreach my $method (@methods) { - print "\n"; - - # Print a synopsis of the function. - if ($method_table{$method}->{'signatures'} eq 'undef') { - # No documentation. Bad server. No biscuit. - print "unknown $method (...)\n"; - } else { - for my $signature (@{$method_table{$method}->{'signatures'}}) { - my $return_type = shift @$signature; - my $arguments = join(", ", @$signature); - print "$return_type $method ($arguments)\n"; - } - } - print "\n"; - - my $help = $method_table{$method}->{'help'}; - if ($help =~ /\n/) { - # Text has already been broken into lines by the server, so just - # indent it by two spaces and hope for the best. - my @lines = split(/\n/, $help); - my $help = " " . join("\n ", @lines); - print "$help\n"; - } else { - # Print our help text in a nicely-wrapped fashion using Perl's - # formatting routines. - $helptext = $method_table{$method}->{'help'}; - write; - } -} - -format STDOUT = - ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<~~ - $helptext -. diff --git a/libs/xmlrpc-c/tools/xml-rpc-api2txt.1 b/libs/xmlrpc-c/tools/xml-rpc-api2txt.1 deleted file mode 100644 index a9e1ee3..0000000 --- a/libs/xmlrpc-c/tools/xml-rpc-api2txt.1 +++ /dev/null @@ -1,47 +0,0 @@ -.\" Hey, EMACS: -*- nroff -*- -.\" First parameter, NAME, should be all caps -.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection -.\" other parameters are allowed: see man(7), man(1) -.TH XML-RPC-API2TXT 1 "June 27, 2001" -.\" Please adjust this date whenever revising the manpage. -.\" -.\" Some roff macros, for reference: -.\" .nh disable hyphenation -.\" .hy enable hyphenation -.\" .ad l left justify -.\" .ad b justify to both left and right margins -.\" .nf disable filling -.\" .fi enable filling -.\" .br insert line break -.\" .sp insert n+1 empty lines -.\" for manpage-specific macros, see man(7) -.SH NAME -xml-rpc-api2txt \- Print out a description of an XML-RPC API as text -.SH SYNOPSIS -.B xml-rpc-api2txt -\fIserver-url\fR -.SH DESCRIPTION -xml-rpc-api2txt queries an XML-RPC server using the XML-RPC -Instrospection API designed by Edd Dumbill. It then prints the -results to standard output in a nicely formatted form, suitable for -sending via e-mail. -.PP -You can find a list of supported XML-RPC server libraries (and patches -for many others) at \fBhttp://xmlrpc-c.sourceforge.net/hacks.php\fR. -.SH OPTIONS -.TP -.I server-url -The name of the server to query. Try -\fBhttp://xmlrpc-c.sourceforge.net/cgi-bin/interop.cgi\fR. -.SH BUGS -xml-rpc-api2txt assumes that method descriptions are ASCII text, not -HTML as specified in the standard. (In practice, both conventions are -often seen.) -.SH SEE ALSO -.BR xmlrpc-c (7), -.BR xml-rpc-api2cpp (1). -.PP -This program is part of xmlrpc-c. -.SH AUTHOR -This manual page was written by Eric Kidd . -It may be distributed under the same terms as the rest of xmlrpc-c. diff --git a/libs/xmlrpc-c/tools/xmlrpc/.cvsignore b/libs/xmlrpc-c/tools/xmlrpc/.cvsignore deleted file mode 100644 index 73a3b1b..0000000 --- a/libs/xmlrpc-c/tools/xmlrpc/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -xmlrpc diff --git a/libs/xmlrpc-c/tools/xmlrpc/Makefile b/libs/xmlrpc-c/tools/xmlrpc/Makefile index c1f3b34..a8b3372 100644 --- a/libs/xmlrpc-c/tools/xmlrpc/Makefile +++ b/libs/xmlrpc-c/tools/xmlrpc/Makefile @@ -21,8 +21,6 @@ INCLUDES = \ -Isrcdir/include \ -Isrcdir/lib/util/include -CFLAGS = $(CFLAGS_COMMON) $(INCLUDES) $(CFLAGS_PERSONAL) $(CADD) - LDFLAGS = $(LADD) all: xmlrpc @@ -36,7 +34,7 @@ UTIL_OBJS = \ UTILS = $(UTIL_OBJS:%=$(UTIL_DIR)/%) -DUMPVALUE = srcdir/tools/lib/dumpvalue.o +DUMPVALUE = blddir/tools/lib/dumpvalue.o # Can we just use $(LIBS) in the link? @@ -48,14 +46,14 @@ xmlrpc: $(XMLRPC_OBJS) $(LIBS) $(UTILS) $(CCLD) -o $@ $(LDFLAGS) $(XMLRPC_OBJS) $(UTILS) $(CLIENT_LDLIBS) %.o:%.c $(BLDDIR)/include/xmlrpc-c/config.h - $(CC) -c $(CFLAGS) $< + $(CC) -c $(CFLAGS_ALL) $< # 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 +include depend.mk .PHONY: dep dep: dep-common diff --git a/libs/xmlrpc-c/tools/xmlrpc/Makefile.depend b/libs/xmlrpc-c/tools/xmlrpc/Makefile.depend deleted file mode 100644 index e69de29..0000000 diff --git a/libs/xmlrpc-c/tools/xmlrpc/xmlrpc.c b/libs/xmlrpc-c/tools/xmlrpc/xmlrpc.c index c768b7b..06da3e5 100644 --- a/libs/xmlrpc-c/tools/xmlrpc/xmlrpc.c +++ b/libs/xmlrpc-c/tools/xmlrpc/xmlrpc.c @@ -35,7 +35,7 @@ */ -//#define _GNU_SOURCE +#define _XOPEN_SOURCE 600 /* Make sure strdup() is in */ #include #include @@ -55,6 +55,7 @@ #include "xmlrpc-c/base.h" #include "xmlrpc-c/client.h" +#include "xmlrpc-c/string_int.h" #define NAME "xmlrpc command line program" #define VERSION "1.0" @@ -260,6 +261,33 @@ buildString(xmlrpc_env * const envP, static void +interpretHex(xmlrpc_env * const envP, + const char * const valueString, + size_t const valueStringSize, + unsigned char * const byteString) { + + size_t bsCursor; + size_t strCursor; + + for (strCursor = 0, bsCursor = 0; + strCursor < valueStringSize && !envP->fault_occurred; + ) { + int rc; + + rc = sscanf(&valueString[strCursor], "%2hhx", + &byteString[bsCursor++]); + + if (rc != 1) + xmlrpc_faultf(envP, "Invalid hex data '%s'", + &valueString[strCursor]); + else + strCursor += 2; + } +} + + + +static void buildBytestring(xmlrpc_env * const envP, const char * const valueString, xmlrpc_value ** const paramPP) { @@ -269,33 +297,25 @@ buildBytestring(xmlrpc_env * const envP, if (valueStringSize / 2 * 2 != valueStringSize) xmlrpc_faultf(envP, "Hexadecimal text is not an even " "number of characters (it is %u characters)", - strlen(valueString)); + (unsigned)strlen(valueString)); else { size_t const byteStringSize = strlen(valueString)/2; - unsigned char byteString[byteStringSize]; - size_t bsCursor; - size_t strCursor; - - strCursor = 0; - bsCursor = 0; + unsigned char * byteString; - while (strCursor < valueStringSize && !envP->fault_occurred) { - int rc; + MALLOCARRAY(byteString, byteStringSize); - assert(bsCursor < byteStringSize); + if (byteString == NULL) + xmlrpc_faultf(envP, "Failed to allocate %u-byte buffer", + (unsigned)byteStringSize); + else { + interpretHex(envP, valueString, valueStringSize, byteString); - rc = sscanf(&valueString[strCursor], "%2hhx", - &byteString[bsCursor++]); + if (!envP->fault_occurred) + *paramPP = xmlrpc_base64_new(envP, byteStringSize, byteString); - if (rc != 1) - xmlrpc_faultf(envP, "Invalid hex data '%s'", - &valueString[strCursor]); - else - strCursor += 2; + free(byteString); } - if (!envP->fault_occurred) - *paramPP = xmlrpc_base64_new(envP, byteStringSize, byteString); } } @@ -409,19 +429,19 @@ computeParameter(xmlrpc_env * const envP, const char * const paramArg, xmlrpc_value ** const paramPP) { - if (strncmp(paramArg, "s/", 2) == 0) + if (xmlrpc_strneq(paramArg, "s/", 2)) buildString(envP, ¶mArg[2], paramPP); - else if (strncmp(paramArg, "h/", 2) == 0) + else if (xmlrpc_strneq(paramArg, "h/", 2)) buildBytestring(envP, ¶mArg[2], paramPP); - else if (strncmp(paramArg, "i/", 2) == 0) + else if (xmlrpc_strneq(paramArg, "i/", 2)) buildInt(envP, ¶mArg[2], paramPP); - else if (strncmp(paramArg, "I/", 2) == 0) + else if (xmlrpc_strneq(paramArg, "I/", 2)) buildI8(envP, ¶mArg[2], paramPP); - else if (strncmp(paramArg, "d/", 2) == 0) + else if (xmlrpc_strneq(paramArg, "d/", 2)) buildDouble(envP, ¶mArg[2], paramPP); - else if (strncmp(paramArg, "b/", 2) == 0) + else if (xmlrpc_strneq(paramArg, "b/", 2)) buildBool(envP, ¶mArg[2], paramPP); - else if (strncmp(paramArg, "n/", 2) == 0) + else if (xmlrpc_strneq(paramArg, "n/", 2)) buildNil(envP, ¶mArg[2], paramPP); else { /* It's not in normal type/value format, so we take it to be diff --git a/libs/xmlrpc-c/tools/xmlrpc/xmlrpc.html b/libs/xmlrpc-c/tools/xmlrpc/xmlrpc.html index 07119c8..55315d5 100644 --- a/libs/xmlrpc-c/tools/xmlrpc/xmlrpc.html +++ b/libs/xmlrpc-c/tools/xmlrpc/xmlrpc.html @@ -34,7 +34,7 @@ http://gggeek.damacom.it/debugger/
 
-     $ xmlrpc http://xmlrpc.server.net/~bryanh echostring \
+     $ xmlrpc http://xmlrpc.example.com/~bryanh echostring \
          "s/This is a string"
      Result:
        String: This is a string
@@ -44,7 +44,7 @@ http://gggeek.damacom.it/debugger/
 
 
 
-     $ xmlrpc http://xmlrpc.server.net/~bryanh echostring \
+     $ xmlrpc http://xmlrpc.example.com/~bryanh echostring \
          "This is a string in shortcut syntax"
      Result:
        String: This is a string in shortcut syntax
@@ -53,7 +53,7 @@ http://gggeek.damacom.it/debugger/
 
 
-     $ xmlrpc http://xmlrpc.server.net sample.add i/3 i/5 \
+     $ xmlrpc http://xmlrpc.example.com sample.add i/3 i/5 \
          transport=curl -curlinterface=eth1 -username=bryanh -password=passw0rd
        Result:
          Integer: 8
diff --git a/libs/xmlrpc-c/tools/xmlrpc_cpp_proxy/Makefile b/libs/xmlrpc-c/tools/xmlrpc_cpp_proxy/Makefile
index d6f50a6..fec3cb8 100644
--- a/libs/xmlrpc-c/tools/xmlrpc_cpp_proxy/Makefile
+++ b/libs/xmlrpc-c/tools/xmlrpc_cpp_proxy/Makefile
@@ -14,9 +14,11 @@ PROGRAMS_TO_INSTALL = xmlrpc_cpp_proxy
 
 include $(SRCDIR)/tools/common.mk
 
-INCLUDES = -I$(BLDDIR) -I$(BLDDIR)/include -I$(SRCDIR)/include
+#  in Glibc 2.2 has a bug that results in inlining failure,
+# so we disable warnings for that:
+CFLAGS_LOCAL = -Wno-inline
 
-CXXFLAGS = $(INCLUDES) $(CXXFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD)
+INCLUDES = -I$(BLDDIR) -I$(BLDDIR)/include -Isrcdir/include
 
 LDFLAGS = $(LADD)
 
@@ -43,14 +45,14 @@ xmlrpc_cpp_proxy:  $(OBJECTS) $(LIBS)
 	$(CXXLD) -o $@ $(LDFLAGS) $(OBJECTS) $(LDLIBS) $(LADD)
 
 %.o:%.cpp $(BLDDIR)/include/xmlrpc-c/config.h
-	$(CXX) -c $(CXXFLAGS) $<
+	$(CXX) -c $(CXXFLAGS_ALL) $<
 
 # 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
+include depend.mk
 
 .PHONY: clean
 clean: clean-common
diff --git a/libs/xmlrpc-c/tools/xmlrpc_pstream/Makefile b/libs/xmlrpc-c/tools/xmlrpc_pstream/Makefile
index 2fb24fb..9a538fc 100644
--- a/libs/xmlrpc-c/tools/xmlrpc_pstream/Makefile
+++ b/libs/xmlrpc-c/tools/xmlrpc_pstream/Makefile
@@ -23,15 +23,13 @@ INCLUDES = \
   -Iblddir/include \
   -Isrcdir/include \
 
-CXXFLAGS = $(INCLUDES) $(CXXFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD)
-
 LDFLAGS = $(LADD)
 
 all: xmlrpc_pstream
 
 OBJECTS = \
   xmlrpc_pstream.o \
-  $(TOOLSDIR)/lib/dumpvalue.o \
+  blddir/tools/lib/dumpvalue.o \
 
 LIBS = \
   $(LIBXMLRPC_CLIENTPP) \
@@ -57,14 +55,14 @@ xmlrpc_pstream:  $(OBJECTS) $(LIBS) $(UTILS)
 	$(CXXLD) -o $@ $(LDFLAGS) $(OBJECTS) $(UTILS) $(LDLIBS) $(LADD)
 
 %.o:%.cpp blddir/include/xmlrpc-c/config.h
-	$(CXX) -c $(CXXFLAGS) $<
+	$(CXX) -c $(CXXFLAGS_ALL) $<
 
 # This common.mk dependency makes sure the symlinks get built before
 # this make file is used for anything.
 
-$(SRCDIR)/common.mk: srcdir blddir
+$(SRCDIR)/tools/common.mk: srcdir blddir
 
-include Makefile.depend
+include depend.mk
 
 .PHONY: clean
 clean: clean-common
diff --git a/libs/xmlrpc-c/tools/xmlrpc_pstream/xmlrpc_pstream.cpp b/libs/xmlrpc-c/tools/xmlrpc_pstream/xmlrpc_pstream.cpp
index 399e1b3..1417708 100644
--- a/libs/xmlrpc-c/tools/xmlrpc_pstream/xmlrpc_pstream.cpp
+++ b/libs/xmlrpc-c/tools/xmlrpc_pstream/xmlrpc_pstream.cpp
@@ -3,9 +3,10 @@
 #include 
 #include 
 #include 
-#include 
-#include 
-#include 
+#include 
+#include 
+#include 
+#include 
 #include 
 #include 
 #include 
diff --git a/libs/xmlrpc-c/tools/xmlrpc_pstream/xmlrpc_pstream.html b/libs/xmlrpc-c/tools/xmlrpc_pstream/xmlrpc_pstream.html
index ca4d859..5604d2b 100644
--- a/libs/xmlrpc-c/tools/xmlrpc_pstream/xmlrpc_pstream.html
+++ b/libs/xmlrpc-c/tools/xmlrpc_pstream/xmlrpc_pstream.html
@@ -121,7 +121,7 @@ You may specify no parameters if you like.
 a slash.  Example: i/5.  Here, the "i" signifies an
 integer data type.  "5" is the value.
 
-

xmlrpc is capable of only a subset of the +

xmlrpc_pstream is capable of only a subset of the possible XML-RPC types, as follows by prefix:

diff --git a/libs/xmlrpc-c/tools/xmlrpc_transport/.cvsignore b/libs/xmlrpc-c/tools/xmlrpc_transport/.cvsignore deleted file mode 100644 index bff9884..0000000 --- a/libs/xmlrpc-c/tools/xmlrpc_transport/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -xmlrpc_transport diff --git a/libs/xmlrpc-c/tools/xmlrpc_transport/Makefile b/libs/xmlrpc-c/tools/xmlrpc_transport/Makefile index 9941eb1..d9eefcb 100644 --- a/libs/xmlrpc-c/tools/xmlrpc_transport/Makefile +++ b/libs/xmlrpc-c/tools/xmlrpc_transport/Makefile @@ -17,10 +17,8 @@ include $(SRCDIR)/tools/common.mk INCLUDES = \ -I$(BLDDIR) \ -I$(BLDDIR)/include \ - -I$(SRCDIR)/include \ - -I$(SRCDIR)/lib/util/include - -CFLAGS = $(CFLAGS_COMMON) $(INCLUDES) $(CFLAGS_PERSONAL) $(CADD) + -Isrcdir/include \ + -Isrcdir/lib/util/include LDFLAGS = $(LADD) @@ -35,27 +33,20 @@ UTIL_OBJS = \ UTILS = $(UTIL_OBJS:%=$(UTIL_DIR)/%) -# 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 - $(CC) -c $(CFLAGS) $< + $(CC) -c $(CFLAGS_ALL) $< # 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 +include depend.mk .PHONY: dep dep: dep-common diff --git a/libs/xmlrpc-c/tools/xmlrpc_transport/Makefile.depend b/libs/xmlrpc-c/tools/xmlrpc_transport/Makefile.depend deleted file mode 100644 index e69de29..0000000 diff --git a/libs/xmlrpc-c/tools/xmlrpc_transport/xmlrpc_transport b/libs/xmlrpc-c/tools/xmlrpc_transport/xmlrpc_transport deleted file mode 100755 index e002ec0..0000000 --- a/libs/xmlrpc-c/tools/xmlrpc_transport/xmlrpc_transport +++ /dev/null @@ -1,120 +0,0 @@ -#! /bin/sh - -# xmlrpc_transport - temporary wrapper script for .libs/xmlrpc_transport -# Generated by ltmain.sh - GNU libtool 1.3.4 (1.385.2.196 1999/12/07 21:47:57) -# -# The xmlrpc_transport program cannot be directly executed until all the libtool -# libraries that it depends on are installed. -# -# This wrapper script should never be moved out of the build directory. -# If it is, it will not operate correctly. - -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -Xsed='sed -e 1s/^X//' -sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g' - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -if test "${CDPATH+set}" = set; then CDPATH=:; export CDPATH; fi - -relink_command="gcc -o \$progdir/\$file -L /usr/link/w3c-libwww -lwwwxml -lxmltok -lxmlparse -lwwwzip -lwwwinit -lwwwapp -lwwwhtml -lwwwtelnet -lwwwnews -lwwwhttp -lwwwmime -lwwwgopher -lwwwftp -lwwwfile -lwwwdir -lwwwcache -lwwwstream -lwwwmux -lwwwtrans -lwwwcore -lwwwutils -lmd5 -ldl -lz -L /subsys/openssl/link -lssl -lcrypto -L/subsys/curl/lib -lcurl -lssl -lcrypto -ldl -lz -lpthread xmlrpc_transport.o /mp/hdc1/xmlrpc-c-1.03.14/tools/xmlrpc_transport/../../src/.libs/libxmlrpc_client.so /mp/hdc1/xmlrpc-c-1.03.14/tools/xmlrpc_transport/../../src/.libs/libxmlrpc.so /mp/hdc1/xmlrpc-c-1.03.14/tools/xmlrpc_transport/../../lib/expat/xmlparse/.libs/libxmlrpc_xmlparse.so /mp/hdc1/xmlrpc-c-1.03.14/tools/xmlrpc_transport/../../lib/expat/xmltok/.libs/libxmlrpc_xmltok.so /mp/hdc1/xmlrpc-c-1.03.14/tools/xmlrpc_transport/../../lib/util/cmdline_parser.o /mp/hdc1/xmlrpc-c-1.03.14/tools/xmlrpc_transport/../../lib/util/getoptx.o -Wl,--rpath -Wl,/mp/hdc1/xmlrpc-c-1.03.14/src/.libs -Wl,--rpath -Wl,/mp/hdc1/xmlrpc-c-1.03.14/lib/expat/xmlparse/.libs -Wl,--rpath -Wl,/mp/hdc1/xmlrpc-c-1.03.14/lib/expat/xmltok/.libs -Wl,--rpath -Wl,/usr/local/lib" - -# This environment variable determines our operation mode. -if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then - # install mode needs the following variable: - link_against_libtool_libs=' /mp/hdc1/xmlrpc-c-1.03.14/tools/xmlrpc_transport/../../src/libxmlrpc_client.la /mp/hdc1/xmlrpc-c-1.03.14/tools/xmlrpc_transport/../../src/libxmlrpc.la /mp/hdc1/xmlrpc-c-1.03.14/tools/xmlrpc_transport/../../lib/expat/xmlparse/libxmlrpc_xmlparse.la /mp/hdc1/xmlrpc-c-1.03.14/tools/xmlrpc_transport/../../lib/expat/xmltok/libxmlrpc_xmltok.la' -else - # When we are sourced in execute mode, $file and $echo are already set. - if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then - echo="/syspathbasic/echo" - file="$0" - # Make sure echo works. - if test "X$1" = X--no-reexec; then - # Discard the --no-reexec flag, and continue. - shift - elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then - # Yippee, $echo works! - : - else - # Restart under the correct shell, and then maybe $echo will work. - exec /bin/sh "$0" --no-reexec ${1+"$@"} - fi - fi - - # Find the directory that this script lives in. - thisdir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` - test "x$thisdir" = "x$file" && thisdir=. - - # Follow symbolic links until we get to the real thisdir. - file=`ls -ld "$file" | sed -n 's/.*-> //p'` - while test -n "$file"; do - destdir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` - - # If there was a directory component, then change thisdir. - if test "x$destdir" != "x$file"; then - case "$destdir" in - [\/]* | [A-Za-z]:[\/]*) thisdir="$destdir" ;; - *) thisdir="$thisdir/$destdir" ;; - esac - fi - - file=`$echo "X$file" | $Xsed -e 's%^.*/%%'` - file=`ls -ld "$thisdir/$file" | sed -n 's/.*-> //p'` - done - - # Try to get the absolute directory name. - absdir=`cd "$thisdir" && pwd` - test -n "$absdir" && thisdir="$absdir" - - program=lt-'xmlrpc_transport' - progdir="$thisdir/.libs" - - if test ! -f "$progdir/$program" || \ - { file=`ls -1dt "$progdir/$program" "$progdir/../$program" 2>/dev/null | sed 1q`; \ - test "X$file" != "X$progdir/$program"; }; then - - file="$$-$program" - - if test ! -d "$progdir"; then - mkdir "$progdir" - else - rm -f "$progdir/$file" - fi - - # relink executable if necessary - if test -n "$relink_command"; then - if (cd "$thisdir" && eval $relink_command); then : - else - rm -f "$progdir/$file" - exit 1 - fi - fi - - mv -f "$progdir/$file" "$progdir/$program" 2>/dev/null || - { rm -f "$progdir/$program"; - mv -f "$progdir/$file" "$progdir/$program"; } - rm -f "$progdir/$file" - fi - - if test -f "$progdir/$program"; then - if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then - # Run the actual program with our arguments. - - # Export the path to the program. - PATH="$progdir:$PATH" - export PATH - - exec $program ${1+"$@"} - - $echo "$0: cannot exec $program ${1+"$@"}" - exit 1 - fi - else - # The program doesn't exist. - $echo "$0: error: $progdir/$program does not exist" 1>&2 - $echo "This script is just a wrapper for $program." 1>&2 - echo "See the libtool documentation for more information." 1>&2 - exit 1 - fi -fi diff --git a/libs/xmlrpc-c/tools/xmlrpc_transport/xmlrpc_transport.c b/libs/xmlrpc-c/tools/xmlrpc_transport/xmlrpc_transport.c index 0fe671d..39697b4 100644 --- a/libs/xmlrpc-c/tools/xmlrpc_transport/xmlrpc_transport.c +++ b/libs/xmlrpc-c/tools/xmlrpc_transport/xmlrpc_transport.c @@ -2,7 +2,7 @@ an XML-RPC call. */ -//#define _GNU_SOURCE +#define _XOPEN_SOURCE 600 /* Make sure strdup() is in */ #include #include diff --git a/libs/xmlrpc-c/transport_config.make b/libs/xmlrpc-c/transport_config.make deleted file mode 100644 index 5791af6..0000000 --- a/libs/xmlrpc-c/transport_config.make +++ /dev/null @@ -1,39 +0,0 @@ -# -*-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 - diff --git a/libs/xmlrpc-c/transport_config.mk b/libs/xmlrpc-c/transport_config.mk new file mode 100644 index 0000000..5791af6 --- /dev/null +++ b/libs/xmlrpc-c/transport_config.mk @@ -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 + diff --git a/libs/xmlrpc-c/unix-common.make b/libs/xmlrpc-c/unix-common.make deleted file mode 100644 index b684c70..0000000 --- a/libs/xmlrpc-c/unix-common.make +++ /dev/null @@ -1,79 +0,0 @@ -# -*-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)=%) diff --git a/libs/xmlrpc-c/unix-common.mk b/libs/xmlrpc-c/unix-common.mk new file mode 100644 index 0000000..8f5016c --- /dev/null +++ b/libs/xmlrpc-c/unix-common.mk @@ -0,0 +1,82 @@ +# -*-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 the rule to make +# a shared library (in common.mk). I.e. $@ is the name of the shared +# library file. + +# 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) $(LADD) $(LDFLAGS_SHLIB) -o $@ $^ + +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)=%) diff --git a/libs/xmlrpc-c/version.h b/libs/xmlrpc-c/version.h deleted file mode 100644 index 18e70f2..0000000 --- a/libs/xmlrpc-c/version.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef XMLRPC_C_VERSION_INCLUDED -#define XMLRPC_C_VERSION_INCLUDED -/* generated by Windows/mkvers.bat on Fri 05/23/2008 ... */ -#define XMLRPC_C_VERSION "Xmlrpc-c 1.14.99" -#define XMLRPC_VERSION_MAJOR 1 -#define XMLRPC_VERSION_MINOR 14 -#define XMLRPC_VERSION_POINT 99 -#endif diff --git a/libs/xmlrpc-c/version.mk b/libs/xmlrpc-c/version.mk new file mode 100644 index 0000000..b59310a --- /dev/null +++ b/libs/xmlrpc-c/version.mk @@ -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 = 26 +XMLRPC_POINT_RELEASE = 0 diff --git a/libs/xmlrpc-c/xmlrpc-c-config.in b/libs/xmlrpc-c/xmlrpc-c-config.in deleted file mode 100644 index 2095b5f..0000000 --- a/libs/xmlrpc-c/xmlrpc-c-config.in +++ /dev/null @@ -1,180 +0,0 @@ -#!/bin/sh -# Stolen from rep-config and adapted for use with xmlrpc-c. -# Other bits stolen from gnome-config & automake output. - -prefix=@prefix@ -exec_prefix=@exec_prefix@ - -bindir=@bindir@ -sbindir=@sbindir@ -libexecdir=@libexecdir@ -datadir=@datadir@ -sysconfdir=@sysconfdir@ -sharedstatedir=@sharedstatedir@ -localstatedir=@localstatedir@ -libdir=@libdir@ -infodir=@infodir@ -mandir=@mandir@ -includedir=@includedir@ - -pkgdatadir=$datadir/@PACKAGE@ -pkglibdir=$libdir/@PACKAGE@ -pkgincludedir=$includedir/@PACKAGE@ - -ENABLE_LIBXML2_BACKEND="@ENABLE_LIBXML2_BACKEND@" -MUST_BUILD_CURL_CLIENT="@MUST_BUILD_CURL_CLIENT@" -MUST_BUILD_WININET_CLIENT="@MUST_BUILD_WININET_CLIENT@" -MUST_BUILD_LIBWWW_CLIENT="@MUST_BUILD_LIBWWW_CLIENT@" - -usage="Usage: xmlrpc-c-config ...