Jeff 5 роки тому
батько
коміт
7781de0aa0
100 змінених файлів з 23506 додано та 0 видалено
  1. 39 0
      scbc.tools/Include/curl/Makefile.am
  2. 693 0
      scbc.tools/Include/curl/Makefile.in
  3. 2871 0
      scbc.tools/Include/curl/curl.h
  4. 77 0
      scbc.tools/Include/curl/curlver.h
  5. 112 0
      scbc.tools/Include/curl/easy.h
  6. 50 0
      scbc.tools/Include/curl/mprintf.h
  7. 441 0
      scbc.tools/Include/curl/multi.h
  8. 33 0
      scbc.tools/Include/curl/stdcheaders.h
  9. 493 0
      scbc.tools/Include/curl/system.h
  10. 698 0
      scbc.tools/Include/curl/typecheck-gcc.h
  11. 123 0
      scbc.tools/Include/curl/urlapi.h
  12. 376 0
      scbc.tools/Log4C/GlobalMacro.h
  13. 479 0
      scbc.tools/Log4C/Log4C.vcproj
  14. 3 0
      scbc.tools/Log4C/log4c.def
  15. 27 0
      scbc.tools/Log4C/log4c.h
  16. 251 0
      scbc.tools/Log4C/log4c/appender.h
  17. 71 0
      scbc.tools/Log4C/log4c/appender_typ_stream.h
  18. 58 0
      scbc.tools/Log4C/log4c/appender_type_mmap.h
  19. 120 0
      scbc.tools/Log4C/log4c/appender_type_rollingfile.h
  20. 67 0
      scbc.tools/Log4C/log4c/appender_type_stream.h
  21. 130 0
      scbc.tools/Log4C/log4c/appender_type_stream2.h
  22. 56 0
      scbc.tools/Log4C/log4c/appender_type_syslog.h
  23. 46 0
      scbc.tools/Log4C/log4c/buffer.h
  24. 651 0
      scbc.tools/Log4C/log4c/category.h
  25. 41 0
      scbc.tools/Log4C/log4c/config-win32.h
  26. 26 0
      scbc.tools/Log4C/log4c/config.h
  27. 46 0
      scbc.tools/Log4C/log4c/defs.h
  28. 65 0
      scbc.tools/Log4C/log4c/init.h
  29. 204 0
      scbc.tools/Log4C/log4c/layout.h
  30. 38 0
      scbc.tools/Log4C/log4c/layout_type_basic.h
  31. 42 0
      scbc.tools/Log4C/log4c/layout_type_basic_r.h
  32. 43 0
      scbc.tools/Log4C/log4c/layout_type_dated.h
  33. 45 0
      scbc.tools/Log4C/log4c/layout_type_dated_r.h
  34. 45 0
      scbc.tools/Log4C/log4c/layout_type_dated_threadid.h
  35. 73 0
      scbc.tools/Log4C/log4c/location_info.h
  36. 553 0
      scbc.tools/Log4C/log4c/log.h
  37. 89 0
      scbc.tools/Log4C/log4c/logging_event.h
  38. 56 0
      scbc.tools/Log4C/log4c/priority.h
  39. 70 0
      scbc.tools/Log4C/log4c/rc.h
  40. 215 0
      scbc.tools/Log4C/log4c/rollingpolicy.h
  41. 86 0
      scbc.tools/Log4C/log4c/rollingpolicy_type_sizewin.h
  42. 40 0
      scbc.tools/Log4C/log4c/sharedmemory.h
  43. 57 0
      scbc.tools/Log4C/log4c/version.h
  44. 676 0
      scbc.tools/Log4C/log4c/vos.h
  45. 238 0
      scbc.tools/Log4C/log4c/voscfg.h
  46. 19 0
      scbc.tools/Log4C/sd/defs.h
  47. 21 0
      scbc.tools/Log4C/sd/domnode-xml-parser.h
  48. 882 0
      scbc.tools/Log4C/sd/domnode-xml-scanner.h
  49. 33 0
      scbc.tools/Log4C/sd/domnode-xml.h
  50. 65 0
      scbc.tools/Log4C/sd/domnode.h
  51. 16 0
      scbc.tools/Log4C/sd/error.h
  52. 1014 0
      scbc.tools/Log4C/sd/expat.h
  53. 115 0
      scbc.tools/Log4C/sd/expat_external.h
  54. 43 0
      scbc.tools/Log4C/sd/factory.h
  55. 166 0
      scbc.tools/Log4C/sd/hash.h
  56. 190 0
      scbc.tools/Log4C/sd/list.h
  57. 43 0
      scbc.tools/Log4C/sd/malloc.h
  58. 137 0
      scbc.tools/Log4C/sd/sd_xplatform.h
  59. 59 0
      scbc.tools/Log4C/sd/sprintf.h
  60. 41 0
      scbc.tools/Log4C/sd/stack.h
  61. 132 0
      scbc.tools/cJson/JsonUtils.cpp
  62. 15 0
      scbc.tools/cJson/JsonUtils.h
  63. 132 0
      scbc.tools/cJson/Json_Type.h
  64. 2973 0
      scbc.tools/cJson/cJSON.c
  65. 285 0
      scbc.tools/cJson/cJSON.h
  66. 1457 0
      scbc.tools/cJson/cJSON_Utils.c
  67. 88 0
      scbc.tools/cJson/cJSON_Utils.h
  68. 136 0
      scbc.tools/filehelper/filehelper.cpp
  69. 61 0
      scbc.tools/filehelper/filehelper.h
  70. 327 0
      scbc.tools/filehelper/findfile.cpp
  71. 86 0
      scbc.tools/filehelper/findfile.h
  72. BIN
      scbc.tools/lib/Log4C.dll
  73. BIN
      scbc.tools/lib/Log4C.lib
  74. BIN
      scbc.tools/lib/libcurl.lib
  75. BIN
      scbc.tools/lib/libcurld.lib
  76. BIN
      scbc.tools/lib/libeay32.lib
  77. BIN
      scbc.tools/lib/ssleay32.lib
  78. 23 0
      scbc.tools/scbc.tools.sln
  79. 130 0
      scbc.tools/scbc.tools/Base64.cpp
  80. 70 0
      scbc.tools/scbc.tools/Base64.h
  81. 235 0
      scbc.tools/scbc.tools/CharConvert.cpp
  82. 22 0
      scbc.tools/scbc.tools/CharConvert.h
  83. 739 0
      scbc.tools/scbc.tools/CharEncoding.cpp
  84. 97 0
      scbc.tools/scbc.tools/CharEncoding.h
  85. 84 0
      scbc.tools/scbc.tools/CritSection.h
  86. 663 0
      scbc.tools/scbc.tools/CurlClient.cpp
  87. 92 0
      scbc.tools/scbc.tools/CurlClient.h
  88. 836 0
      scbc.tools/scbc.tools/Global.cpp
  89. 300 0
      scbc.tools/scbc.tools/Global.h
  90. 48 0
      scbc.tools/scbc.tools/ReadMe.txt
  91. 17 0
      scbc.tools/scbc.tools/Resource.h
  92. 27 0
      scbc.tools/scbc.tools/log4c.h
  93. 45 0
      scbc.tools/scbc.tools/scbc.tools.cpp
  94. 27 0
      scbc.tools/scbc.tools/scbc.tools.h
  95. 69 0
      scbc.tools/scbc.tools/scbc.tools.rc
  96. 408 0
      scbc.tools/scbc.tools/scbc.tools.vcproj
  97. 8 0
      scbc.tools/scbc.tools/stdafx.cpp
  98. 34 0
      scbc.tools/scbc.tools/stdafx.h
  99. 259 0
      scbc.tools/scbc.tools/stdint.h
  100. 24 0
      scbc.tools/scbc.tools/targetver.h

+ 39 - 0
scbc.tools/Include/curl/Makefile.am

@@ -0,0 +1,39 @@
+#***************************************************************************
+#                                  _   _ ____  _
+#  Project                     ___| | | |  _ \| |
+#                             / __| | | | |_) | |
+#                            | (__| |_| |  _ <| |___
+#                             \___|\___/|_| \_\_____|
+#
+# Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.haxx.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+###########################################################################
+pkginclude_HEADERS = \
+  curl.h curlver.h easy.h mprintf.h stdcheaders.h multi.h \
+  typecheck-gcc.h system.h urlapi.h
+
+pkgincludedir= $(includedir)/curl
+
+CHECKSRC = $(CS_$(V))
+CS_0 = @echo "  RUN     " $@;
+CS_1 =
+CS_ = $(CS_0)
+
+checksrc:
+	$(CHECKSRC)@PERL@ $(top_srcdir)/lib/checksrc.pl -D$(top_srcdir)/include/curl $(pkginclude_HEADERS)
+
+if CURLDEBUG
+# for debug builds, we scan the sources on all regular make invokes
+all-local: checksrc
+endif

+ 693 - 0
scbc.tools/Include/curl/Makefile.in

@@ -0,0 +1,693 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+  if test -z '$(MAKELEVEL)'; then \
+    false; \
+  elif test -n '$(MAKE_HOST)'; then \
+    true; \
+  elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+    true; \
+  else \
+    false; \
+  fi; \
+}
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \	]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = include/curl
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_compile_check_sizeof.m4 \
+	$(top_srcdir)/m4/curl-compilers.m4 \
+	$(top_srcdir)/m4/curl-confopts.m4 \
+	$(top_srcdir)/m4/curl-functions.m4 \
+	$(top_srcdir)/m4/curl-openssl.m4 \
+	$(top_srcdir)/m4/curl-override.m4 \
+	$(top_srcdir)/m4/curl-reentrant.m4 $(top_srcdir)/m4/libtool.m4 \
+	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+	$(top_srcdir)/m4/xc-am-iface.m4 \
+	$(top_srcdir)/m4/xc-cc-check.m4 \
+	$(top_srcdir)/m4/xc-lt-iface.m4 \
+	$(top_srcdir)/m4/xc-translit.m4 \
+	$(top_srcdir)/m4/xc-val-flgs.m4 \
+	$(top_srcdir)/m4/zz40-xc-ovr.m4 \
+	$(top_srcdir)/m4/zz50-xc-ovr.m4 \
+	$(top_srcdir)/m4/zz60-xc-ovr.m4 $(top_srcdir)/acinclude.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(pkginclude_HEADERS) \
+	$(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/lib/curl_config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+  for p in $$list; do echo "$$p $$p"; done | \
+  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+    if (++n[$$2] == $(am__install_max)) \
+      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+    END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+  test -z "$$files" \
+    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+         $(am__cd) "$$dir" && rm -f $$files; }; \
+  }
+am__installdirs = "$(DESTDIR)$(pkgincludedir)"
+HEADERS = $(pkginclude_HEADERS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__DIST_COMMON = $(srcdir)/Makefile.in
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+pkgincludedir = $(includedir)/curl
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AR_FLAGS = @AR_FLAGS@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BLANK_AT_MAKETIME = @BLANK_AT_MAKETIME@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CFLAG_CURL_SYMBOL_HIDING = @CFLAG_CURL_SYMBOL_HIDING@
+CONFIGURE_OPTIONS = @CONFIGURE_OPTIONS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CPPFLAG_CURL_STATICLIB = @CPPFLAG_CURL_STATICLIB@
+CURLVERSION = @CURLVERSION@
+CURL_CA_BUNDLE = @CURL_CA_BUNDLE@
+CURL_CFLAG_EXTRAS = @CURL_CFLAG_EXTRAS@
+CURL_DISABLE_DICT = @CURL_DISABLE_DICT@
+CURL_DISABLE_FILE = @CURL_DISABLE_FILE@
+CURL_DISABLE_FTP = @CURL_DISABLE_FTP@
+CURL_DISABLE_GOPHER = @CURL_DISABLE_GOPHER@
+CURL_DISABLE_HTTP = @CURL_DISABLE_HTTP@
+CURL_DISABLE_IMAP = @CURL_DISABLE_IMAP@
+CURL_DISABLE_LDAP = @CURL_DISABLE_LDAP@
+CURL_DISABLE_LDAPS = @CURL_DISABLE_LDAPS@
+CURL_DISABLE_POP3 = @CURL_DISABLE_POP3@
+CURL_DISABLE_PROXY = @CURL_DISABLE_PROXY@
+CURL_DISABLE_RTSP = @CURL_DISABLE_RTSP@
+CURL_DISABLE_SMB = @CURL_DISABLE_SMB@
+CURL_DISABLE_SMTP = @CURL_DISABLE_SMTP@
+CURL_DISABLE_TELNET = @CURL_DISABLE_TELNET@
+CURL_DISABLE_TFTP = @CURL_DISABLE_TFTP@
+CURL_LT_SHLIB_VERSIONED_FLAVOUR = @CURL_LT_SHLIB_VERSIONED_FLAVOUR@
+CURL_NETWORK_AND_TIME_LIBS = @CURL_NETWORK_AND_TIME_LIBS@
+CURL_NETWORK_LIBS = @CURL_NETWORK_LIBS@
+CURL_WITH_MULTI_SSL = @CURL_WITH_MULTI_SSL@
+CYGPATH_W = @CYGPATH_W@
+DEFAULT_SSL_BACKEND = @DEFAULT_SSL_BACKEND@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ENABLE_SHARED = @ENABLE_SHARED@
+ENABLE_STATIC = @ENABLE_STATIC@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FISH_FUNCTIONS_DIR = @FISH_FUNCTIONS_DIR@
+GCOV = @GCOV@
+GREP = @GREP@
+HAVE_BROTLI = @HAVE_BROTLI@
+HAVE_GNUTLS_SRP = @HAVE_GNUTLS_SRP@
+HAVE_LDAP_SSL = @HAVE_LDAP_SSL@
+HAVE_LIBZ = @HAVE_LIBZ@
+HAVE_OPENSSL_SRP = @HAVE_OPENSSL_SRP@
+HAVE_PROTO_BSDSOCKET_H = @HAVE_PROTO_BSDSOCKET_H@
+IDN_ENABLED = @IDN_ENABLED@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IPV6_ENABLED = @IPV6_ENABLED@
+LCOV = @LCOV@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBCURL_LIBS = @LIBCURL_LIBS@
+LIBMETALINK_CPPFLAGS = @LIBMETALINK_CPPFLAGS@
+LIBMETALINK_LDFLAGS = @LIBMETALINK_LDFLAGS@
+LIBMETALINK_LIBS = @LIBMETALINK_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MANOPT = @MANOPT@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NROFF = @NROFF@
+NSS_LIBS = @NSS_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKGADD_NAME = @PKGADD_NAME@
+PKGADD_PKG = @PKGADD_PKG@
+PKGADD_VENDOR = @PKGADD_VENDOR@
+PKGCONFIG = @PKGCONFIG@
+RANDOM_FILE = @RANDOM_FILE@
+RANLIB = @RANLIB@
+REQUIRE_LIB_DEPS = @REQUIRE_LIB_DEPS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SSL_BACKENDS = @SSL_BACKENDS@
+SSL_ENABLED = @SSL_ENABLED@
+SSL_LIBS = @SSL_LIBS@
+STRIP = @STRIP@
+SUPPORT_FEATURES = @SUPPORT_FEATURES@
+SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
+USE_ARES = @USE_ARES@
+USE_GNUTLS = @USE_GNUTLS@
+USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@
+USE_LIBRTMP = @USE_LIBRTMP@
+USE_LIBSSH = @USE_LIBSSH@
+USE_LIBSSH2 = @USE_LIBSSH2@
+USE_MBEDTLS = @USE_MBEDTLS@
+USE_MESALINK = @USE_MESALINK@
+USE_NGHTTP2 = @USE_NGHTTP2@
+USE_NSS = @USE_NSS@
+USE_OPENLDAP = @USE_OPENLDAP@
+USE_SCHANNEL = @USE_SCHANNEL@
+USE_SECTRANSP = @USE_SECTRANSP@
+USE_UNIX_SOCKETS = @USE_UNIX_SOCKETS@
+USE_WINDOWS_SSPI = @USE_WINDOWS_SSPI@
+USE_WOLFSSL = @USE_WOLFSSL@
+VERSION = @VERSION@
+VERSIONNUM = @VERSIONNUM@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSH_FUNCTIONS_DIR = @ZSH_FUNCTIONS_DIR@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libext = @libext@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+subdirs = @subdirs@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+
+#***************************************************************************
+#                                  _   _ ____  _
+#  Project                     ___| | | |  _ \| |
+#                             / __| | | | |_) | |
+#                            | (__| |_| |  _ <| |___
+#                             \___|\___/|_| \_\_____|
+#
+# Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.haxx.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+###########################################################################
+pkginclude_HEADERS = \
+  curl.h curlver.h easy.h mprintf.h stdcheaders.h multi.h \
+  typecheck-gcc.h system.h urlapi.h
+
+CHECKSRC = $(CS_$(V))
+CS_0 = @echo "  RUN     " $@;
+CS_1 = 
+CS_ = $(CS_0)
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu include/curl/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu include/curl/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+install-pkgincludeHEADERS: $(pkginclude_HEADERS)
+	@$(NORMAL_INSTALL)
+	@list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \
+	if test -n "$$list"; then \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(pkgincludedir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(pkgincludedir)" || exit 1; \
+	fi; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkgincludedir)'"; \
+	  $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkgincludedir)" || exit $$?; \
+	done
+
+uninstall-pkgincludeHEADERS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	dir='$(DESTDIR)$(pkgincludedir)'; $(am__uninstall_files_from_dir)
+
+ID: $(am__tagged_files)
+	$(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	set x; \
+	here=`pwd`; \
+	$(am__define_uniq_tagged_files); \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	$(am__define_uniq_tagged_files); \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+	list='$(am__tagged_files)'; \
+	case "$(srcdir)" in \
+	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+	  *) sdir=$(subdir)/$(srcdir) ;; \
+	esac; \
+	for i in $$list; do \
+	  if test -f "$$i"; then \
+	    echo "$(subdir)/$$i"; \
+	  else \
+	    echo "$$sdir/$$i"; \
+	  fi; \
+	done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+	  else \
+	    test -f "$(distdir)/$$file" \
+	    || cp -p $$d/$$file "$(distdir)/$$file" \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+@CURLDEBUG_FALSE@all-local:
+all-am: Makefile $(HEADERS) all-local
+installdirs:
+	for dir in "$(DESTDIR)$(pkgincludedir)"; do \
+	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+	done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	if test -z '$(STRIP)'; then \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	      install; \
+	else \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+	fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pkgincludeHEADERS
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pkgincludeHEADERS
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am all-local check check-am clean \
+	clean-generic clean-libtool cscopelist-am ctags ctags-am \
+	distclean distclean-generic distclean-libtool distclean-tags \
+	distdir dvi dvi-am html html-am info info-am install \
+	install-am install-data install-data-am install-dvi \
+	install-dvi-am install-exec install-exec-am install-html \
+	install-html-am install-info install-info-am install-man \
+	install-pdf install-pdf-am install-pkgincludeHEADERS \
+	install-ps install-ps-am install-strip installcheck \
+	installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-generic \
+	mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
+	uninstall-am uninstall-pkgincludeHEADERS
+
+.PRECIOUS: Makefile
+
+
+checksrc:
+	$(CHECKSRC)@PERL@ $(top_srcdir)/lib/checksrc.pl -D$(top_srcdir)/include/curl $(pkginclude_HEADERS)
+
+# for debug builds, we scan the sources on all regular make invokes
+@CURLDEBUG_TRUE@all-local: checksrc
+
+# 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:

+ 2871 - 0
scbc.tools/Include/curl/curl.h

@@ -0,0 +1,2871 @@
+#ifndef __CURL_CURL_H
+#define __CURL_CURL_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * If you have libcurl problems, all docs and details are found here:
+ *   https://curl.haxx.se/libcurl/
+ *
+ * curl-library mailing list subscription and unsubscription web interface:
+ *   https://cool.haxx.se/mailman/listinfo/curl-library/
+ */
+
+#ifdef CURL_NO_OLDIES
+#define CURL_STRICTER
+#endif
+
+#include "curlver.h"         /* libcurl version defines   */
+#include "system.h"          /* determine things run-time */
+
+/*
+ * Define WIN32 when build target is Win32 API
+ */
+
+#if (defined(_WIN32) || defined(__WIN32__)) && \
+     !defined(WIN32) && !defined(__SYMBIAN32__)
+#define WIN32
+#endif
+
+#include <stdio.h>
+#include <limits.h>
+
+#if defined(__FreeBSD__) && (__FreeBSD__ >= 2)
+/* Needed for __FreeBSD_version symbol definition */
+#include <osreldate.h>
+#endif
+
+/* The include stuff here below is mainly for time_t! */
+#include <sys/types.h>
+#include <time.h>
+
+#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__CYGWIN__)
+#if !(defined(_WINSOCKAPI_) || defined(_WINSOCK_H) || \
+      defined(__LWIP_OPT_H__) || defined(LWIP_HDR_OPT_H))
+/* The check above prevents the winsock2 inclusion if winsock.h already was
+   included, since they can't co-exist without problems */
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#endif
+#endif
+
+/* HP-UX systems version 9, 10 and 11 lack sys/select.h and so does oldish
+   libc5-based Linux systems. Only include it on systems that are known to
+   require it! */
+#if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \
+    defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \
+    defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \
+    defined(__CYGWIN__) || \
+   (defined(__FreeBSD_version) && (__FreeBSD_version < 800000))
+#include <sys/select.h>
+#endif
+
+#if !defined(WIN32) && !defined(_WIN32_WCE)
+#include <sys/socket.h>
+#endif
+
+#if !defined(WIN32) && !defined(__WATCOMC__) && !defined(__VXWORKS__)
+#include <sys/time.h>
+#endif
+
+#ifdef __BEOS__
+#include <support/SupportDefs.h>
+#endif
+
+/* Compatibility for non-Clang compilers */
+#ifndef __has_declspec_attribute
+#  define __has_declspec_attribute(x) 0
+#endif
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#if defined(BUILDING_LIBCURL) || defined(CURL_STRICTER)
+typedef struct Curl_easy CURL;
+typedef struct Curl_share CURLSH;
+#else
+typedef void CURL;
+typedef void CURLSH;
+#endif
+
+/*
+ * libcurl external API function linkage decorations.
+ */
+
+#ifdef CURL_STATICLIB
+#  define CURL_EXTERN
+#elif defined(WIN32) || defined(__SYMBIAN32__) || \
+     (__has_declspec_attribute(dllexport) && \
+      __has_declspec_attribute(dllimport))
+#  if defined(BUILDING_LIBCURL)
+#    define CURL_EXTERN  __declspec(dllexport)
+#  else
+#    define CURL_EXTERN  __declspec(dllimport)
+#  endif
+#elif defined(BUILDING_LIBCURL) && defined(CURL_HIDDEN_SYMBOLS)
+#  define CURL_EXTERN CURL_EXTERN_SYMBOL
+#else
+#  define CURL_EXTERN
+#endif
+
+#ifndef curl_socket_typedef
+/* socket typedef */
+#if defined(WIN32) && !defined(__LWIP_OPT_H__) && !defined(LWIP_HDR_OPT_H)
+typedef SOCKET curl_socket_t;
+#define CURL_SOCKET_BAD INVALID_SOCKET
+#else
+typedef int curl_socket_t;
+#define CURL_SOCKET_BAD -1
+#endif
+#define curl_socket_typedef
+#endif /* curl_socket_typedef */
+
+/* enum for the different supported SSL backends */
+typedef enum {
+  CURLSSLBACKEND_NONE = 0,
+  CURLSSLBACKEND_OPENSSL = 1,
+  CURLSSLBACKEND_GNUTLS = 2,
+  CURLSSLBACKEND_NSS = 3,
+  CURLSSLBACKEND_OBSOLETE4 = 4,  /* Was QSOSSL. */
+  CURLSSLBACKEND_GSKIT = 5,
+  CURLSSLBACKEND_POLARSSL = 6,
+  CURLSSLBACKEND_WOLFSSL = 7,
+  CURLSSLBACKEND_SCHANNEL = 8,
+  CURLSSLBACKEND_SECURETRANSPORT = 9,
+  CURLSSLBACKEND_AXTLS = 10, /* never used since 7.63.0 */
+  CURLSSLBACKEND_MBEDTLS = 11,
+  CURLSSLBACKEND_MESALINK = 12
+} curl_sslbackend;
+
+/* aliases for library clones and renames */
+#define CURLSSLBACKEND_LIBRESSL CURLSSLBACKEND_OPENSSL
+#define CURLSSLBACKEND_BORINGSSL CURLSSLBACKEND_OPENSSL
+
+/* deprecated names: */
+#define CURLSSLBACKEND_CYASSL CURLSSLBACKEND_WOLFSSL
+#define CURLSSLBACKEND_DARWINSSL CURLSSLBACKEND_SECURETRANSPORT
+
+struct curl_httppost {
+  struct curl_httppost *next;       /* next entry in the list */
+  char *name;                       /* pointer to allocated name */
+  long namelength;                  /* length of name length */
+  char *contents;                   /* pointer to allocated data contents */
+  long contentslength;              /* length of contents field, see also
+                                       CURL_HTTPPOST_LARGE */
+  char *buffer;                     /* pointer to allocated buffer contents */
+  long bufferlength;                /* length of buffer field */
+  char *contenttype;                /* Content-Type */
+  struct curl_slist *contentheader; /* list of extra headers for this form */
+  struct curl_httppost *more;       /* if one field name has more than one
+                                       file, this link should link to following
+                                       files */
+  long flags;                       /* as defined below */
+
+/* specified content is a file name */
+#define CURL_HTTPPOST_FILENAME (1<<0)
+/* specified content is a file name */
+#define CURL_HTTPPOST_READFILE (1<<1)
+/* name is only stored pointer do not free in formfree */
+#define CURL_HTTPPOST_PTRNAME (1<<2)
+/* contents is only stored pointer do not free in formfree */
+#define CURL_HTTPPOST_PTRCONTENTS (1<<3)
+/* upload file from buffer */
+#define CURL_HTTPPOST_BUFFER (1<<4)
+/* upload file from pointer contents */
+#define CURL_HTTPPOST_PTRBUFFER (1<<5)
+/* upload file contents by using the regular read callback to get the data and
+   pass the given pointer as custom pointer */
+#define CURL_HTTPPOST_CALLBACK (1<<6)
+/* use size in 'contentlen', added in 7.46.0 */
+#define CURL_HTTPPOST_LARGE (1<<7)
+
+  char *showfilename;               /* The file name to show. If not set, the
+                                       actual file name will be used (if this
+                                       is a file part) */
+  void *userp;                      /* custom pointer used for
+                                       HTTPPOST_CALLBACK posts */
+  curl_off_t contentlen;            /* alternative length of contents
+                                       field. Used if CURL_HTTPPOST_LARGE is
+                                       set. Added in 7.46.0 */
+};
+
+/* This is the CURLOPT_PROGRESSFUNCTION callback prototype. It is now
+   considered deprecated but was the only choice up until 7.31.0 */
+typedef int (*curl_progress_callback)(void *clientp,
+                                      double dltotal,
+                                      double dlnow,
+                                      double ultotal,
+                                      double ulnow);
+
+/* This is the CURLOPT_XFERINFOFUNCTION callback prototype. It was introduced
+   in 7.32.0, avoids the use of floating point numbers and provides more
+   detailed information. */
+typedef int (*curl_xferinfo_callback)(void *clientp,
+                                      curl_off_t dltotal,
+                                      curl_off_t dlnow,
+                                      curl_off_t ultotal,
+                                      curl_off_t ulnow);
+
+#ifndef CURL_MAX_READ_SIZE
+  /* The maximum receive buffer size configurable via CURLOPT_BUFFERSIZE. */
+#define CURL_MAX_READ_SIZE 524288
+#endif
+
+#ifndef CURL_MAX_WRITE_SIZE
+  /* Tests have proven that 20K is a very bad buffer size for uploads on
+     Windows, while 16K for some odd reason performed a lot better.
+     We do the ifndef check to allow this value to easier be changed at build
+     time for those who feel adventurous. The practical minimum is about
+     400 bytes since libcurl uses a buffer of this size as a scratch area
+     (unrelated to network send operations). */
+#define CURL_MAX_WRITE_SIZE 16384
+#endif
+
+#ifndef CURL_MAX_HTTP_HEADER
+/* The only reason to have a max limit for this is to avoid the risk of a bad
+   server feeding libcurl with a never-ending header that will cause reallocs
+   infinitely */
+#define CURL_MAX_HTTP_HEADER (100*1024)
+#endif
+
+/* This is a magic return code for the write callback that, when returned,
+   will signal libcurl to pause receiving on the current transfer. */
+#define CURL_WRITEFUNC_PAUSE 0x10000001
+
+typedef size_t (*curl_write_callback)(char *buffer,
+                                      size_t size,
+                                      size_t nitems,
+                                      void *outstream);
+
+/* This callback will be called when a new resolver request is made */
+typedef int (*curl_resolver_start_callback)(void *resolver_state,
+                                            void *reserved, void *userdata);
+
+/* enumeration of file types */
+typedef enum {
+  CURLFILETYPE_FILE = 0,
+  CURLFILETYPE_DIRECTORY,
+  CURLFILETYPE_SYMLINK,
+  CURLFILETYPE_DEVICE_BLOCK,
+  CURLFILETYPE_DEVICE_CHAR,
+  CURLFILETYPE_NAMEDPIPE,
+  CURLFILETYPE_SOCKET,
+  CURLFILETYPE_DOOR, /* is possible only on Sun Solaris now */
+
+  CURLFILETYPE_UNKNOWN /* should never occur */
+} curlfiletype;
+
+#define CURLFINFOFLAG_KNOWN_FILENAME    (1<<0)
+#define CURLFINFOFLAG_KNOWN_FILETYPE    (1<<1)
+#define CURLFINFOFLAG_KNOWN_TIME        (1<<2)
+#define CURLFINFOFLAG_KNOWN_PERM        (1<<3)
+#define CURLFINFOFLAG_KNOWN_UID         (1<<4)
+#define CURLFINFOFLAG_KNOWN_GID         (1<<5)
+#define CURLFINFOFLAG_KNOWN_SIZE        (1<<6)
+#define CURLFINFOFLAG_KNOWN_HLINKCOUNT  (1<<7)
+
+/* Content of this structure depends on information which is known and is
+   achievable (e.g. by FTP LIST parsing). Please see the url_easy_setopt(3) man
+   page for callbacks returning this structure -- some fields are mandatory,
+   some others are optional. The FLAG field has special meaning. */
+struct curl_fileinfo {
+  char *filename;
+  curlfiletype filetype;
+  time_t time; /* always zero! */
+  unsigned int perm;
+  int uid;
+  int gid;
+  curl_off_t size;
+  long int hardlinks;
+
+  struct {
+    /* If some of these fields is not NULL, it is a pointer to b_data. */
+    char *time;
+    char *perm;
+    char *user;
+    char *group;
+    char *target; /* pointer to the target filename of a symlink */
+  } strings;
+
+  unsigned int flags;
+
+  /* used internally */
+  char *b_data;
+  size_t b_size;
+  size_t b_used;
+};
+
+/* return codes for CURLOPT_CHUNK_BGN_FUNCTION */
+#define CURL_CHUNK_BGN_FUNC_OK      0
+#define CURL_CHUNK_BGN_FUNC_FAIL    1 /* tell the lib to end the task */
+#define CURL_CHUNK_BGN_FUNC_SKIP    2 /* skip this chunk over */
+
+/* if splitting of data transfer is enabled, this callback is called before
+   download of an individual chunk started. Note that parameter "remains" works
+   only for FTP wildcard downloading (for now), otherwise is not used */
+typedef long (*curl_chunk_bgn_callback)(const void *transfer_info,
+                                        void *ptr,
+                                        int remains);
+
+/* return codes for CURLOPT_CHUNK_END_FUNCTION */
+#define CURL_CHUNK_END_FUNC_OK      0
+#define CURL_CHUNK_END_FUNC_FAIL    1 /* tell the lib to end the task */
+
+/* If splitting of data transfer is enabled this callback is called after
+   download of an individual chunk finished.
+   Note! After this callback was set then it have to be called FOR ALL chunks.
+   Even if downloading of this chunk was skipped in CHUNK_BGN_FUNC.
+   This is the reason why we don't need "transfer_info" parameter in this
+   callback and we are not interested in "remains" parameter too. */
+typedef long (*curl_chunk_end_callback)(void *ptr);
+
+/* return codes for FNMATCHFUNCTION */
+#define CURL_FNMATCHFUNC_MATCH    0 /* string corresponds to the pattern */
+#define CURL_FNMATCHFUNC_NOMATCH  1 /* pattern doesn't match the string */
+#define CURL_FNMATCHFUNC_FAIL     2 /* an error occurred */
+
+/* callback type for wildcard downloading pattern matching. If the
+   string matches the pattern, return CURL_FNMATCHFUNC_MATCH value, etc. */
+typedef int (*curl_fnmatch_callback)(void *ptr,
+                                     const char *pattern,
+                                     const char *string);
+
+/* These are the return codes for the seek callbacks */
+#define CURL_SEEKFUNC_OK       0
+#define CURL_SEEKFUNC_FAIL     1 /* fail the entire transfer */
+#define CURL_SEEKFUNC_CANTSEEK 2 /* tell libcurl seeking can't be done, so
+                                    libcurl might try other means instead */
+typedef int (*curl_seek_callback)(void *instream,
+                                  curl_off_t offset,
+                                  int origin); /* 'whence' */
+
+/* This is a return code for the read callback that, when returned, will
+   signal libcurl to immediately abort the current transfer. */
+#define CURL_READFUNC_ABORT 0x10000000
+/* This is a return code for the read callback that, when returned, will
+   signal libcurl to pause sending data on the current transfer. */
+#define CURL_READFUNC_PAUSE 0x10000001
+
+/* Return code for when the trailing headers' callback has terminated
+   without any errors*/
+#define CURL_TRAILERFUNC_OK 0
+/* Return code for when was an error in the trailing header's list and we
+  want to abort the request */
+#define CURL_TRAILERFUNC_ABORT 1
+
+typedef size_t (*curl_read_callback)(char *buffer,
+                                      size_t size,
+                                      size_t nitems,
+                                      void *instream);
+
+typedef int (*curl_trailer_callback)(struct curl_slist **list,
+                                      void *userdata);
+
+typedef enum {
+  CURLSOCKTYPE_IPCXN,  /* socket created for a specific IP connection */
+  CURLSOCKTYPE_ACCEPT, /* socket created by accept() call */
+  CURLSOCKTYPE_LAST    /* never use */
+} curlsocktype;
+
+/* The return code from the sockopt_callback can signal information back
+   to libcurl: */
+#define CURL_SOCKOPT_OK 0
+#define CURL_SOCKOPT_ERROR 1 /* causes libcurl to abort and return
+                                CURLE_ABORTED_BY_CALLBACK */
+#define CURL_SOCKOPT_ALREADY_CONNECTED 2
+
+typedef int (*curl_sockopt_callback)(void *clientp,
+                                     curl_socket_t curlfd,
+                                     curlsocktype purpose);
+
+struct curl_sockaddr {
+  int family;
+  int socktype;
+  int protocol;
+  unsigned int addrlen; /* addrlen was a socklen_t type before 7.18.0 but it
+                           turned really ugly and painful on the systems that
+                           lack this type */
+  struct sockaddr addr;
+};
+
+typedef curl_socket_t
+(*curl_opensocket_callback)(void *clientp,
+                            curlsocktype purpose,
+                            struct curl_sockaddr *address);
+
+typedef int
+(*curl_closesocket_callback)(void *clientp, curl_socket_t item);
+
+typedef enum {
+  CURLIOE_OK,            /* I/O operation successful */
+  CURLIOE_UNKNOWNCMD,    /* command was unknown to callback */
+  CURLIOE_FAILRESTART,   /* failed to restart the read */
+  CURLIOE_LAST           /* never use */
+} curlioerr;
+
+typedef enum {
+  CURLIOCMD_NOP,         /* no operation */
+  CURLIOCMD_RESTARTREAD, /* restart the read stream from start */
+  CURLIOCMD_LAST         /* never use */
+} curliocmd;
+
+typedef curlioerr (*curl_ioctl_callback)(CURL *handle,
+                                         int cmd,
+                                         void *clientp);
+
+#ifndef CURL_DID_MEMORY_FUNC_TYPEDEFS
+/*
+ * The following typedef's are signatures of malloc, free, realloc, strdup and
+ * calloc respectively.  Function pointers of these types can be passed to the
+ * curl_global_init_mem() function to set user defined memory management
+ * callback routines.
+ */
+typedef void *(*curl_malloc_callback)(size_t size);
+typedef void (*curl_free_callback)(void *ptr);
+typedef void *(*curl_realloc_callback)(void *ptr, size_t size);
+typedef char *(*curl_strdup_callback)(const char *str);
+typedef void *(*curl_calloc_callback)(size_t nmemb, size_t size);
+
+#define CURL_DID_MEMORY_FUNC_TYPEDEFS
+#endif
+
+/* the kind of data that is passed to information_callback*/
+typedef enum {
+  CURLINFO_TEXT = 0,
+  CURLINFO_HEADER_IN,    /* 1 */
+  CURLINFO_HEADER_OUT,   /* 2 */
+  CURLINFO_DATA_IN,      /* 3 */
+  CURLINFO_DATA_OUT,     /* 4 */
+  CURLINFO_SSL_DATA_IN,  /* 5 */
+  CURLINFO_SSL_DATA_OUT, /* 6 */
+  CURLINFO_END
+} curl_infotype;
+
+typedef int (*curl_debug_callback)
+       (CURL *handle,      /* the handle/transfer this concerns */
+        curl_infotype type, /* what kind of data */
+        char *data,        /* points to the data */
+        size_t size,       /* size of the data pointed to */
+        void *userptr);    /* whatever the user please */
+
+/* All possible error codes from all sorts of curl functions. Future versions
+   may return other values, stay prepared.
+
+   Always add new return codes last. Never *EVER* remove any. The return
+   codes must remain the same!
+ */
+
+typedef enum {
+  CURLE_OK = 0,
+  CURLE_UNSUPPORTED_PROTOCOL,    /* 1 */
+  CURLE_FAILED_INIT,             /* 2 */
+  CURLE_URL_MALFORMAT,           /* 3 */
+  CURLE_NOT_BUILT_IN,            /* 4 - [was obsoleted in August 2007 for
+                                    7.17.0, reused in April 2011 for 7.21.5] */
+  CURLE_COULDNT_RESOLVE_PROXY,   /* 5 */
+  CURLE_COULDNT_RESOLVE_HOST,    /* 6 */
+  CURLE_COULDNT_CONNECT,         /* 7 */
+  CURLE_WEIRD_SERVER_REPLY,      /* 8 */
+  CURLE_REMOTE_ACCESS_DENIED,    /* 9 a service was denied by the server
+                                    due to lack of access - when login fails
+                                    this is not returned. */
+  CURLE_FTP_ACCEPT_FAILED,       /* 10 - [was obsoleted in April 2006 for
+                                    7.15.4, reused in Dec 2011 for 7.24.0]*/
+  CURLE_FTP_WEIRD_PASS_REPLY,    /* 11 */
+  CURLE_FTP_ACCEPT_TIMEOUT,      /* 12 - timeout occurred accepting server
+                                    [was obsoleted in August 2007 for 7.17.0,
+                                    reused in Dec 2011 for 7.24.0]*/
+  CURLE_FTP_WEIRD_PASV_REPLY,    /* 13 */
+  CURLE_FTP_WEIRD_227_FORMAT,    /* 14 */
+  CURLE_FTP_CANT_GET_HOST,       /* 15 */
+  CURLE_HTTP2,                   /* 16 - A problem in the http2 framing layer.
+                                    [was obsoleted in August 2007 for 7.17.0,
+                                    reused in July 2014 for 7.38.0] */
+  CURLE_FTP_COULDNT_SET_TYPE,    /* 17 */
+  CURLE_PARTIAL_FILE,            /* 18 */
+  CURLE_FTP_COULDNT_RETR_FILE,   /* 19 */
+  CURLE_OBSOLETE20,              /* 20 - NOT USED */
+  CURLE_QUOTE_ERROR,             /* 21 - quote command failure */
+  CURLE_HTTP_RETURNED_ERROR,     /* 22 */
+  CURLE_WRITE_ERROR,             /* 23 */
+  CURLE_OBSOLETE24,              /* 24 - NOT USED */
+  CURLE_UPLOAD_FAILED,           /* 25 - failed upload "command" */
+  CURLE_READ_ERROR,              /* 26 - couldn't open/read from file */
+  CURLE_OUT_OF_MEMORY,           /* 27 */
+  /* Note: CURLE_OUT_OF_MEMORY may sometimes indicate a conversion error
+           instead of a memory allocation error if CURL_DOES_CONVERSIONS
+           is defined
+  */
+  CURLE_OPERATION_TIMEDOUT,      /* 28 - the timeout time was reached */
+  CURLE_OBSOLETE29,              /* 29 - NOT USED */
+  CURLE_FTP_PORT_FAILED,         /* 30 - FTP PORT operation failed */
+  CURLE_FTP_COULDNT_USE_REST,    /* 31 - the REST command failed */
+  CURLE_OBSOLETE32,              /* 32 - NOT USED */
+  CURLE_RANGE_ERROR,             /* 33 - RANGE "command" didn't work */
+  CURLE_HTTP_POST_ERROR,         /* 34 */
+  CURLE_SSL_CONNECT_ERROR,       /* 35 - wrong when connecting with SSL */
+  CURLE_BAD_DOWNLOAD_RESUME,     /* 36 - couldn't resume download */
+  CURLE_FILE_COULDNT_READ_FILE,  /* 37 */
+  CURLE_LDAP_CANNOT_BIND,        /* 38 */
+  CURLE_LDAP_SEARCH_FAILED,      /* 39 */
+  CURLE_OBSOLETE40,              /* 40 - NOT USED */
+  CURLE_FUNCTION_NOT_FOUND,      /* 41 - NOT USED starting with 7.53.0 */
+  CURLE_ABORTED_BY_CALLBACK,     /* 42 */
+  CURLE_BAD_FUNCTION_ARGUMENT,   /* 43 */
+  CURLE_OBSOLETE44,              /* 44 - NOT USED */
+  CURLE_INTERFACE_FAILED,        /* 45 - CURLOPT_INTERFACE failed */
+  CURLE_OBSOLETE46,              /* 46 - NOT USED */
+  CURLE_TOO_MANY_REDIRECTS,      /* 47 - catch endless re-direct loops */
+  CURLE_UNKNOWN_OPTION,          /* 48 - User specified an unknown option */
+  CURLE_TELNET_OPTION_SYNTAX,    /* 49 - Malformed telnet option */
+  CURLE_OBSOLETE50,              /* 50 - NOT USED */
+  CURLE_OBSOLETE51,              /* 51 - NOT USED */
+  CURLE_GOT_NOTHING,             /* 52 - when this is a specific error */
+  CURLE_SSL_ENGINE_NOTFOUND,     /* 53 - SSL crypto engine not found */
+  CURLE_SSL_ENGINE_SETFAILED,    /* 54 - can not set SSL crypto engine as
+                                    default */
+  CURLE_SEND_ERROR,              /* 55 - failed sending network data */
+  CURLE_RECV_ERROR,              /* 56 - failure in receiving network data */
+  CURLE_OBSOLETE57,              /* 57 - NOT IN USE */
+  CURLE_SSL_CERTPROBLEM,         /* 58 - problem with the local certificate */
+  CURLE_SSL_CIPHER,              /* 59 - couldn't use specified cipher */
+  CURLE_PEER_FAILED_VERIFICATION, /* 60 - peer's certificate or fingerprint
+                                     wasn't verified fine */
+  CURLE_BAD_CONTENT_ENCODING,    /* 61 - Unrecognized/bad encoding */
+  CURLE_LDAP_INVALID_URL,        /* 62 - Invalid LDAP URL */
+  CURLE_FILESIZE_EXCEEDED,       /* 63 - Maximum file size exceeded */
+  CURLE_USE_SSL_FAILED,          /* 64 - Requested FTP SSL level failed */
+  CURLE_SEND_FAIL_REWIND,        /* 65 - Sending the data requires a rewind
+                                    that failed */
+  CURLE_SSL_ENGINE_INITFAILED,   /* 66 - failed to initialise ENGINE */
+  CURLE_LOGIN_DENIED,            /* 67 - user, password or similar was not
+                                    accepted and we failed to login */
+  CURLE_TFTP_NOTFOUND,           /* 68 - file not found on server */
+  CURLE_TFTP_PERM,               /* 69 - permission problem on server */
+  CURLE_REMOTE_DISK_FULL,        /* 70 - out of disk space on server */
+  CURLE_TFTP_ILLEGAL,            /* 71 - Illegal TFTP operation */
+  CURLE_TFTP_UNKNOWNID,          /* 72 - Unknown transfer ID */
+  CURLE_REMOTE_FILE_EXISTS,      /* 73 - File already exists */
+  CURLE_TFTP_NOSUCHUSER,         /* 74 - No such user */
+  CURLE_CONV_FAILED,             /* 75 - conversion failed */
+  CURLE_CONV_REQD,               /* 76 - caller must register conversion
+                                    callbacks using curl_easy_setopt options
+                                    CURLOPT_CONV_FROM_NETWORK_FUNCTION,
+                                    CURLOPT_CONV_TO_NETWORK_FUNCTION, and
+                                    CURLOPT_CONV_FROM_UTF8_FUNCTION */
+  CURLE_SSL_CACERT_BADFILE,      /* 77 - could not load CACERT file, missing
+                                    or wrong format */
+  CURLE_REMOTE_FILE_NOT_FOUND,   /* 78 - remote file not found */
+  CURLE_SSH,                     /* 79 - error from the SSH layer, somewhat
+                                    generic so the error message will be of
+                                    interest when this has happened */
+
+  CURLE_SSL_SHUTDOWN_FAILED,     /* 80 - Failed to shut down the SSL
+                                    connection */
+  CURLE_AGAIN,                   /* 81 - socket is not ready for send/recv,
+                                    wait till it's ready and try again (Added
+                                    in 7.18.2) */
+  CURLE_SSL_CRL_BADFILE,         /* 82 - could not load CRL file, missing or
+                                    wrong format (Added in 7.19.0) */
+  CURLE_SSL_ISSUER_ERROR,        /* 83 - Issuer check failed.  (Added in
+                                    7.19.0) */
+  CURLE_FTP_PRET_FAILED,         /* 84 - a PRET command failed */
+  CURLE_RTSP_CSEQ_ERROR,         /* 85 - mismatch of RTSP CSeq numbers */
+  CURLE_RTSP_SESSION_ERROR,      /* 86 - mismatch of RTSP Session Ids */
+  CURLE_FTP_BAD_FILE_LIST,       /* 87 - unable to parse FTP file list */
+  CURLE_CHUNK_FAILED,            /* 88 - chunk callback reported error */
+  CURLE_NO_CONNECTION_AVAILABLE, /* 89 - No connection available, the
+                                    session will be queued */
+  CURLE_SSL_PINNEDPUBKEYNOTMATCH, /* 90 - specified pinned public key did not
+                                     match */
+  CURLE_SSL_INVALIDCERTSTATUS,   /* 91 - invalid certificate status */
+  CURLE_HTTP2_STREAM,            /* 92 - stream error in HTTP/2 framing layer
+                                    */
+  CURLE_RECURSIVE_API_CALL,      /* 93 - an api function was called from
+                                    inside a callback */
+  CURL_LAST /* never use! */
+} CURLcode;
+
+#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
+                          the obsolete stuff removed! */
+
+/* Previously obsolete error code re-used in 7.38.0 */
+#define CURLE_OBSOLETE16 CURLE_HTTP2
+
+/* Previously obsolete error codes re-used in 7.24.0 */
+#define CURLE_OBSOLETE10 CURLE_FTP_ACCEPT_FAILED
+#define CURLE_OBSOLETE12 CURLE_FTP_ACCEPT_TIMEOUT
+
+/*  compatibility with older names */
+#define CURLOPT_ENCODING CURLOPT_ACCEPT_ENCODING
+#define CURLE_FTP_WEIRD_SERVER_REPLY CURLE_WEIRD_SERVER_REPLY
+
+/* The following were added in 7.62.0 */
+#define CURLE_SSL_CACERT CURLE_PEER_FAILED_VERIFICATION
+
+/* The following were added in 7.21.5, April 2011 */
+#define CURLE_UNKNOWN_TELNET_OPTION CURLE_UNKNOWN_OPTION
+
+/* The following were added in 7.17.1 */
+/* These are scheduled to disappear by 2009 */
+#define CURLE_SSL_PEER_CERTIFICATE CURLE_PEER_FAILED_VERIFICATION
+
+/* The following were added in 7.17.0 */
+/* These are scheduled to disappear by 2009 */
+#define CURLE_OBSOLETE CURLE_OBSOLETE50 /* no one should be using this! */
+#define CURLE_BAD_PASSWORD_ENTERED CURLE_OBSOLETE46
+#define CURLE_BAD_CALLING_ORDER CURLE_OBSOLETE44
+#define CURLE_FTP_USER_PASSWORD_INCORRECT CURLE_OBSOLETE10
+#define CURLE_FTP_CANT_RECONNECT CURLE_OBSOLETE16
+#define CURLE_FTP_COULDNT_GET_SIZE CURLE_OBSOLETE32
+#define CURLE_FTP_COULDNT_SET_ASCII CURLE_OBSOLETE29
+#define CURLE_FTP_WEIRD_USER_REPLY CURLE_OBSOLETE12
+#define CURLE_FTP_WRITE_ERROR CURLE_OBSOLETE20
+#define CURLE_LIBRARY_NOT_FOUND CURLE_OBSOLETE40
+#define CURLE_MALFORMAT_USER CURLE_OBSOLETE24
+#define CURLE_SHARE_IN_USE CURLE_OBSOLETE57
+#define CURLE_URL_MALFORMAT_USER CURLE_NOT_BUILT_IN
+
+#define CURLE_FTP_ACCESS_DENIED CURLE_REMOTE_ACCESS_DENIED
+#define CURLE_FTP_COULDNT_SET_BINARY CURLE_FTP_COULDNT_SET_TYPE
+#define CURLE_FTP_QUOTE_ERROR CURLE_QUOTE_ERROR
+#define CURLE_TFTP_DISKFULL CURLE_REMOTE_DISK_FULL
+#define CURLE_TFTP_EXISTS CURLE_REMOTE_FILE_EXISTS
+#define CURLE_HTTP_RANGE_ERROR CURLE_RANGE_ERROR
+#define CURLE_FTP_SSL_FAILED CURLE_USE_SSL_FAILED
+
+/* The following were added earlier */
+
+#define CURLE_OPERATION_TIMEOUTED CURLE_OPERATION_TIMEDOUT
+
+#define CURLE_HTTP_NOT_FOUND CURLE_HTTP_RETURNED_ERROR
+#define CURLE_HTTP_PORT_FAILED CURLE_INTERFACE_FAILED
+#define CURLE_FTP_COULDNT_STOR_FILE CURLE_UPLOAD_FAILED
+
+#define CURLE_FTP_PARTIAL_FILE CURLE_PARTIAL_FILE
+#define CURLE_FTP_BAD_DOWNLOAD_RESUME CURLE_BAD_DOWNLOAD_RESUME
+
+/* This was the error code 50 in 7.7.3 and a few earlier versions, this
+   is no longer used by libcurl but is instead #defined here only to not
+   make programs break */
+#define CURLE_ALREADY_COMPLETE 99999
+
+/* Provide defines for really old option names */
+#define CURLOPT_FILE CURLOPT_WRITEDATA /* name changed in 7.9.7 */
+#define CURLOPT_INFILE CURLOPT_READDATA /* name changed in 7.9.7 */
+#define CURLOPT_WRITEHEADER CURLOPT_HEADERDATA
+
+/* Since long deprecated options with no code in the lib that does anything
+   with them. */
+#define CURLOPT_WRITEINFO CURLOPT_OBSOLETE40
+#define CURLOPT_CLOSEPOLICY CURLOPT_OBSOLETE72
+
+#endif /*!CURL_NO_OLDIES*/
+
+/* This prototype applies to all conversion callbacks */
+typedef CURLcode (*curl_conv_callback)(char *buffer, size_t length);
+
+typedef CURLcode (*curl_ssl_ctx_callback)(CURL *curl,    /* easy handle */
+                                          void *ssl_ctx, /* actually an OpenSSL
+                                                            or WolfSSL SSL_CTX,
+                                                            or an mbedTLS
+                                                          mbedtls_ssl_config */
+                                          void *userptr);
+
+typedef enum {
+  CURLPROXY_HTTP = 0,   /* added in 7.10, new in 7.19.4 default is to use
+                           CONNECT HTTP/1.1 */
+  CURLPROXY_HTTP_1_0 = 1,   /* added in 7.19.4, force to use CONNECT
+                               HTTP/1.0  */
+  CURLPROXY_HTTPS = 2, /* added in 7.52.0 */
+  CURLPROXY_SOCKS4 = 4, /* support added in 7.15.2, enum existed already
+                           in 7.10 */
+  CURLPROXY_SOCKS5 = 5, /* added in 7.10 */
+  CURLPROXY_SOCKS4A = 6, /* added in 7.18.0 */
+  CURLPROXY_SOCKS5_HOSTNAME = 7 /* Use the SOCKS5 protocol but pass along the
+                                   host name rather than the IP address. added
+                                   in 7.18.0 */
+} curl_proxytype;  /* this enum was added in 7.10 */
+
+/*
+ * Bitmasks for CURLOPT_HTTPAUTH and CURLOPT_PROXYAUTH options:
+ *
+ * CURLAUTH_NONE         - No HTTP authentication
+ * CURLAUTH_BASIC        - HTTP Basic authentication (default)
+ * CURLAUTH_DIGEST       - HTTP Digest authentication
+ * CURLAUTH_NEGOTIATE    - HTTP Negotiate (SPNEGO) authentication
+ * CURLAUTH_GSSNEGOTIATE - Alias for CURLAUTH_NEGOTIATE (deprecated)
+ * CURLAUTH_NTLM         - HTTP NTLM authentication
+ * CURLAUTH_DIGEST_IE    - HTTP Digest authentication with IE flavour
+ * CURLAUTH_NTLM_WB      - HTTP NTLM authentication delegated to winbind helper
+ * CURLAUTH_BEARER       - HTTP Bearer token authentication
+ * CURLAUTH_ONLY         - Use together with a single other type to force no
+ *                         authentication or just that single type
+ * CURLAUTH_ANY          - All fine types set
+ * CURLAUTH_ANYSAFE      - All fine types except Basic
+ */
+
+#define CURLAUTH_NONE         ((unsigned long)0)
+#define CURLAUTH_BASIC        (((unsigned long)1)<<0)
+#define CURLAUTH_DIGEST       (((unsigned long)1)<<1)
+#define CURLAUTH_NEGOTIATE    (((unsigned long)1)<<2)
+/* Deprecated since the advent of CURLAUTH_NEGOTIATE */
+#define CURLAUTH_GSSNEGOTIATE CURLAUTH_NEGOTIATE
+/* Used for CURLOPT_SOCKS5_AUTH to stay terminologically correct */
+#define CURLAUTH_GSSAPI CURLAUTH_NEGOTIATE
+#define CURLAUTH_NTLM         (((unsigned long)1)<<3)
+#define CURLAUTH_DIGEST_IE    (((unsigned long)1)<<4)
+#define CURLAUTH_NTLM_WB      (((unsigned long)1)<<5)
+#define CURLAUTH_BEARER       (((unsigned long)1)<<6)
+#define CURLAUTH_ONLY         (((unsigned long)1)<<31)
+#define CURLAUTH_ANY          (~CURLAUTH_DIGEST_IE)
+#define CURLAUTH_ANYSAFE      (~(CURLAUTH_BASIC|CURLAUTH_DIGEST_IE))
+
+#define CURLSSH_AUTH_ANY       ~0     /* all types supported by the server */
+#define CURLSSH_AUTH_NONE      0      /* none allowed, silly but complete */
+#define CURLSSH_AUTH_PUBLICKEY (1<<0) /* public/private key files */
+#define CURLSSH_AUTH_PASSWORD  (1<<1) /* password */
+#define CURLSSH_AUTH_HOST      (1<<2) /* host key files */
+#define CURLSSH_AUTH_KEYBOARD  (1<<3) /* keyboard interactive */
+#define CURLSSH_AUTH_AGENT     (1<<4) /* agent (ssh-agent, pageant...) */
+#define CURLSSH_AUTH_GSSAPI    (1<<5) /* gssapi (kerberos, ...) */
+#define CURLSSH_AUTH_DEFAULT CURLSSH_AUTH_ANY
+
+#define CURLGSSAPI_DELEGATION_NONE        0      /* no delegation (default) */
+#define CURLGSSAPI_DELEGATION_POLICY_FLAG (1<<0) /* if permitted by policy */
+#define CURLGSSAPI_DELEGATION_FLAG        (1<<1) /* delegate always */
+
+#define CURL_ERROR_SIZE 256
+
+enum curl_khtype {
+  CURLKHTYPE_UNKNOWN,
+  CURLKHTYPE_RSA1,
+  CURLKHTYPE_RSA,
+  CURLKHTYPE_DSS,
+  CURLKHTYPE_ECDSA,
+  CURLKHTYPE_ED25519
+};
+
+struct curl_khkey {
+  const char *key; /* points to a zero-terminated string encoded with base64
+                      if len is zero, otherwise to the "raw" data */
+  size_t len;
+  enum curl_khtype keytype;
+};
+
+/* this is the set of return values expected from the curl_sshkeycallback
+   callback */
+enum curl_khstat {
+  CURLKHSTAT_FINE_ADD_TO_FILE,
+  CURLKHSTAT_FINE,
+  CURLKHSTAT_REJECT, /* reject the connection, return an error */
+  CURLKHSTAT_DEFER,  /* do not accept it, but we can't answer right now so
+                        this causes a CURLE_DEFER error but otherwise the
+                        connection will be left intact etc */
+  CURLKHSTAT_LAST    /* not for use, only a marker for last-in-list */
+};
+
+/* this is the set of status codes pass in to the callback */
+enum curl_khmatch {
+  CURLKHMATCH_OK,       /* match */
+  CURLKHMATCH_MISMATCH, /* host found, key mismatch! */
+  CURLKHMATCH_MISSING,  /* no matching host/key found */
+  CURLKHMATCH_LAST      /* not for use, only a marker for last-in-list */
+};
+
+typedef int
+  (*curl_sshkeycallback) (CURL *easy,     /* easy handle */
+                          const struct curl_khkey *knownkey, /* known */
+                          const struct curl_khkey *foundkey, /* found */
+                          enum curl_khmatch, /* libcurl's view on the keys */
+                          void *clientp); /* custom pointer passed from app */
+
+/* parameter for the CURLOPT_USE_SSL option */
+typedef enum {
+  CURLUSESSL_NONE,    /* do not attempt to use SSL */
+  CURLUSESSL_TRY,     /* try using SSL, proceed anyway otherwise */
+  CURLUSESSL_CONTROL, /* SSL for the control connection or fail */
+  CURLUSESSL_ALL,     /* SSL for all communication or fail */
+  CURLUSESSL_LAST     /* not an option, never use */
+} curl_usessl;
+
+/* Definition of bits for the CURLOPT_SSL_OPTIONS argument: */
+
+/* - ALLOW_BEAST tells libcurl to allow the BEAST SSL vulnerability in the
+   name of improving interoperability with older servers. Some SSL libraries
+   have introduced work-arounds for this flaw but those work-arounds sometimes
+   make the SSL communication fail. To regain functionality with those broken
+   servers, a user can this way allow the vulnerability back. */
+#define CURLSSLOPT_ALLOW_BEAST (1<<0)
+
+/* - NO_REVOKE tells libcurl to disable certificate revocation checks for those
+   SSL backends where such behavior is present. */
+#define CURLSSLOPT_NO_REVOKE (1<<1)
+
+/* The default connection attempt delay in milliseconds for happy eyeballs.
+   CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.3 and happy-eyeballs-timeout-ms.d document
+   this value, keep them in sync. */
+#define CURL_HET_DEFAULT 200L
+
+/* The default connection upkeep interval in milliseconds. */
+#define CURL_UPKEEP_INTERVAL_DEFAULT 60000L
+
+#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
+                          the obsolete stuff removed! */
+
+/* Backwards compatibility with older names */
+/* These are scheduled to disappear by 2009 */
+
+#define CURLFTPSSL_NONE CURLUSESSL_NONE
+#define CURLFTPSSL_TRY CURLUSESSL_TRY
+#define CURLFTPSSL_CONTROL CURLUSESSL_CONTROL
+#define CURLFTPSSL_ALL CURLUSESSL_ALL
+#define CURLFTPSSL_LAST CURLUSESSL_LAST
+#define curl_ftpssl curl_usessl
+#endif /*!CURL_NO_OLDIES*/
+
+/* parameter for the CURLOPT_FTP_SSL_CCC option */
+typedef enum {
+  CURLFTPSSL_CCC_NONE,    /* do not send CCC */
+  CURLFTPSSL_CCC_PASSIVE, /* Let the server initiate the shutdown */
+  CURLFTPSSL_CCC_ACTIVE,  /* Initiate the shutdown */
+  CURLFTPSSL_CCC_LAST     /* not an option, never use */
+} curl_ftpccc;
+
+/* parameter for the CURLOPT_FTPSSLAUTH option */
+typedef enum {
+  CURLFTPAUTH_DEFAULT, /* let libcurl decide */
+  CURLFTPAUTH_SSL,     /* use "AUTH SSL" */
+  CURLFTPAUTH_TLS,     /* use "AUTH TLS" */
+  CURLFTPAUTH_LAST /* not an option, never use */
+} curl_ftpauth;
+
+/* parameter for the CURLOPT_FTP_CREATE_MISSING_DIRS option */
+typedef enum {
+  CURLFTP_CREATE_DIR_NONE,  /* do NOT create missing dirs! */
+  CURLFTP_CREATE_DIR,       /* (FTP/SFTP) if CWD fails, try MKD and then CWD
+                               again if MKD succeeded, for SFTP this does
+                               similar magic */
+  CURLFTP_CREATE_DIR_RETRY, /* (FTP only) if CWD fails, try MKD and then CWD
+                               again even if MKD failed! */
+  CURLFTP_CREATE_DIR_LAST   /* not an option, never use */
+} curl_ftpcreatedir;
+
+/* parameter for the CURLOPT_FTP_FILEMETHOD option */
+typedef enum {
+  CURLFTPMETHOD_DEFAULT,   /* let libcurl pick */
+  CURLFTPMETHOD_MULTICWD,  /* single CWD operation for each path part */
+  CURLFTPMETHOD_NOCWD,     /* no CWD at all */
+  CURLFTPMETHOD_SINGLECWD, /* one CWD to full dir, then work on file */
+  CURLFTPMETHOD_LAST       /* not an option, never use */
+} curl_ftpmethod;
+
+/* bitmask defines for CURLOPT_HEADEROPT */
+#define CURLHEADER_UNIFIED  0
+#define CURLHEADER_SEPARATE (1<<0)
+
+/* CURLALTSVC_* are bits for the CURLOPT_ALTSVC_CTRL option */
+#define CURLALTSVC_IMMEDIATELY  (1<<0)
+#define CURLALTSVC_ALTUSED      (1<<1)
+#define CURLALTSVC_READONLYFILE (1<<2)
+#define CURLALTSVC_H1           (1<<3)
+#define CURLALTSVC_H2           (1<<4)
+#define CURLALTSVC_H3           (1<<5)
+
+/* CURLPROTO_ defines are for the CURLOPT_*PROTOCOLS options */
+#define CURLPROTO_HTTP   (1<<0)
+#define CURLPROTO_HTTPS  (1<<1)
+#define CURLPROTO_FTP    (1<<2)
+#define CURLPROTO_FTPS   (1<<3)
+#define CURLPROTO_SCP    (1<<4)
+#define CURLPROTO_SFTP   (1<<5)
+#define CURLPROTO_TELNET (1<<6)
+#define CURLPROTO_LDAP   (1<<7)
+#define CURLPROTO_LDAPS  (1<<8)
+#define CURLPROTO_DICT   (1<<9)
+#define CURLPROTO_FILE   (1<<10)
+#define CURLPROTO_TFTP   (1<<11)
+#define CURLPROTO_IMAP   (1<<12)
+#define CURLPROTO_IMAPS  (1<<13)
+#define CURLPROTO_POP3   (1<<14)
+#define CURLPROTO_POP3S  (1<<15)
+#define CURLPROTO_SMTP   (1<<16)
+#define CURLPROTO_SMTPS  (1<<17)
+#define CURLPROTO_RTSP   (1<<18)
+#define CURLPROTO_RTMP   (1<<19)
+#define CURLPROTO_RTMPT  (1<<20)
+#define CURLPROTO_RTMPE  (1<<21)
+#define CURLPROTO_RTMPTE (1<<22)
+#define CURLPROTO_RTMPS  (1<<23)
+#define CURLPROTO_RTMPTS (1<<24)
+#define CURLPROTO_GOPHER (1<<25)
+#define CURLPROTO_SMB    (1<<26)
+#define CURLPROTO_SMBS   (1<<27)
+#define CURLPROTO_ALL    (~0) /* enable everything */
+
+/* long may be 32 or 64 bits, but we should never depend on anything else
+   but 32 */
+#define CURLOPTTYPE_LONG          0
+#define CURLOPTTYPE_OBJECTPOINT   10000
+#define CURLOPTTYPE_FUNCTIONPOINT 20000
+#define CURLOPTTYPE_OFF_T         30000
+
+/* *STRINGPOINT is an alias for OBJECTPOINT to allow tools to extract the
+   string options from the header file */
+
+/* name is uppercase CURLOPT_<name>,
+   type is one of the defined CURLOPTTYPE_<type>
+   number is unique identifier */
+#ifdef CINIT
+#undef CINIT
+#endif
+
+#ifdef CURL_ISOCPP
+#define CINIT(na,t,nu) CURLOPT_ ## na = CURLOPTTYPE_ ## t + nu
+#else
+/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */
+#define LONG          CURLOPTTYPE_LONG
+#define OBJECTPOINT   CURLOPTTYPE_OBJECTPOINT
+#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT
+#define OFF_T         CURLOPTTYPE_OFF_T
+#define CINIT(name,type,number) CURLOPT_/**/name = type + number
+#endif
+
+/* handy aliases that make no run-time difference */
+#define CURLOPTTYPE_STRINGPOINT  CURLOPTTYPE_OBJECTPOINT
+#define CURLOPTTYPE_SLISTPOINT  CURLOPTTYPE_OBJECTPOINT
+
+/*
+ * This macro-mania below setups the CURLOPT_[what] enum, to be used with
+ * curl_easy_setopt(). The first argument in the CINIT() macro is the [what]
+ * word.
+ */
+
+typedef enum {
+  /* This is the FILE * or void * the regular output should be written to. */
+  CINIT(WRITEDATA, OBJECTPOINT, 1),
+
+  /* The full URL to get/put */
+  CINIT(URL, STRINGPOINT, 2),
+
+  /* Port number to connect to, if other than default. */
+  CINIT(PORT, LONG, 3),
+
+  /* Name of proxy to use. */
+  CINIT(PROXY, STRINGPOINT, 4),
+
+  /* "user:password;options" to use when fetching. */
+  CINIT(USERPWD, STRINGPOINT, 5),
+
+  /* "user:password" to use with proxy. */
+  CINIT(PROXYUSERPWD, STRINGPOINT, 6),
+
+  /* Range to get, specified as an ASCII string. */
+  CINIT(RANGE, STRINGPOINT, 7),
+
+  /* not used */
+
+  /* Specified file stream to upload from (use as input): */
+  CINIT(READDATA, OBJECTPOINT, 9),
+
+  /* Buffer to receive error messages in, must be at least CURL_ERROR_SIZE
+   * bytes big. */
+  CINIT(ERRORBUFFER, OBJECTPOINT, 10),
+
+  /* Function that will be called to store the output (instead of fwrite). The
+   * parameters will use fwrite() syntax, make sure to follow them. */
+  CINIT(WRITEFUNCTION, FUNCTIONPOINT, 11),
+
+  /* Function that will be called to read the input (instead of fread). The
+   * parameters will use fread() syntax, make sure to follow them. */
+  CINIT(READFUNCTION, FUNCTIONPOINT, 12),
+
+  /* Time-out the read operation after this amount of seconds */
+  CINIT(TIMEOUT, LONG, 13),
+
+  /* If the CURLOPT_INFILE is used, this can be used to inform libcurl about
+   * how large the file being sent really is. That allows better error
+   * checking and better verifies that the upload was successful. -1 means
+   * unknown size.
+   *
+   * For large file support, there is also a _LARGE version of the key
+   * which takes an off_t type, allowing platforms with larger off_t
+   * sizes to handle larger files.  See below for INFILESIZE_LARGE.
+   */
+  CINIT(INFILESIZE, LONG, 14),
+
+  /* POST static input fields. */
+  CINIT(POSTFIELDS, OBJECTPOINT, 15),
+
+  /* Set the referrer page (needed by some CGIs) */
+  CINIT(REFERER, STRINGPOINT, 16),
+
+  /* Set the FTP PORT string (interface name, named or numerical IP address)
+     Use i.e '-' to use default address. */
+  CINIT(FTPPORT, STRINGPOINT, 17),
+
+  /* Set the User-Agent string (examined by some CGIs) */
+  CINIT(USERAGENT, STRINGPOINT, 18),
+
+  /* If the download receives less than "low speed limit" bytes/second
+   * during "low speed time" seconds, the operations is aborted.
+   * You could i.e if you have a pretty high speed connection, abort if
+   * it is less than 2000 bytes/sec during 20 seconds.
+   */
+
+  /* Set the "low speed limit" */
+  CINIT(LOW_SPEED_LIMIT, LONG, 19),
+
+  /* Set the "low speed time" */
+  CINIT(LOW_SPEED_TIME, LONG, 20),
+
+  /* Set the continuation offset.
+   *
+   * Note there is also a _LARGE version of this key which uses
+   * off_t types, allowing for large file offsets on platforms which
+   * use larger-than-32-bit off_t's.  Look below for RESUME_FROM_LARGE.
+   */
+  CINIT(RESUME_FROM, LONG, 21),
+
+  /* Set cookie in request: */
+  CINIT(COOKIE, STRINGPOINT, 22),
+
+  /* This points to a linked list of headers, struct curl_slist kind. This
+     list is also used for RTSP (in spite of its name) */
+  CINIT(HTTPHEADER, SLISTPOINT, 23),
+
+  /* This points to a linked list of post entries, struct curl_httppost */
+  CINIT(HTTPPOST, OBJECTPOINT, 24),
+
+  /* name of the file keeping your private SSL-certificate */
+  CINIT(SSLCERT, STRINGPOINT, 25),
+
+  /* password for the SSL or SSH private key */
+  CINIT(KEYPASSWD, STRINGPOINT, 26),
+
+  /* send TYPE parameter? */
+  CINIT(CRLF, LONG, 27),
+
+  /* send linked-list of QUOTE commands */
+  CINIT(QUOTE, SLISTPOINT, 28),
+
+  /* send FILE * or void * to store headers to, if you use a callback it
+     is simply passed to the callback unmodified */
+  CINIT(HEADERDATA, OBJECTPOINT, 29),
+
+  /* point to a file to read the initial cookies from, also enables
+     "cookie awareness" */
+  CINIT(COOKIEFILE, STRINGPOINT, 31),
+
+  /* What version to specifically try to use.
+     See CURL_SSLVERSION defines below. */
+  CINIT(SSLVERSION, LONG, 32),
+
+  /* What kind of HTTP time condition to use, see defines */
+  CINIT(TIMECONDITION, LONG, 33),
+
+  /* Time to use with the above condition. Specified in number of seconds
+     since 1 Jan 1970 */
+  CINIT(TIMEVALUE, LONG, 34),
+
+  /* 35 = OBSOLETE */
+
+  /* Custom request, for customizing the get command like
+     HTTP: DELETE, TRACE and others
+     FTP: to use a different list command
+     */
+  CINIT(CUSTOMREQUEST, STRINGPOINT, 36),
+
+  /* FILE handle to use instead of stderr */
+  CINIT(STDERR, OBJECTPOINT, 37),
+
+  /* 38 is not used */
+
+  /* send linked-list of post-transfer QUOTE commands */
+  CINIT(POSTQUOTE, SLISTPOINT, 39),
+
+  CINIT(OBSOLETE40, OBJECTPOINT, 40), /* OBSOLETE, do not use! */
+
+  CINIT(VERBOSE, LONG, 41),      /* talk a lot */
+  CINIT(HEADER, LONG, 42),       /* throw the header out too */
+  CINIT(NOPROGRESS, LONG, 43),   /* shut off the progress meter */
+  CINIT(NOBODY, LONG, 44),       /* use HEAD to get http document */
+  CINIT(FAILONERROR, LONG, 45),  /* no output on http error codes >= 400 */
+  CINIT(UPLOAD, LONG, 46),       /* this is an upload */
+  CINIT(POST, LONG, 47),         /* HTTP POST method */
+  CINIT(DIRLISTONLY, LONG, 48),  /* bare names when listing directories */
+
+  CINIT(APPEND, LONG, 50),       /* Append instead of overwrite on upload! */
+
+  /* Specify whether to read the user+password from the .netrc or the URL.
+   * This must be one of the CURL_NETRC_* enums below. */
+  CINIT(NETRC, LONG, 51),
+
+  CINIT(FOLLOWLOCATION, LONG, 52),  /* use Location: Luke! */
+
+  CINIT(TRANSFERTEXT, LONG, 53), /* transfer data in text/ASCII format */
+  CINIT(PUT, LONG, 54),          /* HTTP PUT */
+
+  /* 55 = OBSOLETE */
+
+  /* DEPRECATED
+   * Function that will be called instead of the internal progress display
+   * function. This function should be defined as the curl_progress_callback
+   * prototype defines. */
+  CINIT(PROGRESSFUNCTION, FUNCTIONPOINT, 56),
+
+  /* Data passed to the CURLOPT_PROGRESSFUNCTION and CURLOPT_XFERINFOFUNCTION
+     callbacks */
+  CINIT(PROGRESSDATA, OBJECTPOINT, 57),
+#define CURLOPT_XFERINFODATA CURLOPT_PROGRESSDATA
+
+  /* We want the referrer field set automatically when following locations */
+  CINIT(AUTOREFERER, LONG, 58),
+
+  /* Port of the proxy, can be set in the proxy string as well with:
+     "[host]:[port]" */
+  CINIT(PROXYPORT, LONG, 59),
+
+  /* size of the POST input data, if strlen() is not good to use */
+  CINIT(POSTFIELDSIZE, LONG, 60),
+
+  /* tunnel non-http operations through a HTTP proxy */
+  CINIT(HTTPPROXYTUNNEL, LONG, 61),
+
+  /* Set the interface string to use as outgoing network interface */
+  CINIT(INTERFACE, STRINGPOINT, 62),
+
+  /* Set the krb4/5 security level, this also enables krb4/5 awareness.  This
+   * is a string, 'clear', 'safe', 'confidential' or 'private'.  If the string
+   * is set but doesn't match one of these, 'private' will be used.  */
+  CINIT(KRBLEVEL, STRINGPOINT, 63),
+
+  /* Set if we should verify the peer in ssl handshake, set 1 to verify. */
+  CINIT(SSL_VERIFYPEER, LONG, 64),
+
+  /* The CApath or CAfile used to validate the peer certificate
+     this option is used only if SSL_VERIFYPEER is true */
+  CINIT(CAINFO, STRINGPOINT, 65),
+
+  /* 66 = OBSOLETE */
+  /* 67 = OBSOLETE */
+
+  /* Maximum number of http redirects to follow */
+  CINIT(MAXREDIRS, LONG, 68),
+
+  /* Pass a long set to 1 to get the date of the requested document (if
+     possible)! Pass a zero to shut it off. */
+  CINIT(FILETIME, LONG, 69),
+
+  /* This points to a linked list of telnet options */
+  CINIT(TELNETOPTIONS, SLISTPOINT, 70),
+
+  /* Max amount of cached alive connections */
+  CINIT(MAXCONNECTS, LONG, 71),
+
+  CINIT(OBSOLETE72, LONG, 72), /* OBSOLETE, do not use! */
+
+  /* 73 = OBSOLETE */
+
+  /* Set to explicitly use a new connection for the upcoming transfer.
+     Do not use this unless you're absolutely sure of this, as it makes the
+     operation slower and is less friendly for the network. */
+  CINIT(FRESH_CONNECT, LONG, 74),
+
+  /* Set to explicitly forbid the upcoming transfer's connection to be re-used
+     when done. Do not use this unless you're absolutely sure of this, as it
+     makes the operation slower and is less friendly for the network. */
+  CINIT(FORBID_REUSE, LONG, 75),
+
+  /* Set to a file name that contains random data for libcurl to use to
+     seed the random engine when doing SSL connects. */
+  CINIT(RANDOM_FILE, STRINGPOINT, 76),
+
+  /* Set to the Entropy Gathering Daemon socket pathname */
+  CINIT(EGDSOCKET, STRINGPOINT, 77),
+
+  /* Time-out connect operations after this amount of seconds, if connects are
+     OK within this time, then fine... This only aborts the connect phase. */
+  CINIT(CONNECTTIMEOUT, LONG, 78),
+
+  /* Function that will be called to store headers (instead of fwrite). The
+   * parameters will use fwrite() syntax, make sure to follow them. */
+  CINIT(HEADERFUNCTION, FUNCTIONPOINT, 79),
+
+  /* Set this to force the HTTP request to get back to GET. Only really usable
+     if POST, PUT or a custom request have been used first.
+   */
+  CINIT(HTTPGET, LONG, 80),
+
+  /* Set if we should verify the Common name from the peer certificate in ssl
+   * handshake, set 1 to check existence, 2 to ensure that it matches the
+   * provided hostname. */
+  CINIT(SSL_VERIFYHOST, LONG, 81),
+
+  /* Specify which file name to write all known cookies in after completed
+     operation. Set file name to "-" (dash) to make it go to stdout. */
+  CINIT(COOKIEJAR, STRINGPOINT, 82),
+
+  /* Specify which SSL ciphers to use */
+  CINIT(SSL_CIPHER_LIST, STRINGPOINT, 83),
+
+  /* Specify which HTTP version to use! This must be set to one of the
+     CURL_HTTP_VERSION* enums set below. */
+  CINIT(HTTP_VERSION, LONG, 84),
+
+  /* Specifically switch on or off the FTP engine's use of the EPSV command. By
+     default, that one will always be attempted before the more traditional
+     PASV command. */
+  CINIT(FTP_USE_EPSV, LONG, 85),
+
+  /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") */
+  CINIT(SSLCERTTYPE, STRINGPOINT, 86),
+
+  /* name of the file keeping your private SSL-key */
+  CINIT(SSLKEY, STRINGPOINT, 87),
+
+  /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") */
+  CINIT(SSLKEYTYPE, STRINGPOINT, 88),
+
+  /* crypto engine for the SSL-sub system */
+  CINIT(SSLENGINE, STRINGPOINT, 89),
+
+  /* set the crypto engine for the SSL-sub system as default
+     the param has no meaning...
+   */
+  CINIT(SSLENGINE_DEFAULT, LONG, 90),
+
+  /* Non-zero value means to use the global dns cache */
+  CINIT(DNS_USE_GLOBAL_CACHE, LONG, 91), /* DEPRECATED, do not use! */
+
+  /* DNS cache timeout */
+  CINIT(DNS_CACHE_TIMEOUT, LONG, 92),
+
+  /* send linked-list of pre-transfer QUOTE commands */
+  CINIT(PREQUOTE, SLISTPOINT, 93),
+
+  /* set the debug function */
+  CINIT(DEBUGFUNCTION, FUNCTIONPOINT, 94),
+
+  /* set the data for the debug function */
+  CINIT(DEBUGDATA, OBJECTPOINT, 95),
+
+  /* mark this as start of a cookie session */
+  CINIT(COOKIESESSION, LONG, 96),
+
+  /* The CApath directory used to validate the peer certificate
+     this option is used only if SSL_VERIFYPEER is true */
+  CINIT(CAPATH, STRINGPOINT, 97),
+
+  /* Instruct libcurl to use a smaller receive buffer */
+  CINIT(BUFFERSIZE, LONG, 98),
+
+  /* Instruct libcurl to not use any signal/alarm handlers, even when using
+     timeouts. This option is useful for multi-threaded applications.
+     See libcurl-the-guide for more background information. */
+  CINIT(NOSIGNAL, LONG, 99),
+
+  /* Provide a CURLShare for mutexing non-ts data */
+  CINIT(SHARE, OBJECTPOINT, 100),
+
+  /* indicates type of proxy. accepted values are CURLPROXY_HTTP (default),
+     CURLPROXY_HTTPS, CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and
+     CURLPROXY_SOCKS5. */
+  CINIT(PROXYTYPE, LONG, 101),
+
+  /* Set the Accept-Encoding string. Use this to tell a server you would like
+     the response to be compressed. Before 7.21.6, this was known as
+     CURLOPT_ENCODING */
+  CINIT(ACCEPT_ENCODING, STRINGPOINT, 102),
+
+  /* Set pointer to private data */
+  CINIT(PRIVATE, OBJECTPOINT, 103),
+
+  /* Set aliases for HTTP 200 in the HTTP Response header */
+  CINIT(HTTP200ALIASES, SLISTPOINT, 104),
+
+  /* Continue to send authentication (user+password) when following locations,
+     even when hostname changed. This can potentially send off the name
+     and password to whatever host the server decides. */
+  CINIT(UNRESTRICTED_AUTH, LONG, 105),
+
+  /* Specifically switch on or off the FTP engine's use of the EPRT command (
+     it also disables the LPRT attempt). By default, those ones will always be
+     attempted before the good old traditional PORT command. */
+  CINIT(FTP_USE_EPRT, LONG, 106),
+
+  /* Set this to a bitmask value to enable the particular authentications
+     methods you like. Use this in combination with CURLOPT_USERPWD.
+     Note that setting multiple bits may cause extra network round-trips. */
+  CINIT(HTTPAUTH, LONG, 107),
+
+  /* Set the ssl context callback function, currently only for OpenSSL or
+     WolfSSL ssl_ctx, or mbedTLS mbedtls_ssl_config in the second argument.
+     The function must match the curl_ssl_ctx_callback prototype. */
+  CINIT(SSL_CTX_FUNCTION, FUNCTIONPOINT, 108),
+
+  /* Set the userdata for the ssl context callback function's third
+     argument */
+  CINIT(SSL_CTX_DATA, OBJECTPOINT, 109),
+
+  /* FTP Option that causes missing dirs to be created on the remote server.
+     In 7.19.4 we introduced the convenience enums for this option using the
+     CURLFTP_CREATE_DIR prefix.
+  */
+  CINIT(FTP_CREATE_MISSING_DIRS, LONG, 110),
+
+  /* Set this to a bitmask value to enable the particular authentications
+     methods you like. Use this in combination with CURLOPT_PROXYUSERPWD.
+     Note that setting multiple bits may cause extra network round-trips. */
+  CINIT(PROXYAUTH, LONG, 111),
+
+  /* FTP option that changes the timeout, in seconds, associated with
+     getting a response.  This is different from transfer timeout time and
+     essentially places a demand on the FTP server to acknowledge commands
+     in a timely manner. */
+  CINIT(FTP_RESPONSE_TIMEOUT, LONG, 112),
+#define CURLOPT_SERVER_RESPONSE_TIMEOUT CURLOPT_FTP_RESPONSE_TIMEOUT
+
+  /* Set this option to one of the CURL_IPRESOLVE_* defines (see below) to
+     tell libcurl to resolve names to those IP versions only. This only has
+     affect on systems with support for more than one, i.e IPv4 _and_ IPv6. */
+  CINIT(IPRESOLVE, LONG, 113),
+
+  /* Set this option to limit the size of a file that will be downloaded from
+     an HTTP or FTP server.
+
+     Note there is also _LARGE version which adds large file support for
+     platforms which have larger off_t sizes.  See MAXFILESIZE_LARGE below. */
+  CINIT(MAXFILESIZE, LONG, 114),
+
+  /* See the comment for INFILESIZE above, but in short, specifies
+   * the size of the file being uploaded.  -1 means unknown.
+   */
+  CINIT(INFILESIZE_LARGE, OFF_T, 115),
+
+  /* Sets the continuation offset.  There is also a LONG version of this;
+   * look above for RESUME_FROM.
+   */
+  CINIT(RESUME_FROM_LARGE, OFF_T, 116),
+
+  /* Sets the maximum size of data that will be downloaded from
+   * an HTTP or FTP server.  See MAXFILESIZE above for the LONG version.
+   */
+  CINIT(MAXFILESIZE_LARGE, OFF_T, 117),
+
+  /* Set this option to the file name of your .netrc file you want libcurl
+     to parse (using the CURLOPT_NETRC option). If not set, libcurl will do
+     a poor attempt to find the user's home directory and check for a .netrc
+     file in there. */
+  CINIT(NETRC_FILE, STRINGPOINT, 118),
+
+  /* Enable SSL/TLS for FTP, pick one of:
+     CURLUSESSL_TRY     - try using SSL, proceed anyway otherwise
+     CURLUSESSL_CONTROL - SSL for the control connection or fail
+     CURLUSESSL_ALL     - SSL for all communication or fail
+  */
+  CINIT(USE_SSL, LONG, 119),
+
+  /* The _LARGE version of the standard POSTFIELDSIZE option */
+  CINIT(POSTFIELDSIZE_LARGE, OFF_T, 120),
+
+  /* Enable/disable the TCP Nagle algorithm */
+  CINIT(TCP_NODELAY, LONG, 121),
+
+  /* 122 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
+  /* 123 OBSOLETE. Gone in 7.16.0 */
+  /* 124 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
+  /* 125 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
+  /* 126 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
+  /* 127 OBSOLETE. Gone in 7.16.0 */
+  /* 128 OBSOLETE. Gone in 7.16.0 */
+
+  /* When FTP over SSL/TLS is selected (with CURLOPT_USE_SSL), this option
+     can be used to change libcurl's default action which is to first try
+     "AUTH SSL" and then "AUTH TLS" in this order, and proceed when a OK
+     response has been received.
+
+     Available parameters are:
+     CURLFTPAUTH_DEFAULT - let libcurl decide
+     CURLFTPAUTH_SSL     - try "AUTH SSL" first, then TLS
+     CURLFTPAUTH_TLS     - try "AUTH TLS" first, then SSL
+  */
+  CINIT(FTPSSLAUTH, LONG, 129),
+
+  CINIT(IOCTLFUNCTION, FUNCTIONPOINT, 130),
+  CINIT(IOCTLDATA, OBJECTPOINT, 131),
+
+  /* 132 OBSOLETE. Gone in 7.16.0 */
+  /* 133 OBSOLETE. Gone in 7.16.0 */
+
+  /* zero terminated string for pass on to the FTP server when asked for
+     "account" info */
+  CINIT(FTP_ACCOUNT, STRINGPOINT, 134),
+
+  /* feed cookie into cookie engine */
+  CINIT(COOKIELIST, STRINGPOINT, 135),
+
+  /* ignore Content-Length */
+  CINIT(IGNORE_CONTENT_LENGTH, LONG, 136),
+
+  /* Set to non-zero to skip the IP address received in a 227 PASV FTP server
+     response. Typically used for FTP-SSL purposes but is not restricted to
+     that. libcurl will then instead use the same IP address it used for the
+     control connection. */
+  CINIT(FTP_SKIP_PASV_IP, LONG, 137),
+
+  /* Select "file method" to use when doing FTP, see the curl_ftpmethod
+     above. */
+  CINIT(FTP_FILEMETHOD, LONG, 138),
+
+  /* Local port number to bind the socket to */
+  CINIT(LOCALPORT, LONG, 139),
+
+  /* Number of ports to try, including the first one set with LOCALPORT.
+     Thus, setting it to 1 will make no additional attempts but the first.
+  */
+  CINIT(LOCALPORTRANGE, LONG, 140),
+
+  /* no transfer, set up connection and let application use the socket by
+     extracting it with CURLINFO_LASTSOCKET */
+  CINIT(CONNECT_ONLY, LONG, 141),
+
+  /* Function that will be called to convert from the
+     network encoding (instead of using the iconv calls in libcurl) */
+  CINIT(CONV_FROM_NETWORK_FUNCTION, FUNCTIONPOINT, 142),
+
+  /* Function that will be called to convert to the
+     network encoding (instead of using the iconv calls in libcurl) */
+  CINIT(CONV_TO_NETWORK_FUNCTION, FUNCTIONPOINT, 143),
+
+  /* Function that will be called to convert from UTF8
+     (instead of using the iconv calls in libcurl)
+     Note that this is used only for SSL certificate processing */
+  CINIT(CONV_FROM_UTF8_FUNCTION, FUNCTIONPOINT, 144),
+
+  /* if the connection proceeds too quickly then need to slow it down */
+  /* limit-rate: maximum number of bytes per second to send or receive */
+  CINIT(MAX_SEND_SPEED_LARGE, OFF_T, 145),
+  CINIT(MAX_RECV_SPEED_LARGE, OFF_T, 146),
+
+  /* Pointer to command string to send if USER/PASS fails. */
+  CINIT(FTP_ALTERNATIVE_TO_USER, STRINGPOINT, 147),
+
+  /* callback function for setting socket options */
+  CINIT(SOCKOPTFUNCTION, FUNCTIONPOINT, 148),
+  CINIT(SOCKOPTDATA, OBJECTPOINT, 149),
+
+  /* set to 0 to disable session ID re-use for this transfer, default is
+     enabled (== 1) */
+  CINIT(SSL_SESSIONID_CACHE, LONG, 150),
+
+  /* allowed SSH authentication methods */
+  CINIT(SSH_AUTH_TYPES, LONG, 151),
+
+  /* Used by scp/sftp to do public/private key authentication */
+  CINIT(SSH_PUBLIC_KEYFILE, STRINGPOINT, 152),
+  CINIT(SSH_PRIVATE_KEYFILE, STRINGPOINT, 153),
+
+  /* Send CCC (Clear Command Channel) after authentication */
+  CINIT(FTP_SSL_CCC, LONG, 154),
+
+  /* Same as TIMEOUT and CONNECTTIMEOUT, but with ms resolution */
+  CINIT(TIMEOUT_MS, LONG, 155),
+  CINIT(CONNECTTIMEOUT_MS, LONG, 156),
+
+  /* set to zero to disable the libcurl's decoding and thus pass the raw body
+     data to the application even when it is encoded/compressed */
+  CINIT(HTTP_TRANSFER_DECODING, LONG, 157),
+  CINIT(HTTP_CONTENT_DECODING, LONG, 158),
+
+  /* Permission used when creating new files and directories on the remote
+     server for protocols that support it, SFTP/SCP/FILE */
+  CINIT(NEW_FILE_PERMS, LONG, 159),
+  CINIT(NEW_DIRECTORY_PERMS, LONG, 160),
+
+  /* Set the behaviour of POST when redirecting. Values must be set to one
+     of CURL_REDIR* defines below. This used to be called CURLOPT_POST301 */
+  CINIT(POSTREDIR, LONG, 161),
+
+  /* used by scp/sftp to verify the host's public key */
+  CINIT(SSH_HOST_PUBLIC_KEY_MD5, STRINGPOINT, 162),
+
+  /* Callback function for opening socket (instead of socket(2)). Optionally,
+     callback is able change the address or refuse to connect returning
+     CURL_SOCKET_BAD.  The callback should have type
+     curl_opensocket_callback */
+  CINIT(OPENSOCKETFUNCTION, FUNCTIONPOINT, 163),
+  CINIT(OPENSOCKETDATA, OBJECTPOINT, 164),
+
+  /* POST volatile input fields. */
+  CINIT(COPYPOSTFIELDS, OBJECTPOINT, 165),
+
+  /* set transfer mode (;type=<a|i>) when doing FTP via an HTTP proxy */
+  CINIT(PROXY_TRANSFER_MODE, LONG, 166),
+
+  /* Callback function for seeking in the input stream */
+  CINIT(SEEKFUNCTION, FUNCTIONPOINT, 167),
+  CINIT(SEEKDATA, OBJECTPOINT, 168),
+
+  /* CRL file */
+  CINIT(CRLFILE, STRINGPOINT, 169),
+
+  /* Issuer certificate */
+  CINIT(ISSUERCERT, STRINGPOINT, 170),
+
+  /* (IPv6) Address scope */
+  CINIT(ADDRESS_SCOPE, LONG, 171),
+
+  /* Collect certificate chain info and allow it to get retrievable with
+     CURLINFO_CERTINFO after the transfer is complete. */
+  CINIT(CERTINFO, LONG, 172),
+
+  /* "name" and "pwd" to use when fetching. */
+  CINIT(USERNAME, STRINGPOINT, 173),
+  CINIT(PASSWORD, STRINGPOINT, 174),
+
+    /* "name" and "pwd" to use with Proxy when fetching. */
+  CINIT(PROXYUSERNAME, STRINGPOINT, 175),
+  CINIT(PROXYPASSWORD, STRINGPOINT, 176),
+
+  /* Comma separated list of hostnames defining no-proxy zones. These should
+     match both hostnames directly, and hostnames within a domain. For
+     example, local.com will match local.com and www.local.com, but NOT
+     notlocal.com or www.notlocal.com. For compatibility with other
+     implementations of this, .local.com will be considered to be the same as
+     local.com. A single * is the only valid wildcard, and effectively
+     disables the use of proxy. */
+  CINIT(NOPROXY, STRINGPOINT, 177),
+
+  /* block size for TFTP transfers */
+  CINIT(TFTP_BLKSIZE, LONG, 178),
+
+  /* Socks Service */
+  CINIT(SOCKS5_GSSAPI_SERVICE, STRINGPOINT, 179), /* DEPRECATED, do not use! */
+
+  /* Socks Service */
+  CINIT(SOCKS5_GSSAPI_NEC, LONG, 180),
+
+  /* set the bitmask for the protocols that are allowed to be used for the
+     transfer, which thus helps the app which takes URLs from users or other
+     external inputs and want to restrict what protocol(s) to deal
+     with. Defaults to CURLPROTO_ALL. */
+  CINIT(PROTOCOLS, LONG, 181),
+
+  /* set the bitmask for the protocols that libcurl is allowed to follow to,
+     as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs
+     to be set in both bitmasks to be allowed to get redirected to. */
+  CINIT(REDIR_PROTOCOLS, LONG, 182),
+
+  /* set the SSH knownhost file name to use */
+  CINIT(SSH_KNOWNHOSTS, STRINGPOINT, 183),
+
+  /* set the SSH host key callback, must point to a curl_sshkeycallback
+     function */
+  CINIT(SSH_KEYFUNCTION, FUNCTIONPOINT, 184),
+
+  /* set the SSH host key callback custom pointer */
+  CINIT(SSH_KEYDATA, OBJECTPOINT, 185),
+
+  /* set the SMTP mail originator */
+  CINIT(MAIL_FROM, STRINGPOINT, 186),
+
+  /* set the list of SMTP mail receiver(s) */
+  CINIT(MAIL_RCPT, SLISTPOINT, 187),
+
+  /* FTP: send PRET before PASV */
+  CINIT(FTP_USE_PRET, LONG, 188),
+
+  /* RTSP request method (OPTIONS, SETUP, PLAY, etc...) */
+  CINIT(RTSP_REQUEST, LONG, 189),
+
+  /* The RTSP session identifier */
+  CINIT(RTSP_SESSION_ID, STRINGPOINT, 190),
+
+  /* The RTSP stream URI */
+  CINIT(RTSP_STREAM_URI, STRINGPOINT, 191),
+
+  /* The Transport: header to use in RTSP requests */
+  CINIT(RTSP_TRANSPORT, STRINGPOINT, 192),
+
+  /* Manually initialize the client RTSP CSeq for this handle */
+  CINIT(RTSP_CLIENT_CSEQ, LONG, 193),
+
+  /* Manually initialize the server RTSP CSeq for this handle */
+  CINIT(RTSP_SERVER_CSEQ, LONG, 194),
+
+  /* The stream to pass to INTERLEAVEFUNCTION. */
+  CINIT(INTERLEAVEDATA, OBJECTPOINT, 195),
+
+  /* Let the application define a custom write method for RTP data */
+  CINIT(INTERLEAVEFUNCTION, FUNCTIONPOINT, 196),
+
+  /* Turn on wildcard matching */
+  CINIT(WILDCARDMATCH, LONG, 197),
+
+  /* Directory matching callback called before downloading of an
+     individual file (chunk) started */
+  CINIT(CHUNK_BGN_FUNCTION, FUNCTIONPOINT, 198),
+
+  /* Directory matching callback called after the file (chunk)
+     was downloaded, or skipped */
+  CINIT(CHUNK_END_FUNCTION, FUNCTIONPOINT, 199),
+
+  /* Change match (fnmatch-like) callback for wildcard matching */
+  CINIT(FNMATCH_FUNCTION, FUNCTIONPOINT, 200),
+
+  /* Let the application define custom chunk data pointer */
+  CINIT(CHUNK_DATA, OBJECTPOINT, 201),
+
+  /* FNMATCH_FUNCTION user pointer */
+  CINIT(FNMATCH_DATA, OBJECTPOINT, 202),
+
+  /* send linked-list of name:port:address sets */
+  CINIT(RESOLVE, SLISTPOINT, 203),
+
+  /* Set a username for authenticated TLS */
+  CINIT(TLSAUTH_USERNAME, STRINGPOINT, 204),
+
+  /* Set a password for authenticated TLS */
+  CINIT(TLSAUTH_PASSWORD, STRINGPOINT, 205),
+
+  /* Set authentication type for authenticated TLS */
+  CINIT(TLSAUTH_TYPE, STRINGPOINT, 206),
+
+  /* Set to 1 to enable the "TE:" header in HTTP requests to ask for
+     compressed transfer-encoded responses. Set to 0 to disable the use of TE:
+     in outgoing requests. The current default is 0, but it might change in a
+     future libcurl release.
+
+     libcurl will ask for the compressed methods it knows of, and if that
+     isn't any, it will not ask for transfer-encoding at all even if this
+     option is set to 1.
+
+  */
+  CINIT(TRANSFER_ENCODING, LONG, 207),
+
+  /* Callback function for closing socket (instead of close(2)). The callback
+     should have type curl_closesocket_callback */
+  CINIT(CLOSESOCKETFUNCTION, FUNCTIONPOINT, 208),
+  CINIT(CLOSESOCKETDATA, OBJECTPOINT, 209),
+
+  /* allow GSSAPI credential delegation */
+  CINIT(GSSAPI_DELEGATION, LONG, 210),
+
+  /* Set the name servers to use for DNS resolution */
+  CINIT(DNS_SERVERS, STRINGPOINT, 211),
+
+  /* Time-out accept operations (currently for FTP only) after this amount
+     of milliseconds. */
+  CINIT(ACCEPTTIMEOUT_MS, LONG, 212),
+
+  /* Set TCP keepalive */
+  CINIT(TCP_KEEPALIVE, LONG, 213),
+
+  /* non-universal keepalive knobs (Linux, AIX, HP-UX, more) */
+  CINIT(TCP_KEEPIDLE, LONG, 214),
+  CINIT(TCP_KEEPINTVL, LONG, 215),
+
+  /* Enable/disable specific SSL features with a bitmask, see CURLSSLOPT_* */
+  CINIT(SSL_OPTIONS, LONG, 216),
+
+  /* Set the SMTP auth originator */
+  CINIT(MAIL_AUTH, STRINGPOINT, 217),
+
+  /* Enable/disable SASL initial response */
+  CINIT(SASL_IR, LONG, 218),
+
+  /* Function that will be called instead of the internal progress display
+   * function. This function should be defined as the curl_xferinfo_callback
+   * prototype defines. (Deprecates CURLOPT_PROGRESSFUNCTION) */
+  CINIT(XFERINFOFUNCTION, FUNCTIONPOINT, 219),
+
+  /* The XOAUTH2 bearer token */
+  CINIT(XOAUTH2_BEARER, STRINGPOINT, 220),
+
+  /* Set the interface string to use as outgoing network
+   * interface for DNS requests.
+   * Only supported by the c-ares DNS backend */
+  CINIT(DNS_INTERFACE, STRINGPOINT, 221),
+
+  /* Set the local IPv4 address to use for outgoing DNS requests.
+   * Only supported by the c-ares DNS backend */
+  CINIT(DNS_LOCAL_IP4, STRINGPOINT, 222),
+
+  /* Set the local IPv6 address to use for outgoing DNS requests.
+   * Only supported by the c-ares DNS backend */
+  CINIT(DNS_LOCAL_IP6, STRINGPOINT, 223),
+
+  /* Set authentication options directly */
+  CINIT(LOGIN_OPTIONS, STRINGPOINT, 224),
+
+  /* Enable/disable TLS NPN extension (http2 over ssl might fail without) */
+  CINIT(SSL_ENABLE_NPN, LONG, 225),
+
+  /* Enable/disable TLS ALPN extension (http2 over ssl might fail without) */
+  CINIT(SSL_ENABLE_ALPN, LONG, 226),
+
+  /* Time to wait for a response to a HTTP request containing an
+   * Expect: 100-continue header before sending the data anyway. */
+  CINIT(EXPECT_100_TIMEOUT_MS, LONG, 227),
+
+  /* This points to a linked list of headers used for proxy requests only,
+     struct curl_slist kind */
+  CINIT(PROXYHEADER, SLISTPOINT, 228),
+
+  /* Pass in a bitmask of "header options" */
+  CINIT(HEADEROPT, LONG, 229),
+
+  /* The public key in DER form used to validate the peer public key
+     this option is used only if SSL_VERIFYPEER is true */
+  CINIT(PINNEDPUBLICKEY, STRINGPOINT, 230),
+
+  /* Path to Unix domain socket */
+  CINIT(UNIX_SOCKET_PATH, STRINGPOINT, 231),
+
+  /* Set if we should verify the certificate status. */
+  CINIT(SSL_VERIFYSTATUS, LONG, 232),
+
+  /* Set if we should enable TLS false start. */
+  CINIT(SSL_FALSESTART, LONG, 233),
+
+  /* Do not squash dot-dot sequences */
+  CINIT(PATH_AS_IS, LONG, 234),
+
+  /* Proxy Service Name */
+  CINIT(PROXY_SERVICE_NAME, STRINGPOINT, 235),
+
+  /* Service Name */
+  CINIT(SERVICE_NAME, STRINGPOINT, 236),
+
+  /* Wait/don't wait for pipe/mutex to clarify */
+  CINIT(PIPEWAIT, LONG, 237),
+
+  /* Set the protocol used when curl is given a URL without a protocol */
+  CINIT(DEFAULT_PROTOCOL, STRINGPOINT, 238),
+
+  /* Set stream weight, 1 - 256 (default is 16) */
+  CINIT(STREAM_WEIGHT, LONG, 239),
+
+  /* Set stream dependency on another CURL handle */
+  CINIT(STREAM_DEPENDS, OBJECTPOINT, 240),
+
+  /* Set E-xclusive stream dependency on another CURL handle */
+  CINIT(STREAM_DEPENDS_E, OBJECTPOINT, 241),
+
+  /* Do not send any tftp option requests to the server */
+  CINIT(TFTP_NO_OPTIONS, LONG, 242),
+
+  /* Linked-list of host:port:connect-to-host:connect-to-port,
+     overrides the URL's host:port (only for the network layer) */
+  CINIT(CONNECT_TO, SLISTPOINT, 243),
+
+  /* Set TCP Fast Open */
+  CINIT(TCP_FASTOPEN, LONG, 244),
+
+  /* Continue to send data if the server responds early with an
+   * HTTP status code >= 300 */
+  CINIT(KEEP_SENDING_ON_ERROR, LONG, 245),
+
+  /* The CApath or CAfile used to validate the proxy certificate
+     this option is used only if PROXY_SSL_VERIFYPEER is true */
+  CINIT(PROXY_CAINFO, STRINGPOINT, 246),
+
+  /* The CApath directory used to validate the proxy certificate
+     this option is used only if PROXY_SSL_VERIFYPEER is true */
+  CINIT(PROXY_CAPATH, STRINGPOINT, 247),
+
+  /* Set if we should verify the proxy in ssl handshake,
+     set 1 to verify. */
+  CINIT(PROXY_SSL_VERIFYPEER, LONG, 248),
+
+  /* Set if we should verify the Common name from the proxy certificate in ssl
+   * handshake, set 1 to check existence, 2 to ensure that it matches
+   * the provided hostname. */
+  CINIT(PROXY_SSL_VERIFYHOST, LONG, 249),
+
+  /* What version to specifically try to use for proxy.
+     See CURL_SSLVERSION defines below. */
+  CINIT(PROXY_SSLVERSION, LONG, 250),
+
+  /* Set a username for authenticated TLS for proxy */
+  CINIT(PROXY_TLSAUTH_USERNAME, STRINGPOINT, 251),
+
+  /* Set a password for authenticated TLS for proxy */
+  CINIT(PROXY_TLSAUTH_PASSWORD, STRINGPOINT, 252),
+
+  /* Set authentication type for authenticated TLS for proxy */
+  CINIT(PROXY_TLSAUTH_TYPE, STRINGPOINT, 253),
+
+  /* name of the file keeping your private SSL-certificate for proxy */
+  CINIT(PROXY_SSLCERT, STRINGPOINT, 254),
+
+  /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") for
+     proxy */
+  CINIT(PROXY_SSLCERTTYPE, STRINGPOINT, 255),
+
+  /* name of the file keeping your private SSL-key for proxy */
+  CINIT(PROXY_SSLKEY, STRINGPOINT, 256),
+
+  /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") for
+     proxy */
+  CINIT(PROXY_SSLKEYTYPE, STRINGPOINT, 257),
+
+  /* password for the SSL private key for proxy */
+  CINIT(PROXY_KEYPASSWD, STRINGPOINT, 258),
+
+  /* Specify which SSL ciphers to use for proxy */
+  CINIT(PROXY_SSL_CIPHER_LIST, STRINGPOINT, 259),
+
+  /* CRL file for proxy */
+  CINIT(PROXY_CRLFILE, STRINGPOINT, 260),
+
+  /* Enable/disable specific SSL features with a bitmask for proxy, see
+     CURLSSLOPT_* */
+  CINIT(PROXY_SSL_OPTIONS, LONG, 261),
+
+  /* Name of pre proxy to use. */
+  CINIT(PRE_PROXY, STRINGPOINT, 262),
+
+  /* The public key in DER form used to validate the proxy public key
+     this option is used only if PROXY_SSL_VERIFYPEER is true */
+  CINIT(PROXY_PINNEDPUBLICKEY, STRINGPOINT, 263),
+
+  /* Path to an abstract Unix domain socket */
+  CINIT(ABSTRACT_UNIX_SOCKET, STRINGPOINT, 264),
+
+  /* Suppress proxy CONNECT response headers from user callbacks */
+  CINIT(SUPPRESS_CONNECT_HEADERS, LONG, 265),
+
+  /* The request target, instead of extracted from the URL */
+  CINIT(REQUEST_TARGET, STRINGPOINT, 266),
+
+  /* bitmask of allowed auth methods for connections to SOCKS5 proxies */
+  CINIT(SOCKS5_AUTH, LONG, 267),
+
+  /* Enable/disable SSH compression */
+  CINIT(SSH_COMPRESSION, LONG, 268),
+
+  /* Post MIME data. */
+  CINIT(MIMEPOST, OBJECTPOINT, 269),
+
+  /* Time to use with the CURLOPT_TIMECONDITION. Specified in number of
+     seconds since 1 Jan 1970. */
+  CINIT(TIMEVALUE_LARGE, OFF_T, 270),
+
+  /* Head start in milliseconds to give happy eyeballs. */
+  CINIT(HAPPY_EYEBALLS_TIMEOUT_MS, LONG, 271),
+
+  /* Function that will be called before a resolver request is made */
+  CINIT(RESOLVER_START_FUNCTION, FUNCTIONPOINT, 272),
+
+  /* User data to pass to the resolver start callback. */
+  CINIT(RESOLVER_START_DATA, OBJECTPOINT, 273),
+
+  /* send HAProxy PROXY protocol header? */
+  CINIT(HAPROXYPROTOCOL, LONG, 274),
+
+  /* shuffle addresses before use when DNS returns multiple */
+  CINIT(DNS_SHUFFLE_ADDRESSES, LONG, 275),
+
+  /* Specify which TLS 1.3 ciphers suites to use */
+  CINIT(TLS13_CIPHERS, STRINGPOINT, 276),
+  CINIT(PROXY_TLS13_CIPHERS, STRINGPOINT, 277),
+
+  /* Disallow specifying username/login in URL. */
+  CINIT(DISALLOW_USERNAME_IN_URL, LONG, 278),
+
+  /* DNS-over-HTTPS URL */
+  CINIT(DOH_URL, STRINGPOINT, 279),
+
+  /* Preferred buffer size to use for uploads */
+  CINIT(UPLOAD_BUFFERSIZE, LONG, 280),
+
+  /* Time in ms between connection upkeep calls for long-lived connections. */
+  CINIT(UPKEEP_INTERVAL_MS, LONG, 281),
+
+  /* Specify URL using CURL URL API. */
+  CINIT(CURLU, OBJECTPOINT, 282),
+
+  /* add trailing data just after no more data is available */
+  CINIT(TRAILERFUNCTION, FUNCTIONPOINT, 283),
+
+  /* pointer to be passed to HTTP_TRAILER_FUNCTION */
+  CINIT(TRAILERDATA, OBJECTPOINT, 284),
+
+  /* set this to 1L to allow HTTP/0.9 responses or 0L to disallow */
+  CINIT(HTTP09_ALLOWED, LONG, 285),
+
+  /* alt-svc control bitmask */
+  CINIT(ALTSVC_CTRL, LONG, 286),
+
+  /* alt-svc cache file name to possibly read from/write to */
+  CINIT(ALTSVC, STRINGPOINT, 287),
+
+  /* maximum age of a connection to consider it for reuse (in seconds) */
+  CINIT(MAXAGE_CONN, LONG, 288),
+
+  CURLOPT_LASTENTRY /* the last unused */
+} CURLoption;
+
+#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
+                          the obsolete stuff removed! */
+
+/* Backwards compatibility with older names */
+/* These are scheduled to disappear by 2011 */
+
+/* This was added in version 7.19.1 */
+#define CURLOPT_POST301 CURLOPT_POSTREDIR
+
+/* These are scheduled to disappear by 2009 */
+
+/* The following were added in 7.17.0 */
+#define CURLOPT_SSLKEYPASSWD CURLOPT_KEYPASSWD
+#define CURLOPT_FTPAPPEND CURLOPT_APPEND
+#define CURLOPT_FTPLISTONLY CURLOPT_DIRLISTONLY
+#define CURLOPT_FTP_SSL CURLOPT_USE_SSL
+
+/* The following were added earlier */
+
+#define CURLOPT_SSLCERTPASSWD CURLOPT_KEYPASSWD
+#define CURLOPT_KRB4LEVEL CURLOPT_KRBLEVEL
+
+#else
+/* This is set if CURL_NO_OLDIES is defined at compile-time */
+#undef CURLOPT_DNS_USE_GLOBAL_CACHE /* soon obsolete */
+#endif
+
+
+  /* Below here follows defines for the CURLOPT_IPRESOLVE option. If a host
+     name resolves addresses using more than one IP protocol version, this
+     option might be handy to force libcurl to use a specific IP version. */
+#define CURL_IPRESOLVE_WHATEVER 0 /* default, resolves addresses to all IP
+                                     versions that your system allows */
+#define CURL_IPRESOLVE_V4       1 /* resolve to IPv4 addresses */
+#define CURL_IPRESOLVE_V6       2 /* resolve to IPv6 addresses */
+
+  /* three convenient "aliases" that follow the name scheme better */
+#define CURLOPT_RTSPHEADER CURLOPT_HTTPHEADER
+
+  /* These enums are for use with the CURLOPT_HTTP_VERSION option. */
+enum {
+  CURL_HTTP_VERSION_NONE, /* setting this means we don't care, and that we'd
+                             like the library to choose the best possible
+                             for us! */
+  CURL_HTTP_VERSION_1_0,  /* please use HTTP 1.0 in the request */
+  CURL_HTTP_VERSION_1_1,  /* please use HTTP 1.1 in the request */
+  CURL_HTTP_VERSION_2_0,  /* please use HTTP 2 in the request */
+  CURL_HTTP_VERSION_2TLS, /* use version 2 for HTTPS, version 1.1 for HTTP */
+  CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE,  /* please use HTTP 2 without HTTP/1.1
+                                           Upgrade */
+
+  CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */
+};
+
+/* Convenience definition simple because the name of the version is HTTP/2 and
+   not 2.0. The 2_0 version of the enum name was set while the version was
+   still planned to be 2.0 and we stick to it for compatibility. */
+#define CURL_HTTP_VERSION_2 CURL_HTTP_VERSION_2_0
+
+/*
+ * Public API enums for RTSP requests
+ */
+enum {
+    CURL_RTSPREQ_NONE, /* first in list */
+    CURL_RTSPREQ_OPTIONS,
+    CURL_RTSPREQ_DESCRIBE,
+    CURL_RTSPREQ_ANNOUNCE,
+    CURL_RTSPREQ_SETUP,
+    CURL_RTSPREQ_PLAY,
+    CURL_RTSPREQ_PAUSE,
+    CURL_RTSPREQ_TEARDOWN,
+    CURL_RTSPREQ_GET_PARAMETER,
+    CURL_RTSPREQ_SET_PARAMETER,
+    CURL_RTSPREQ_RECORD,
+    CURL_RTSPREQ_RECEIVE,
+    CURL_RTSPREQ_LAST /* last in list */
+};
+
+  /* These enums are for use with the CURLOPT_NETRC option. */
+enum CURL_NETRC_OPTION {
+  CURL_NETRC_IGNORED,     /* The .netrc will never be read.
+                           * This is the default. */
+  CURL_NETRC_OPTIONAL,    /* A user:password in the URL will be preferred
+                           * to one in the .netrc. */
+  CURL_NETRC_REQUIRED,    /* A user:password in the URL will be ignored.
+                           * Unless one is set programmatically, the .netrc
+                           * will be queried. */
+  CURL_NETRC_LAST
+};
+
+enum {
+  CURL_SSLVERSION_DEFAULT,
+  CURL_SSLVERSION_TLSv1, /* TLS 1.x */
+  CURL_SSLVERSION_SSLv2,
+  CURL_SSLVERSION_SSLv3,
+  CURL_SSLVERSION_TLSv1_0,
+  CURL_SSLVERSION_TLSv1_1,
+  CURL_SSLVERSION_TLSv1_2,
+  CURL_SSLVERSION_TLSv1_3,
+
+  CURL_SSLVERSION_LAST /* never use, keep last */
+};
+
+enum {
+  CURL_SSLVERSION_MAX_NONE =     0,
+  CURL_SSLVERSION_MAX_DEFAULT =  (CURL_SSLVERSION_TLSv1   << 16),
+  CURL_SSLVERSION_MAX_TLSv1_0 =  (CURL_SSLVERSION_TLSv1_0 << 16),
+  CURL_SSLVERSION_MAX_TLSv1_1 =  (CURL_SSLVERSION_TLSv1_1 << 16),
+  CURL_SSLVERSION_MAX_TLSv1_2 =  (CURL_SSLVERSION_TLSv1_2 << 16),
+  CURL_SSLVERSION_MAX_TLSv1_3 =  (CURL_SSLVERSION_TLSv1_3 << 16),
+
+  /* never use, keep last */
+  CURL_SSLVERSION_MAX_LAST =     (CURL_SSLVERSION_LAST    << 16)
+};
+
+enum CURL_TLSAUTH {
+  CURL_TLSAUTH_NONE,
+  CURL_TLSAUTH_SRP,
+  CURL_TLSAUTH_LAST /* never use, keep last */
+};
+
+/* symbols to use with CURLOPT_POSTREDIR.
+   CURL_REDIR_POST_301, CURL_REDIR_POST_302 and CURL_REDIR_POST_303
+   can be bitwise ORed so that CURL_REDIR_POST_301 | CURL_REDIR_POST_302
+   | CURL_REDIR_POST_303 == CURL_REDIR_POST_ALL */
+
+#define CURL_REDIR_GET_ALL  0
+#define CURL_REDIR_POST_301 1
+#define CURL_REDIR_POST_302 2
+#define CURL_REDIR_POST_303 4
+#define CURL_REDIR_POST_ALL \
+    (CURL_REDIR_POST_301|CURL_REDIR_POST_302|CURL_REDIR_POST_303)
+
+typedef enum {
+  CURL_TIMECOND_NONE,
+
+  CURL_TIMECOND_IFMODSINCE,
+  CURL_TIMECOND_IFUNMODSINCE,
+  CURL_TIMECOND_LASTMOD,
+
+  CURL_TIMECOND_LAST
+} curl_TimeCond;
+
+/* Special size_t value signaling a zero-terminated string. */
+#define CURL_ZERO_TERMINATED ((size_t) -1)
+
+/* curl_strequal() and curl_strnequal() are subject for removal in a future
+   release */
+CURL_EXTERN int curl_strequal(const char *s1, const char *s2);
+CURL_EXTERN int curl_strnequal(const char *s1, const char *s2, size_t n);
+
+/* Mime/form handling support. */
+typedef struct curl_mime_s      curl_mime;      /* Mime context. */
+typedef struct curl_mimepart_s  curl_mimepart;  /* Mime part context. */
+
+/*
+ * NAME curl_mime_init()
+ *
+ * DESCRIPTION
+ *
+ * Create a mime context and return its handle. The easy parameter is the
+ * target handle.
+ */
+CURL_EXTERN curl_mime *curl_mime_init(CURL *easy);
+
+/*
+ * NAME curl_mime_free()
+ *
+ * DESCRIPTION
+ *
+ * release a mime handle and its substructures.
+ */
+CURL_EXTERN void curl_mime_free(curl_mime *mime);
+
+/*
+ * NAME curl_mime_addpart()
+ *
+ * DESCRIPTION
+ *
+ * Append a new empty part to the given mime context and return a handle to
+ * the created part.
+ */
+CURL_EXTERN curl_mimepart *curl_mime_addpart(curl_mime *mime);
+
+/*
+ * NAME curl_mime_name()
+ *
+ * DESCRIPTION
+ *
+ * Set mime/form part name.
+ */
+CURL_EXTERN CURLcode curl_mime_name(curl_mimepart *part, const char *name);
+
+/*
+ * NAME curl_mime_filename()
+ *
+ * DESCRIPTION
+ *
+ * Set mime part remote file name.
+ */
+CURL_EXTERN CURLcode curl_mime_filename(curl_mimepart *part,
+                                        const char *filename);
+
+/*
+ * NAME curl_mime_type()
+ *
+ * DESCRIPTION
+ *
+ * Set mime part type.
+ */
+CURL_EXTERN CURLcode curl_mime_type(curl_mimepart *part, const char *mimetype);
+
+/*
+ * NAME curl_mime_encoder()
+ *
+ * DESCRIPTION
+ *
+ * Set mime data transfer encoder.
+ */
+CURL_EXTERN CURLcode curl_mime_encoder(curl_mimepart *part,
+                                       const char *encoding);
+
+/*
+ * NAME curl_mime_data()
+ *
+ * DESCRIPTION
+ *
+ * Set mime part data source from memory data,
+ */
+CURL_EXTERN CURLcode curl_mime_data(curl_mimepart *part,
+                                    const char *data, size_t datasize);
+
+/*
+ * NAME curl_mime_filedata()
+ *
+ * DESCRIPTION
+ *
+ * Set mime part data source from named file.
+ */
+CURL_EXTERN CURLcode curl_mime_filedata(curl_mimepart *part,
+                                        const char *filename);
+
+/*
+ * NAME curl_mime_data_cb()
+ *
+ * DESCRIPTION
+ *
+ * Set mime part data source from callback function.
+ */
+CURL_EXTERN CURLcode curl_mime_data_cb(curl_mimepart *part,
+                                       curl_off_t datasize,
+                                       curl_read_callback readfunc,
+                                       curl_seek_callback seekfunc,
+                                       curl_free_callback freefunc,
+                                       void *arg);
+
+/*
+ * NAME curl_mime_subparts()
+ *
+ * DESCRIPTION
+ *
+ * Set mime part data source from subparts.
+ */
+CURL_EXTERN CURLcode curl_mime_subparts(curl_mimepart *part,
+                                        curl_mime *subparts);
+/*
+ * NAME curl_mime_headers()
+ *
+ * DESCRIPTION
+ *
+ * Set mime part headers.
+ */
+CURL_EXTERN CURLcode curl_mime_headers(curl_mimepart *part,
+                                       struct curl_slist *headers,
+                                       int take_ownership);
+
+/* Old form API. */
+/* name is uppercase CURLFORM_<name> */
+#ifdef CFINIT
+#undef CFINIT
+#endif
+
+#ifdef CURL_ISOCPP
+#define CFINIT(name) CURLFORM_ ## name
+#else
+/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */
+#define CFINIT(name) CURLFORM_/**/name
+#endif
+
+typedef enum {
+  CFINIT(NOTHING),        /********* the first one is unused ************/
+
+  /*  */
+  CFINIT(COPYNAME),
+  CFINIT(PTRNAME),
+  CFINIT(NAMELENGTH),
+  CFINIT(COPYCONTENTS),
+  CFINIT(PTRCONTENTS),
+  CFINIT(CONTENTSLENGTH),
+  CFINIT(FILECONTENT),
+  CFINIT(ARRAY),
+  CFINIT(OBSOLETE),
+  CFINIT(FILE),
+
+  CFINIT(BUFFER),
+  CFINIT(BUFFERPTR),
+  CFINIT(BUFFERLENGTH),
+
+  CFINIT(CONTENTTYPE),
+  CFINIT(CONTENTHEADER),
+  CFINIT(FILENAME),
+  CFINIT(END),
+  CFINIT(OBSOLETE2),
+
+  CFINIT(STREAM),
+  CFINIT(CONTENTLEN), /* added in 7.46.0, provide a curl_off_t length */
+
+  CURLFORM_LASTENTRY /* the last unused */
+} CURLformoption;
+
+#undef CFINIT /* done */
+
+/* structure to be used as parameter for CURLFORM_ARRAY */
+struct curl_forms {
+  CURLformoption option;
+  const char     *value;
+};
+
+/* use this for multipart formpost building */
+/* Returns code for curl_formadd()
+ *
+ * Returns:
+ * CURL_FORMADD_OK             on success
+ * CURL_FORMADD_MEMORY         if the FormInfo allocation fails
+ * CURL_FORMADD_OPTION_TWICE   if one option is given twice for one Form
+ * CURL_FORMADD_NULL           if a null pointer was given for a char
+ * CURL_FORMADD_MEMORY         if the allocation of a FormInfo struct failed
+ * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used
+ * CURL_FORMADD_INCOMPLETE     if the some FormInfo is not complete (or error)
+ * CURL_FORMADD_MEMORY         if a curl_httppost struct cannot be allocated
+ * CURL_FORMADD_MEMORY         if some allocation for string copying failed.
+ * CURL_FORMADD_ILLEGAL_ARRAY  if an illegal option is used in an array
+ *
+ ***************************************************************************/
+typedef enum {
+  CURL_FORMADD_OK, /* first, no error */
+
+  CURL_FORMADD_MEMORY,
+  CURL_FORMADD_OPTION_TWICE,
+  CURL_FORMADD_NULL,
+  CURL_FORMADD_UNKNOWN_OPTION,
+  CURL_FORMADD_INCOMPLETE,
+  CURL_FORMADD_ILLEGAL_ARRAY,
+  CURL_FORMADD_DISABLED, /* libcurl was built with this disabled */
+
+  CURL_FORMADD_LAST /* last */
+} CURLFORMcode;
+
+/*
+ * NAME curl_formadd()
+ *
+ * DESCRIPTION
+ *
+ * Pretty advanced function for building multi-part formposts. Each invoke
+ * adds one part that together construct a full post. Then use
+ * CURLOPT_HTTPPOST to send it off to libcurl.
+ */
+CURL_EXTERN CURLFORMcode curl_formadd(struct curl_httppost **httppost,
+                                      struct curl_httppost **last_post,
+                                      ...);
+
+/*
+ * callback function for curl_formget()
+ * The void *arg pointer will be the one passed as second argument to
+ *   curl_formget().
+ * The character buffer passed to it must not be freed.
+ * Should return the buffer length passed to it as the argument "len" on
+ *   success.
+ */
+typedef size_t (*curl_formget_callback)(void *arg, const char *buf,
+                                        size_t len);
+
+/*
+ * NAME curl_formget()
+ *
+ * DESCRIPTION
+ *
+ * Serialize a curl_httppost struct built with curl_formadd().
+ * Accepts a void pointer as second argument which will be passed to
+ * the curl_formget_callback function.
+ * Returns 0 on success.
+ */
+CURL_EXTERN int curl_formget(struct curl_httppost *form, void *arg,
+                             curl_formget_callback append);
+/*
+ * NAME curl_formfree()
+ *
+ * DESCRIPTION
+ *
+ * Free a multipart formpost previously built with curl_formadd().
+ */
+CURL_EXTERN void curl_formfree(struct curl_httppost *form);
+
+/*
+ * NAME curl_getenv()
+ *
+ * DESCRIPTION
+ *
+ * Returns a malloc()'ed string that MUST be curl_free()ed after usage is
+ * complete. DEPRECATED - see lib/README.curlx
+ */
+CURL_EXTERN char *curl_getenv(const char *variable);
+
+/*
+ * NAME curl_version()
+ *
+ * DESCRIPTION
+ *
+ * Returns a static ascii string of the libcurl version.
+ */
+CURL_EXTERN char *curl_version(void);
+
+/*
+ * NAME curl_easy_escape()
+ *
+ * DESCRIPTION
+ *
+ * Escapes URL strings (converts all letters consider illegal in URLs to their
+ * %XX versions). This function returns a new allocated string or NULL if an
+ * error occurred.
+ */
+CURL_EXTERN char *curl_easy_escape(CURL *handle,
+                                   const char *string,
+                                   int length);
+
+/* the previous version: */
+CURL_EXTERN char *curl_escape(const char *string,
+                              int length);
+
+
+/*
+ * NAME curl_easy_unescape()
+ *
+ * DESCRIPTION
+ *
+ * Unescapes URL encoding in strings (converts all %XX codes to their 8bit
+ * versions). This function returns a new allocated string or NULL if an error
+ * occurred.
+ * Conversion Note: On non-ASCII platforms the ASCII %XX codes are
+ * converted into the host encoding.
+ */
+CURL_EXTERN char *curl_easy_unescape(CURL *handle,
+                                     const char *string,
+                                     int length,
+                                     int *outlength);
+
+/* the previous version */
+CURL_EXTERN char *curl_unescape(const char *string,
+                                int length);
+
+/*
+ * NAME curl_free()
+ *
+ * DESCRIPTION
+ *
+ * Provided for de-allocation in the same translation unit that did the
+ * allocation. Added in libcurl 7.10
+ */
+CURL_EXTERN void curl_free(void *p);
+
+/*
+ * NAME curl_global_init()
+ *
+ * DESCRIPTION
+ *
+ * curl_global_init() should be invoked exactly once for each application that
+ * uses libcurl and before any call of other libcurl functions.
+ *
+ * This function is not thread-safe!
+ */
+CURL_EXTERN CURLcode curl_global_init(long flags);
+
+/*
+ * NAME curl_global_init_mem()
+ *
+ * DESCRIPTION
+ *
+ * curl_global_init() or curl_global_init_mem() should be invoked exactly once
+ * for each application that uses libcurl.  This function can be used to
+ * initialize libcurl and set user defined memory management callback
+ * functions.  Users can implement memory management routines to check for
+ * memory leaks, check for mis-use of the curl library etc.  User registered
+ * callback routines with be invoked by this library instead of the system
+ * memory management routines like malloc, free etc.
+ */
+CURL_EXTERN CURLcode curl_global_init_mem(long flags,
+                                          curl_malloc_callback m,
+                                          curl_free_callback f,
+                                          curl_realloc_callback r,
+                                          curl_strdup_callback s,
+                                          curl_calloc_callback c);
+
+/*
+ * NAME curl_global_cleanup()
+ *
+ * DESCRIPTION
+ *
+ * curl_global_cleanup() should be invoked exactly once for each application
+ * that uses libcurl
+ */
+CURL_EXTERN void curl_global_cleanup(void);
+
+/* linked-list structure for the CURLOPT_QUOTE option (and other) */
+struct curl_slist {
+  char *data;
+  struct curl_slist *next;
+};
+
+/*
+ * NAME curl_global_sslset()
+ *
+ * DESCRIPTION
+ *
+ * When built with multiple SSL backends, curl_global_sslset() allows to
+ * choose one. This function can only be called once, and it must be called
+ * *before* curl_global_init().
+ *
+ * The backend can be identified by the id (e.g. CURLSSLBACKEND_OPENSSL). The
+ * backend can also be specified via the name parameter (passing -1 as id).
+ * If both id and name are specified, the name will be ignored. If neither id
+ * nor name are specified, the function will fail with
+ * CURLSSLSET_UNKNOWN_BACKEND and set the "avail" pointer to the
+ * NULL-terminated list of available backends.
+ *
+ * Upon success, the function returns CURLSSLSET_OK.
+ *
+ * If the specified SSL backend is not available, the function returns
+ * CURLSSLSET_UNKNOWN_BACKEND and sets the "avail" pointer to a NULL-terminated
+ * list of available SSL backends.
+ *
+ * The SSL backend can be set only once. If it has already been set, a
+ * subsequent attempt to change it will result in a CURLSSLSET_TOO_LATE.
+ */
+
+typedef struct {
+  curl_sslbackend id;
+  const char *name;
+} curl_ssl_backend;
+
+typedef enum {
+  CURLSSLSET_OK = 0,
+  CURLSSLSET_UNKNOWN_BACKEND,
+  CURLSSLSET_TOO_LATE,
+  CURLSSLSET_NO_BACKENDS /* libcurl was built without any SSL support */
+} CURLsslset;
+
+CURL_EXTERN CURLsslset curl_global_sslset(curl_sslbackend id, const char *name,
+                                          const curl_ssl_backend ***avail);
+
+/*
+ * NAME curl_slist_append()
+ *
+ * DESCRIPTION
+ *
+ * Appends a string to a linked list. If no list exists, it will be created
+ * first. Returns the new list, after appending.
+ */
+CURL_EXTERN struct curl_slist *curl_slist_append(struct curl_slist *,
+                                                 const char *);
+
+/*
+ * NAME curl_slist_free_all()
+ *
+ * DESCRIPTION
+ *
+ * free a previously built curl_slist.
+ */
+CURL_EXTERN void curl_slist_free_all(struct curl_slist *);
+
+/*
+ * NAME curl_getdate()
+ *
+ * DESCRIPTION
+ *
+ * Returns the time, in seconds since 1 Jan 1970 of the time string given in
+ * the first argument. The time argument in the second parameter is unused
+ * and should be set to NULL.
+ */
+CURL_EXTERN time_t curl_getdate(const char *p, const time_t *unused);
+
+/* info about the certificate chain, only for OpenSSL, GnuTLS, Schannel, NSS
+   and GSKit builds. Asked for with CURLOPT_CERTINFO / CURLINFO_CERTINFO */
+struct curl_certinfo {
+  int num_of_certs;             /* number of certificates with information */
+  struct curl_slist **certinfo; /* for each index in this array, there's a
+                                   linked list with textual information in the
+                                   format "name: value" */
+};
+
+/* Information about the SSL library used and the respective internal SSL
+   handle, which can be used to obtain further information regarding the
+   connection. Asked for with CURLINFO_TLS_SSL_PTR or CURLINFO_TLS_SESSION. */
+struct curl_tlssessioninfo {
+  curl_sslbackend backend;
+  void *internals;
+};
+
+#define CURLINFO_STRING   0x100000
+#define CURLINFO_LONG     0x200000
+#define CURLINFO_DOUBLE   0x300000
+#define CURLINFO_SLIST    0x400000
+#define CURLINFO_PTR      0x400000 /* same as SLIST */
+#define CURLINFO_SOCKET   0x500000
+#define CURLINFO_OFF_T    0x600000
+#define CURLINFO_MASK     0x0fffff
+#define CURLINFO_TYPEMASK 0xf00000
+
+typedef enum {
+  CURLINFO_NONE, /* first, never use this */
+  CURLINFO_EFFECTIVE_URL    = CURLINFO_STRING + 1,
+  CURLINFO_RESPONSE_CODE    = CURLINFO_LONG   + 2,
+  CURLINFO_TOTAL_TIME       = CURLINFO_DOUBLE + 3,
+  CURLINFO_NAMELOOKUP_TIME  = CURLINFO_DOUBLE + 4,
+  CURLINFO_CONNECT_TIME     = CURLINFO_DOUBLE + 5,
+  CURLINFO_PRETRANSFER_TIME = CURLINFO_DOUBLE + 6,
+  CURLINFO_SIZE_UPLOAD      = CURLINFO_DOUBLE + 7,
+  CURLINFO_SIZE_UPLOAD_T    = CURLINFO_OFF_T  + 7,
+  CURLINFO_SIZE_DOWNLOAD    = CURLINFO_DOUBLE + 8,
+  CURLINFO_SIZE_DOWNLOAD_T  = CURLINFO_OFF_T  + 8,
+  CURLINFO_SPEED_DOWNLOAD   = CURLINFO_DOUBLE + 9,
+  CURLINFO_SPEED_DOWNLOAD_T = CURLINFO_OFF_T  + 9,
+  CURLINFO_SPEED_UPLOAD     = CURLINFO_DOUBLE + 10,
+  CURLINFO_SPEED_UPLOAD_T   = CURLINFO_OFF_T  + 10,
+  CURLINFO_HEADER_SIZE      = CURLINFO_LONG   + 11,
+  CURLINFO_REQUEST_SIZE     = CURLINFO_LONG   + 12,
+  CURLINFO_SSL_VERIFYRESULT = CURLINFO_LONG   + 13,
+  CURLINFO_FILETIME         = CURLINFO_LONG   + 14,
+  CURLINFO_FILETIME_T       = CURLINFO_OFF_T  + 14,
+  CURLINFO_CONTENT_LENGTH_DOWNLOAD   = CURLINFO_DOUBLE + 15,
+  CURLINFO_CONTENT_LENGTH_DOWNLOAD_T = CURLINFO_OFF_T  + 15,
+  CURLINFO_CONTENT_LENGTH_UPLOAD     = CURLINFO_DOUBLE + 16,
+  CURLINFO_CONTENT_LENGTH_UPLOAD_T   = CURLINFO_OFF_T  + 16,
+  CURLINFO_STARTTRANSFER_TIME = CURLINFO_DOUBLE + 17,
+  CURLINFO_CONTENT_TYPE     = CURLINFO_STRING + 18,
+  CURLINFO_REDIRECT_TIME    = CURLINFO_DOUBLE + 19,
+  CURLINFO_REDIRECT_COUNT   = CURLINFO_LONG   + 20,
+  CURLINFO_PRIVATE          = CURLINFO_STRING + 21,
+  CURLINFO_HTTP_CONNECTCODE = CURLINFO_LONG   + 22,
+  CURLINFO_HTTPAUTH_AVAIL   = CURLINFO_LONG   + 23,
+  CURLINFO_PROXYAUTH_AVAIL  = CURLINFO_LONG   + 24,
+  CURLINFO_OS_ERRNO         = CURLINFO_LONG   + 25,
+  CURLINFO_NUM_CONNECTS     = CURLINFO_LONG   + 26,
+  CURLINFO_SSL_ENGINES      = CURLINFO_SLIST  + 27,
+  CURLINFO_COOKIELIST       = CURLINFO_SLIST  + 28,
+  CURLINFO_LASTSOCKET       = CURLINFO_LONG   + 29,
+  CURLINFO_FTP_ENTRY_PATH   = CURLINFO_STRING + 30,
+  CURLINFO_REDIRECT_URL     = CURLINFO_STRING + 31,
+  CURLINFO_PRIMARY_IP       = CURLINFO_STRING + 32,
+  CURLINFO_APPCONNECT_TIME  = CURLINFO_DOUBLE + 33,
+  CURLINFO_CERTINFO         = CURLINFO_PTR    + 34,
+  CURLINFO_CONDITION_UNMET  = CURLINFO_LONG   + 35,
+  CURLINFO_RTSP_SESSION_ID  = CURLINFO_STRING + 36,
+  CURLINFO_RTSP_CLIENT_CSEQ = CURLINFO_LONG   + 37,
+  CURLINFO_RTSP_SERVER_CSEQ = CURLINFO_LONG   + 38,
+  CURLINFO_RTSP_CSEQ_RECV   = CURLINFO_LONG   + 39,
+  CURLINFO_PRIMARY_PORT     = CURLINFO_LONG   + 40,
+  CURLINFO_LOCAL_IP         = CURLINFO_STRING + 41,
+  CURLINFO_LOCAL_PORT       = CURLINFO_LONG   + 42,
+  CURLINFO_TLS_SESSION      = CURLINFO_PTR    + 43,
+  CURLINFO_ACTIVESOCKET     = CURLINFO_SOCKET + 44,
+  CURLINFO_TLS_SSL_PTR      = CURLINFO_PTR    + 45,
+  CURLINFO_HTTP_VERSION     = CURLINFO_LONG   + 46,
+  CURLINFO_PROXY_SSL_VERIFYRESULT = CURLINFO_LONG + 47,
+  CURLINFO_PROTOCOL         = CURLINFO_LONG   + 48,
+  CURLINFO_SCHEME           = CURLINFO_STRING + 49,
+  /* Fill in new entries below here! */
+
+  /* Preferably these would be defined conditionally based on the
+     sizeof curl_off_t being 64-bits */
+  CURLINFO_TOTAL_TIME_T     = CURLINFO_OFF_T + 50,
+  CURLINFO_NAMELOOKUP_TIME_T = CURLINFO_OFF_T + 51,
+  CURLINFO_CONNECT_TIME_T   = CURLINFO_OFF_T + 52,
+  CURLINFO_PRETRANSFER_TIME_T = CURLINFO_OFF_T + 53,
+  CURLINFO_STARTTRANSFER_TIME_T = CURLINFO_OFF_T + 54,
+  CURLINFO_REDIRECT_TIME_T  = CURLINFO_OFF_T + 55,
+  CURLINFO_APPCONNECT_TIME_T = CURLINFO_OFF_T + 56,
+
+  CURLINFO_LASTONE          = 56
+} CURLINFO;
+
+/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
+   CURLINFO_HTTP_CODE */
+#define CURLINFO_HTTP_CODE CURLINFO_RESPONSE_CODE
+
+typedef enum {
+  CURLCLOSEPOLICY_NONE, /* first, never use this */
+
+  CURLCLOSEPOLICY_OLDEST,
+  CURLCLOSEPOLICY_LEAST_RECENTLY_USED,
+  CURLCLOSEPOLICY_LEAST_TRAFFIC,
+  CURLCLOSEPOLICY_SLOWEST,
+  CURLCLOSEPOLICY_CALLBACK,
+
+  CURLCLOSEPOLICY_LAST /* last, never use this */
+} curl_closepolicy;
+
+#define CURL_GLOBAL_SSL (1<<0) /* no purpose since since 7.57.0 */
+#define CURL_GLOBAL_WIN32 (1<<1)
+#define CURL_GLOBAL_ALL (CURL_GLOBAL_SSL|CURL_GLOBAL_WIN32)
+#define CURL_GLOBAL_NOTHING 0
+#define CURL_GLOBAL_DEFAULT CURL_GLOBAL_ALL
+#define CURL_GLOBAL_ACK_EINTR (1<<2)
+
+
+/*****************************************************************************
+ * Setup defines, protos etc for the sharing stuff.
+ */
+
+/* Different data locks for a single share */
+typedef enum {
+  CURL_LOCK_DATA_NONE = 0,
+  /*  CURL_LOCK_DATA_SHARE is used internally to say that
+   *  the locking is just made to change the internal state of the share
+   *  itself.
+   */
+  CURL_LOCK_DATA_SHARE,
+  CURL_LOCK_DATA_COOKIE,
+  CURL_LOCK_DATA_DNS,
+  CURL_LOCK_DATA_SSL_SESSION,
+  CURL_LOCK_DATA_CONNECT,
+  CURL_LOCK_DATA_PSL,
+  CURL_LOCK_DATA_LAST
+} curl_lock_data;
+
+/* Different lock access types */
+typedef enum {
+  CURL_LOCK_ACCESS_NONE = 0,   /* unspecified action */
+  CURL_LOCK_ACCESS_SHARED = 1, /* for read perhaps */
+  CURL_LOCK_ACCESS_SINGLE = 2, /* for write perhaps */
+  CURL_LOCK_ACCESS_LAST        /* never use */
+} curl_lock_access;
+
+typedef void (*curl_lock_function)(CURL *handle,
+                                   curl_lock_data data,
+                                   curl_lock_access locktype,
+                                   void *userptr);
+typedef void (*curl_unlock_function)(CURL *handle,
+                                     curl_lock_data data,
+                                     void *userptr);
+
+
+typedef enum {
+  CURLSHE_OK,  /* all is fine */
+  CURLSHE_BAD_OPTION, /* 1 */
+  CURLSHE_IN_USE,     /* 2 */
+  CURLSHE_INVALID,    /* 3 */
+  CURLSHE_NOMEM,      /* 4 out of memory */
+  CURLSHE_NOT_BUILT_IN, /* 5 feature not present in lib */
+  CURLSHE_LAST        /* never use */
+} CURLSHcode;
+
+typedef enum {
+  CURLSHOPT_NONE,  /* don't use */
+  CURLSHOPT_SHARE,   /* specify a data type to share */
+  CURLSHOPT_UNSHARE, /* specify which data type to stop sharing */
+  CURLSHOPT_LOCKFUNC,   /* pass in a 'curl_lock_function' pointer */
+  CURLSHOPT_UNLOCKFUNC, /* pass in a 'curl_unlock_function' pointer */
+  CURLSHOPT_USERDATA,   /* pass in a user data pointer used in the lock/unlock
+                           callback functions */
+  CURLSHOPT_LAST  /* never use */
+} CURLSHoption;
+
+CURL_EXTERN CURLSH *curl_share_init(void);
+CURL_EXTERN CURLSHcode curl_share_setopt(CURLSH *, CURLSHoption option, ...);
+CURL_EXTERN CURLSHcode curl_share_cleanup(CURLSH *);
+
+/****************************************************************************
+ * Structures for querying information about the curl library at runtime.
+ */
+
+typedef enum {
+  CURLVERSION_FIRST,
+  CURLVERSION_SECOND,
+  CURLVERSION_THIRD,
+  CURLVERSION_FOURTH,
+  CURLVERSION_FIFTH,
+  CURLVERSION_LAST /* never actually use this */
+} CURLversion;
+
+/* The 'CURLVERSION_NOW' is the symbolic name meant to be used by
+   basically all programs ever that want to get version information. It is
+   meant to be a built-in version number for what kind of struct the caller
+   expects. If the struct ever changes, we redefine the NOW to another enum
+   from above. */
+#define CURLVERSION_NOW CURLVERSION_FIFTH
+
+typedef struct {
+  CURLversion age;          /* age of the returned struct */
+  const char *version;      /* LIBCURL_VERSION */
+  unsigned int version_num; /* LIBCURL_VERSION_NUM */
+  const char *host;         /* OS/host/cpu/machine when configured */
+  int features;             /* bitmask, see defines below */
+  const char *ssl_version;  /* human readable string */
+  long ssl_version_num;     /* not used anymore, always 0 */
+  const char *libz_version; /* human readable string */
+  /* protocols is terminated by an entry with a NULL protoname */
+  const char * const *protocols;
+
+  /* The fields below this were added in CURLVERSION_SECOND */
+  const char *ares;
+  int ares_num;
+
+  /* This field was added in CURLVERSION_THIRD */
+  const char *libidn;
+
+  /* These field were added in CURLVERSION_FOURTH */
+
+  /* Same as '_libiconv_version' if built with HAVE_ICONV */
+  int iconv_ver_num;
+
+  const char *libssh_version; /* human readable string */
+
+  /* These fields were added in CURLVERSION_FIFTH */
+
+  unsigned int brotli_ver_num; /* Numeric Brotli version
+                                  (MAJOR << 24) | (MINOR << 12) | PATCH */
+  const char *brotli_version; /* human readable string. */
+
+} curl_version_info_data;
+
+#define CURL_VERSION_IPV6         (1<<0)  /* IPv6-enabled */
+#define CURL_VERSION_KERBEROS4    (1<<1)  /* Kerberos V4 auth is supported
+                                             (deprecated) */
+#define CURL_VERSION_SSL          (1<<2)  /* SSL options are present */
+#define CURL_VERSION_LIBZ         (1<<3)  /* libz features are present */
+#define CURL_VERSION_NTLM         (1<<4)  /* NTLM auth is supported */
+#define CURL_VERSION_GSSNEGOTIATE (1<<5)  /* Negotiate auth is supported
+                                             (deprecated) */
+#define CURL_VERSION_DEBUG        (1<<6)  /* Built with debug capabilities */
+#define CURL_VERSION_ASYNCHDNS    (1<<7)  /* Asynchronous DNS resolves */
+#define CURL_VERSION_SPNEGO       (1<<8)  /* SPNEGO auth is supported */
+#define CURL_VERSION_LARGEFILE    (1<<9)  /* Supports files larger than 2GB */
+#define CURL_VERSION_IDN          (1<<10) /* Internationized Domain Names are
+                                             supported */
+#define CURL_VERSION_SSPI         (1<<11) /* Built against Windows SSPI */
+#define CURL_VERSION_CONV         (1<<12) /* Character conversions supported */
+#define CURL_VERSION_CURLDEBUG    (1<<13) /* Debug memory tracking supported */
+#define CURL_VERSION_TLSAUTH_SRP  (1<<14) /* TLS-SRP auth is supported */
+#define CURL_VERSION_NTLM_WB      (1<<15) /* NTLM delegation to winbind helper
+                                             is supported */
+#define CURL_VERSION_HTTP2        (1<<16) /* HTTP2 support built-in */
+#define CURL_VERSION_GSSAPI       (1<<17) /* Built against a GSS-API library */
+#define CURL_VERSION_KERBEROS5    (1<<18) /* Kerberos V5 auth is supported */
+#define CURL_VERSION_UNIX_SOCKETS (1<<19) /* Unix domain sockets support */
+#define CURL_VERSION_PSL          (1<<20) /* Mozilla's Public Suffix List, used
+                                             for cookie domain verification */
+#define CURL_VERSION_HTTPS_PROXY  (1<<21) /* HTTPS-proxy support built-in */
+#define CURL_VERSION_MULTI_SSL    (1<<22) /* Multiple SSL backends available */
+#define CURL_VERSION_BROTLI       (1<<23) /* Brotli features are present. */
+#define CURL_VERSION_ALTSVC       (1<<24) /* Alt-Svc handling built-in */
+
+ /*
+ * NAME curl_version_info()
+ *
+ * DESCRIPTION
+ *
+ * This function returns a pointer to a static copy of the version info
+ * struct. See above.
+ */
+CURL_EXTERN curl_version_info_data *curl_version_info(CURLversion);
+
+/*
+ * NAME curl_easy_strerror()
+ *
+ * DESCRIPTION
+ *
+ * The curl_easy_strerror function may be used to turn a CURLcode value
+ * into the equivalent human readable error string.  This is useful
+ * for printing meaningful error messages.
+ */
+CURL_EXTERN const char *curl_easy_strerror(CURLcode);
+
+/*
+ * NAME curl_share_strerror()
+ *
+ * DESCRIPTION
+ *
+ * The curl_share_strerror function may be used to turn a CURLSHcode value
+ * into the equivalent human readable error string.  This is useful
+ * for printing meaningful error messages.
+ */
+CURL_EXTERN const char *curl_share_strerror(CURLSHcode);
+
+/*
+ * NAME curl_easy_pause()
+ *
+ * DESCRIPTION
+ *
+ * The curl_easy_pause function pauses or unpauses transfers. Select the new
+ * state by setting the bitmask, use the convenience defines below.
+ *
+ */
+CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask);
+
+#define CURLPAUSE_RECV      (1<<0)
+#define CURLPAUSE_RECV_CONT (0)
+
+#define CURLPAUSE_SEND      (1<<2)
+#define CURLPAUSE_SEND_CONT (0)
+
+#define CURLPAUSE_ALL       (CURLPAUSE_RECV|CURLPAUSE_SEND)
+#define CURLPAUSE_CONT      (CURLPAUSE_RECV_CONT|CURLPAUSE_SEND_CONT)
+
+#ifdef  __cplusplus
+}
+#endif
+
+/* unfortunately, the easy.h and multi.h include files need options and info
+  stuff before they can be included! */
+#include "easy.h" /* nothing in curl is fun without the easy stuff */
+#include "multi.h"
+#include "urlapi.h"
+
+/* the typechecker doesn't work in C++ (yet) */
+#if defined(__GNUC__) && defined(__GNUC_MINOR__) && \
+    ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && \
+    !defined(__cplusplus) && !defined(CURL_DISABLE_TYPECHECK)
+#include "typecheck-gcc.h"
+#else
+#if defined(__STDC__) && (__STDC__ >= 1)
+/* This preprocessor magic that replaces a call with the exact same call is
+   only done to make sure application authors pass exactly three arguments
+   to these functions. */
+#define curl_easy_setopt(handle,opt,param) curl_easy_setopt(handle,opt,param)
+#define curl_easy_getinfo(handle,info,arg) curl_easy_getinfo(handle,info,arg)
+#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param)
+#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param)
+#endif /* __STDC__ >= 1 */
+#endif /* gcc >= 4.3 && !__cplusplus */
+
+#endif /* __CURL_CURL_H */

+ 77 - 0
scbc.tools/Include/curl/curlver.h

@@ -0,0 +1,77 @@
+#ifndef __CURL_CURLVER_H
+#define __CURL_CURLVER_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* This header file contains nothing but libcurl version info, generated by
+   a script at release-time. This was made its own header file in 7.11.2 */
+
+/* This is the global package copyright */
+#define LIBCURL_COPYRIGHT "1996 - 2019 Daniel Stenberg, <daniel@haxx.se>."
+
+/* This is the version number of the libcurl package from which this header
+   file origins: */
+#define LIBCURL_VERSION "7.65.3"
+
+/* The numeric version number is also available "in parts" by using these
+   defines: */
+#define LIBCURL_VERSION_MAJOR 7
+#define LIBCURL_VERSION_MINOR 65
+#define LIBCURL_VERSION_PATCH 3
+
+/* This is the numeric version of the libcurl version number, meant for easier
+   parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
+   always follow this syntax:
+
+         0xXXYYZZ
+
+   Where XX, YY and ZZ are the main version, release and patch numbers in
+   hexadecimal (using 8 bits each). All three numbers are always represented
+   using two digits.  1.2 would appear as "0x010200" while version 9.11.7
+   appears as "0x090b07".
+
+   This 6-digit (24 bits) hexadecimal number does not show pre-release number,
+   and it is always a greater number in a more recent release. It makes
+   comparisons with greater than and less than work.
+
+   Note: This define is the full hex number and _does not_ use the
+   CURL_VERSION_BITS() macro since curl's own configure script greps for it
+   and needs it to contain the full number.
+*/
+#define LIBCURL_VERSION_NUM 0x074103
+
+/*
+ * This is the date and time when the full source package was created. The
+ * timestamp is not stored in git, as the timestamp is properly set in the
+ * tarballs by the maketgz script.
+ *
+ * The format of the date follows this template:
+ *
+ * "2007-11-23"
+ */
+#define LIBCURL_TIMESTAMP "2019-07-19"
+
+#define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|(z))
+#define CURL_AT_LEAST_VERSION(x,y,z) \
+  (LIBCURL_VERSION_NUM >= CURL_VERSION_BITS(x, y, z))
+
+#endif /* __CURL_CURLVER_H */

+ 112 - 0
scbc.tools/Include/curl/easy.h

@@ -0,0 +1,112 @@
+#ifndef __CURL_EASY_H
+#define __CURL_EASY_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+CURL_EXTERN CURL *curl_easy_init(void);
+CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);
+CURL_EXTERN CURLcode curl_easy_perform(CURL *curl);
+CURL_EXTERN void curl_easy_cleanup(CURL *curl);
+
+/*
+ * NAME curl_easy_getinfo()
+ *
+ * DESCRIPTION
+ *
+ * Request internal information from the curl session with this function.  The
+ * third argument MUST be a pointer to a long, a pointer to a char * or a
+ * pointer to a double (as the documentation describes elsewhere).  The data
+ * pointed to will be filled in accordingly and can be relied upon only if the
+ * function returns CURLE_OK.  This function is intended to get used *AFTER* a
+ * performed transfer, all results from this function are undefined until the
+ * transfer is completed.
+ */
+CURL_EXTERN CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...);
+
+
+/*
+ * NAME curl_easy_duphandle()
+ *
+ * DESCRIPTION
+ *
+ * Creates a new curl session handle with the same options set for the handle
+ * passed in. Duplicating a handle could only be a matter of cloning data and
+ * options, internal state info and things like persistent connections cannot
+ * be transferred. It is useful in multithreaded applications when you can run
+ * curl_easy_duphandle() for each new thread to avoid a series of identical
+ * curl_easy_setopt() invokes in every thread.
+ */
+CURL_EXTERN CURL *curl_easy_duphandle(CURL *curl);
+
+/*
+ * NAME curl_easy_reset()
+ *
+ * DESCRIPTION
+ *
+ * Re-initializes a CURL handle to the default values. This puts back the
+ * handle to the same state as it was in when it was just created.
+ *
+ * It does keep: live connections, the Session ID cache, the DNS cache and the
+ * cookies.
+ */
+CURL_EXTERN void curl_easy_reset(CURL *curl);
+
+/*
+ * NAME curl_easy_recv()
+ *
+ * DESCRIPTION
+ *
+ * Receives data from the connected socket. Use after successful
+ * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
+ */
+CURL_EXTERN CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen,
+                                    size_t *n);
+
+/*
+ * NAME curl_easy_send()
+ *
+ * DESCRIPTION
+ *
+ * Sends data over the connected socket. Use after successful
+ * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
+ */
+CURL_EXTERN CURLcode curl_easy_send(CURL *curl, const void *buffer,
+                                    size_t buflen, size_t *n);
+
+
+/*
+ * NAME curl_easy_upkeep()
+ *
+ * DESCRIPTION
+ *
+ * Performs connection upkeep for the given session handle.
+ */
+CURL_EXTERN CURLcode curl_easy_upkeep(CURL *curl);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif

+ 50 - 0
scbc.tools/Include/curl/mprintf.h

@@ -0,0 +1,50 @@
+#ifndef __CURL_MPRINTF_H
+#define __CURL_MPRINTF_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include <stdarg.h>
+#include <stdio.h> /* needed for FILE */
+#include "curl.h"  /* for CURL_EXTERN */
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+CURL_EXTERN int curl_mprintf(const char *format, ...);
+CURL_EXTERN int curl_mfprintf(FILE *fd, const char *format, ...);
+CURL_EXTERN int curl_msprintf(char *buffer, const char *format, ...);
+CURL_EXTERN int curl_msnprintf(char *buffer, size_t maxlength,
+                               const char *format, ...);
+CURL_EXTERN int curl_mvprintf(const char *format, va_list args);
+CURL_EXTERN int curl_mvfprintf(FILE *fd, const char *format, va_list args);
+CURL_EXTERN int curl_mvsprintf(char *buffer, const char *format, va_list args);
+CURL_EXTERN int curl_mvsnprintf(char *buffer, size_t maxlength,
+                                const char *format, va_list args);
+CURL_EXTERN char *curl_maprintf(const char *format, ...);
+CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif /* __CURL_MPRINTF_H */

+ 441 - 0
scbc.tools/Include/curl/multi.h

@@ -0,0 +1,441 @@
+#ifndef __CURL_MULTI_H
+#define __CURL_MULTI_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+/*
+  This is an "external" header file. Don't give away any internals here!
+
+  GOALS
+
+  o Enable a "pull" interface. The application that uses libcurl decides where
+    and when to ask libcurl to get/send data.
+
+  o Enable multiple simultaneous transfers in the same thread without making it
+    complicated for the application.
+
+  o Enable the application to select() on its own file descriptors and curl's
+    file descriptors simultaneous easily.
+
+*/
+
+/*
+ * This header file should not really need to include "curl.h" since curl.h
+ * itself includes this file and we expect user applications to do #include
+ * <curl/curl.h> without the need for especially including multi.h.
+ *
+ * For some reason we added this include here at one point, and rather than to
+ * break existing (wrongly written) libcurl applications, we leave it as-is
+ * but with this warning attached.
+ */
+#include "curl.h"
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#if defined(BUILDING_LIBCURL) || defined(CURL_STRICTER)
+typedef struct Curl_multi CURLM;
+#else
+typedef void CURLM;
+#endif
+
+typedef enum {
+  CURLM_CALL_MULTI_PERFORM = -1, /* please call curl_multi_perform() or
+                                    curl_multi_socket*() soon */
+  CURLM_OK,
+  CURLM_BAD_HANDLE,      /* the passed-in handle is not a valid CURLM handle */
+  CURLM_BAD_EASY_HANDLE, /* an easy handle was not good/valid */
+  CURLM_OUT_OF_MEMORY,   /* if you ever get this, you're in deep sh*t */
+  CURLM_INTERNAL_ERROR,  /* this is a libcurl bug */
+  CURLM_BAD_SOCKET,      /* the passed in socket argument did not match */
+  CURLM_UNKNOWN_OPTION,  /* curl_multi_setopt() with unsupported option */
+  CURLM_ADDED_ALREADY,   /* an easy handle already added to a multi handle was
+                            attempted to get added - again */
+  CURLM_RECURSIVE_API_CALL, /* an api function was called from inside a
+                               callback */
+  CURLM_LAST
+} CURLMcode;
+
+/* just to make code nicer when using curl_multi_socket() you can now check
+   for CURLM_CALL_MULTI_SOCKET too in the same style it works for
+   curl_multi_perform() and CURLM_CALL_MULTI_PERFORM */
+#define CURLM_CALL_MULTI_SOCKET CURLM_CALL_MULTI_PERFORM
+
+/* bitmask bits for CURLMOPT_PIPELINING */
+#define CURLPIPE_NOTHING   0L
+#define CURLPIPE_HTTP1     1L
+#define CURLPIPE_MULTIPLEX 2L
+
+typedef enum {
+  CURLMSG_NONE, /* first, not used */
+  CURLMSG_DONE, /* This easy handle has completed. 'result' contains
+                   the CURLcode of the transfer */
+  CURLMSG_LAST /* last, not used */
+} CURLMSG;
+
+struct CURLMsg {
+  CURLMSG msg;       /* what this message means */
+  CURL *easy_handle; /* the handle it concerns */
+  union {
+    void *whatever;    /* message-specific data */
+    CURLcode result;   /* return code for transfer */
+  } data;
+};
+typedef struct CURLMsg CURLMsg;
+
+/* Based on poll(2) structure and values.
+ * We don't use pollfd and POLL* constants explicitly
+ * to cover platforms without poll(). */
+#define CURL_WAIT_POLLIN    0x0001
+#define CURL_WAIT_POLLPRI   0x0002
+#define CURL_WAIT_POLLOUT   0x0004
+
+struct curl_waitfd {
+  curl_socket_t fd;
+  short events;
+  short revents; /* not supported yet */
+};
+
+/*
+ * Name:    curl_multi_init()
+ *
+ * Desc:    inititalize multi-style curl usage
+ *
+ * Returns: a new CURLM handle to use in all 'curl_multi' functions.
+ */
+CURL_EXTERN CURLM *curl_multi_init(void);
+
+/*
+ * Name:    curl_multi_add_handle()
+ *
+ * Desc:    add a standard curl handle to the multi stack
+ *
+ * Returns: CURLMcode type, general multi error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_add_handle(CURLM *multi_handle,
+                                            CURL *curl_handle);
+
+ /*
+  * Name:    curl_multi_remove_handle()
+  *
+  * Desc:    removes a curl handle from the multi stack again
+  *
+  * Returns: CURLMcode type, general multi error code.
+  */
+CURL_EXTERN CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
+                                               CURL *curl_handle);
+
+ /*
+  * Name:    curl_multi_fdset()
+  *
+  * Desc:    Ask curl for its fd_set sets. The app can use these to select() or
+  *          poll() on. We want curl_multi_perform() called as soon as one of
+  *          them are ready.
+  *
+  * Returns: CURLMcode type, general multi error code.
+  */
+CURL_EXTERN CURLMcode curl_multi_fdset(CURLM *multi_handle,
+                                       fd_set *read_fd_set,
+                                       fd_set *write_fd_set,
+                                       fd_set *exc_fd_set,
+                                       int *max_fd);
+
+/*
+ * Name:     curl_multi_wait()
+ *
+ * Desc:     Poll on all fds within a CURLM set as well as any
+ *           additional fds passed to the function.
+ *
+ * Returns:  CURLMcode type, general multi error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_wait(CURLM *multi_handle,
+                                      struct curl_waitfd extra_fds[],
+                                      unsigned int extra_nfds,
+                                      int timeout_ms,
+                                      int *ret);
+
+ /*
+  * Name:    curl_multi_perform()
+  *
+  * Desc:    When the app thinks there's data available for curl it calls this
+  *          function to read/write whatever there is right now. This returns
+  *          as soon as the reads and writes are done. This function does not
+  *          require that there actually is data available for reading or that
+  *          data can be written, it can be called just in case. It returns
+  *          the number of handles that still transfer data in the second
+  *          argument's integer-pointer.
+  *
+  * Returns: CURLMcode type, general multi error code. *NOTE* that this only
+  *          returns errors etc regarding the whole multi stack. There might
+  *          still have occurred problems on individual transfers even when
+  *          this returns OK.
+  */
+CURL_EXTERN CURLMcode curl_multi_perform(CURLM *multi_handle,
+                                         int *running_handles);
+
+ /*
+  * Name:    curl_multi_cleanup()
+  *
+  * Desc:    Cleans up and removes a whole multi stack. It does not free or
+  *          touch any individual easy handles in any way. We need to define
+  *          in what state those handles will be if this function is called
+  *          in the middle of a transfer.
+  *
+  * Returns: CURLMcode type, general multi error code.
+  */
+CURL_EXTERN CURLMcode curl_multi_cleanup(CURLM *multi_handle);
+
+/*
+ * Name:    curl_multi_info_read()
+ *
+ * Desc:    Ask the multi handle if there's any messages/informationals from
+ *          the individual transfers. Messages include informationals such as
+ *          error code from the transfer or just the fact that a transfer is
+ *          completed. More details on these should be written down as well.
+ *
+ *          Repeated calls to this function will return a new struct each
+ *          time, until a special "end of msgs" struct is returned as a signal
+ *          that there is no more to get at this point.
+ *
+ *          The data the returned pointer points to will not survive calling
+ *          curl_multi_cleanup().
+ *
+ *          The 'CURLMsg' struct is meant to be very simple and only contain
+ *          very basic information. If more involved information is wanted,
+ *          we will provide the particular "transfer handle" in that struct
+ *          and that should/could/would be used in subsequent
+ *          curl_easy_getinfo() calls (or similar). The point being that we
+ *          must never expose complex structs to applications, as then we'll
+ *          undoubtably get backwards compatibility problems in the future.
+ *
+ * Returns: A pointer to a filled-in struct, or NULL if it failed or ran out
+ *          of structs. It also writes the number of messages left in the
+ *          queue (after this read) in the integer the second argument points
+ *          to.
+ */
+CURL_EXTERN CURLMsg *curl_multi_info_read(CURLM *multi_handle,
+                                          int *msgs_in_queue);
+
+/*
+ * Name:    curl_multi_strerror()
+ *
+ * Desc:    The curl_multi_strerror function may be used to turn a CURLMcode
+ *          value into the equivalent human readable error string.  This is
+ *          useful for printing meaningful error messages.
+ *
+ * Returns: A pointer to a zero-terminated error message.
+ */
+CURL_EXTERN const char *curl_multi_strerror(CURLMcode);
+
+/*
+ * Name:    curl_multi_socket() and
+ *          curl_multi_socket_all()
+ *
+ * Desc:    An alternative version of curl_multi_perform() that allows the
+ *          application to pass in one of the file descriptors that have been
+ *          detected to have "action" on them and let libcurl perform.
+ *          See man page for details.
+ */
+#define CURL_POLL_NONE   0
+#define CURL_POLL_IN     1
+#define CURL_POLL_OUT    2
+#define CURL_POLL_INOUT  3
+#define CURL_POLL_REMOVE 4
+
+#define CURL_SOCKET_TIMEOUT CURL_SOCKET_BAD
+
+#define CURL_CSELECT_IN   0x01
+#define CURL_CSELECT_OUT  0x02
+#define CURL_CSELECT_ERR  0x04
+
+typedef int (*curl_socket_callback)(CURL *easy,      /* easy handle */
+                                    curl_socket_t s, /* socket */
+                                    int what,        /* see above */
+                                    void *userp,     /* private callback
+                                                        pointer */
+                                    void *socketp);  /* private socket
+                                                        pointer */
+/*
+ * Name:    curl_multi_timer_callback
+ *
+ * Desc:    Called by libcurl whenever the library detects a change in the
+ *          maximum number of milliseconds the app is allowed to wait before
+ *          curl_multi_socket() or curl_multi_perform() must be called
+ *          (to allow libcurl's timed events to take place).
+ *
+ * Returns: The callback should return zero.
+ */
+typedef int (*curl_multi_timer_callback)(CURLM *multi,    /* multi handle */
+                                         long timeout_ms, /* see above */
+                                         void *userp);    /* private callback
+                                                             pointer */
+
+CURL_EXTERN CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
+                                        int *running_handles);
+
+CURL_EXTERN CURLMcode curl_multi_socket_action(CURLM *multi_handle,
+                                               curl_socket_t s,
+                                               int ev_bitmask,
+                                               int *running_handles);
+
+CURL_EXTERN CURLMcode curl_multi_socket_all(CURLM *multi_handle,
+                                            int *running_handles);
+
+#ifndef CURL_ALLOW_OLD_MULTI_SOCKET
+/* This macro below was added in 7.16.3 to push users who recompile to use
+   the new curl_multi_socket_action() instead of the old curl_multi_socket()
+*/
+#define curl_multi_socket(x,y,z) curl_multi_socket_action(x,y,0,z)
+#endif
+
+/*
+ * Name:    curl_multi_timeout()
+ *
+ * Desc:    Returns the maximum number of milliseconds the app is allowed to
+ *          wait before curl_multi_socket() or curl_multi_perform() must be
+ *          called (to allow libcurl's timed events to take place).
+ *
+ * Returns: CURLM error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_timeout(CURLM *multi_handle,
+                                         long *milliseconds);
+
+#undef CINIT /* re-using the same name as in curl.h */
+
+#ifdef CURL_ISOCPP
+#define CINIT(name,type,num) CURLMOPT_ ## name = CURLOPTTYPE_ ## type + num
+#else
+/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */
+#define LONG          CURLOPTTYPE_LONG
+#define OBJECTPOINT   CURLOPTTYPE_OBJECTPOINT
+#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT
+#define OFF_T         CURLOPTTYPE_OFF_T
+#define CINIT(name,type,number) CURLMOPT_/**/name = type + number
+#endif
+
+typedef enum {
+  /* This is the socket callback function pointer */
+  CINIT(SOCKETFUNCTION, FUNCTIONPOINT, 1),
+
+  /* This is the argument passed to the socket callback */
+  CINIT(SOCKETDATA, OBJECTPOINT, 2),
+
+    /* set to 1 to enable pipelining for this multi handle */
+  CINIT(PIPELINING, LONG, 3),
+
+   /* This is the timer callback function pointer */
+  CINIT(TIMERFUNCTION, FUNCTIONPOINT, 4),
+
+  /* This is the argument passed to the timer callback */
+  CINIT(TIMERDATA, OBJECTPOINT, 5),
+
+  /* maximum number of entries in the connection cache */
+  CINIT(MAXCONNECTS, LONG, 6),
+
+  /* maximum number of (pipelining) connections to one host */
+  CINIT(MAX_HOST_CONNECTIONS, LONG, 7),
+
+  /* maximum number of requests in a pipeline */
+  CINIT(MAX_PIPELINE_LENGTH, LONG, 8),
+
+  /* a connection with a content-length longer than this
+     will not be considered for pipelining */
+  CINIT(CONTENT_LENGTH_PENALTY_SIZE, OFF_T, 9),
+
+  /* a connection with a chunk length longer than this
+     will not be considered for pipelining */
+  CINIT(CHUNK_LENGTH_PENALTY_SIZE, OFF_T, 10),
+
+  /* a list of site names(+port) that are blacklisted from
+     pipelining */
+  CINIT(PIPELINING_SITE_BL, OBJECTPOINT, 11),
+
+  /* a list of server types that are blacklisted from
+     pipelining */
+  CINIT(PIPELINING_SERVER_BL, OBJECTPOINT, 12),
+
+  /* maximum number of open connections in total */
+  CINIT(MAX_TOTAL_CONNECTIONS, LONG, 13),
+
+   /* This is the server push callback function pointer */
+  CINIT(PUSHFUNCTION, FUNCTIONPOINT, 14),
+
+  /* This is the argument passed to the server push callback */
+  CINIT(PUSHDATA, OBJECTPOINT, 15),
+
+  CURLMOPT_LASTENTRY /* the last unused */
+} CURLMoption;
+
+
+/*
+ * Name:    curl_multi_setopt()
+ *
+ * Desc:    Sets options for the multi handle.
+ *
+ * Returns: CURLM error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_setopt(CURLM *multi_handle,
+                                        CURLMoption option, ...);
+
+
+/*
+ * Name:    curl_multi_assign()
+ *
+ * Desc:    This function sets an association in the multi handle between the
+ *          given socket and a private pointer of the application. This is
+ *          (only) useful for curl_multi_socket uses.
+ *
+ * Returns: CURLM error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle,
+                                        curl_socket_t sockfd, void *sockp);
+
+
+/*
+ * Name: curl_push_callback
+ *
+ * Desc: This callback gets called when a new stream is being pushed by the
+ *       server. It approves or denies the new stream.
+ *
+ * Returns: CURL_PUSH_OK or CURL_PUSH_DENY.
+ */
+#define CURL_PUSH_OK   0
+#define CURL_PUSH_DENY 1
+
+struct curl_pushheaders;  /* forward declaration only */
+
+CURL_EXTERN char *curl_pushheader_bynum(struct curl_pushheaders *h,
+                                        size_t num);
+CURL_EXTERN char *curl_pushheader_byname(struct curl_pushheaders *h,
+                                         const char *name);
+
+typedef int (*curl_push_callback)(CURL *parent,
+                                  CURL *easy,
+                                  size_t num_headers,
+                                  struct curl_pushheaders *headers,
+                                  void *userp);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif

+ 33 - 0
scbc.tools/Include/curl/stdcheaders.h

@@ -0,0 +1,33 @@
+#ifndef __STDC_HEADERS_H
+#define __STDC_HEADERS_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include <sys/types.h>
+
+size_t fread(void *, size_t, size_t, FILE *);
+size_t fwrite(const void *, size_t, size_t, FILE *);
+
+int strcasecmp(const char *, const char *);
+int strncasecmp(const char *, const char *, size_t);
+
+#endif /* __STDC_HEADERS_H */

+ 493 - 0
scbc.tools/Include/curl/system.h

@@ -0,0 +1,493 @@
+#ifndef __CURL_SYSTEM_H
+#define __CURL_SYSTEM_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * Try to keep one section per platform, compiler and architecture, otherwise,
+ * if an existing section is reused for a different one and later on the
+ * original is adjusted, probably the piggybacking one can be adversely
+ * changed.
+ *
+ * In order to differentiate between platforms/compilers/architectures use
+ * only compiler built in predefined preprocessor symbols.
+ *
+ * curl_off_t
+ * ----------
+ *
+ * For any given platform/compiler curl_off_t must be typedef'ed to a 64-bit
+ * wide signed integral data type. The width of this data type must remain
+ * constant and independent of any possible large file support settings.
+ *
+ * As an exception to the above, curl_off_t shall be typedef'ed to a 32-bit
+ * wide signed integral data type if there is no 64-bit type.
+ *
+ * As a general rule, curl_off_t shall not be mapped to off_t. This rule shall
+ * only be violated if off_t is the only 64-bit data type available and the
+ * size of off_t is independent of large file support settings. Keep your
+ * build on the safe side avoiding an off_t gating.  If you have a 64-bit
+ * off_t then take for sure that another 64-bit data type exists, dig deeper
+ * and you will find it.
+ *
+ */
+
+#if defined(__DJGPP__) || defined(__GO32__)
+#  if defined(__DJGPP__) && (__DJGPP__ > 1)
+#    define CURL_TYPEOF_CURL_OFF_T     long long
+#    define CURL_FORMAT_CURL_OFF_T     "lld"
+#    define CURL_FORMAT_CURL_OFF_TU    "llu"
+#    define CURL_SUFFIX_CURL_OFF_T     LL
+#    define CURL_SUFFIX_CURL_OFF_TU    ULL
+#  else
+#    define CURL_TYPEOF_CURL_OFF_T     long
+#    define CURL_FORMAT_CURL_OFF_T     "ld"
+#    define CURL_FORMAT_CURL_OFF_TU    "lu"
+#    define CURL_SUFFIX_CURL_OFF_T     L
+#    define CURL_SUFFIX_CURL_OFF_TU    UL
+#  endif
+#  define CURL_TYPEOF_CURL_SOCKLEN_T int
+
+#elif defined(__SALFORDC__)
+#  define CURL_TYPEOF_CURL_OFF_T     long
+#  define CURL_FORMAT_CURL_OFF_T     "ld"
+#  define CURL_FORMAT_CURL_OFF_TU    "lu"
+#  define CURL_SUFFIX_CURL_OFF_T     L
+#  define CURL_SUFFIX_CURL_OFF_TU    UL
+#  define CURL_TYPEOF_CURL_SOCKLEN_T int
+
+#elif defined(__BORLANDC__)
+#  if (__BORLANDC__ < 0x520)
+#    define CURL_TYPEOF_CURL_OFF_T     long
+#    define CURL_FORMAT_CURL_OFF_T     "ld"
+#    define CURL_FORMAT_CURL_OFF_TU    "lu"
+#    define CURL_SUFFIX_CURL_OFF_T     L
+#    define CURL_SUFFIX_CURL_OFF_TU    UL
+#  else
+#    define CURL_TYPEOF_CURL_OFF_T     __int64
+#    define CURL_FORMAT_CURL_OFF_T     "I64d"
+#    define CURL_FORMAT_CURL_OFF_TU    "I64u"
+#    define CURL_SUFFIX_CURL_OFF_T     i64
+#    define CURL_SUFFIX_CURL_OFF_TU    ui64
+#  endif
+#  define CURL_TYPEOF_CURL_SOCKLEN_T int
+
+#elif defined(__TURBOC__)
+#  define CURL_TYPEOF_CURL_OFF_T     long
+#  define CURL_FORMAT_CURL_OFF_T     "ld"
+#  define CURL_FORMAT_CURL_OFF_TU    "lu"
+#  define CURL_SUFFIX_CURL_OFF_T     L
+#  define CURL_SUFFIX_CURL_OFF_TU    UL
+#  define CURL_TYPEOF_CURL_SOCKLEN_T int
+
+#elif defined(__WATCOMC__)
+#  if defined(__386__)
+#    define CURL_TYPEOF_CURL_OFF_T     __int64
+#    define CURL_FORMAT_CURL_OFF_T     "I64d"
+#    define CURL_FORMAT_CURL_OFF_TU    "I64u"
+#    define CURL_SUFFIX_CURL_OFF_T     i64
+#    define CURL_SUFFIX_CURL_OFF_TU    ui64
+#  else
+#    define CURL_TYPEOF_CURL_OFF_T     long
+#    define CURL_FORMAT_CURL_OFF_T     "ld"
+#    define CURL_FORMAT_CURL_OFF_TU    "lu"
+#    define CURL_SUFFIX_CURL_OFF_T     L
+#    define CURL_SUFFIX_CURL_OFF_TU    UL
+#  endif
+#  define CURL_TYPEOF_CURL_SOCKLEN_T int
+
+#elif defined(__POCC__)
+#  if (__POCC__ < 280)
+#    define CURL_TYPEOF_CURL_OFF_T     long
+#    define CURL_FORMAT_CURL_OFF_T     "ld"
+#    define CURL_FORMAT_CURL_OFF_TU    "lu"
+#    define CURL_SUFFIX_CURL_OFF_T     L
+#    define CURL_SUFFIX_CURL_OFF_TU    UL
+#  elif defined(_MSC_VER)
+#    define CURL_TYPEOF_CURL_OFF_T     __int64
+#    define CURL_FORMAT_CURL_OFF_T     "I64d"
+#    define CURL_FORMAT_CURL_OFF_TU    "I64u"
+#    define CURL_SUFFIX_CURL_OFF_T     i64
+#    define CURL_SUFFIX_CURL_OFF_TU    ui64
+#  else
+#    define CURL_TYPEOF_CURL_OFF_T     long long
+#    define CURL_FORMAT_CURL_OFF_T     "lld"
+#    define CURL_FORMAT_CURL_OFF_TU    "llu"
+#    define CURL_SUFFIX_CURL_OFF_T     LL
+#    define CURL_SUFFIX_CURL_OFF_TU    ULL
+#  endif
+#  define CURL_TYPEOF_CURL_SOCKLEN_T int
+
+#elif defined(__LCC__)
+#  define CURL_TYPEOF_CURL_OFF_T     long
+#  define CURL_FORMAT_CURL_OFF_T     "ld"
+#  define CURL_FORMAT_CURL_OFF_TU    "lu"
+#  define CURL_SUFFIX_CURL_OFF_T     L
+#  define CURL_SUFFIX_CURL_OFF_TU    UL
+#  define CURL_TYPEOF_CURL_SOCKLEN_T int
+
+#elif defined(__SYMBIAN32__)
+#  if defined(__EABI__)  /* Treat all ARM compilers equally */
+#    define CURL_TYPEOF_CURL_OFF_T     long long
+#    define CURL_FORMAT_CURL_OFF_T     "lld"
+#    define CURL_FORMAT_CURL_OFF_TU    "llu"
+#    define CURL_SUFFIX_CURL_OFF_T     LL
+#    define CURL_SUFFIX_CURL_OFF_TU    ULL
+#  elif defined(__CW32__)
+#    pragma longlong on
+#    define CURL_TYPEOF_CURL_OFF_T     long long
+#    define CURL_FORMAT_CURL_OFF_T     "lld"
+#    define CURL_FORMAT_CURL_OFF_TU    "llu"
+#    define CURL_SUFFIX_CURL_OFF_T     LL
+#    define CURL_SUFFIX_CURL_OFF_TU    ULL
+#  elif defined(__VC32__)
+#    define CURL_TYPEOF_CURL_OFF_T     __int64
+#    define CURL_FORMAT_CURL_OFF_T     "lld"
+#    define CURL_FORMAT_CURL_OFF_TU    "llu"
+#    define CURL_SUFFIX_CURL_OFF_T     LL
+#    define CURL_SUFFIX_CURL_OFF_TU    ULL
+#  endif
+#  define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
+
+#elif defined(__MWERKS__)
+#  define CURL_TYPEOF_CURL_OFF_T     long long
+#  define CURL_FORMAT_CURL_OFF_T     "lld"
+#  define CURL_FORMAT_CURL_OFF_TU    "llu"
+#  define CURL_SUFFIX_CURL_OFF_T     LL
+#  define CURL_SUFFIX_CURL_OFF_TU    ULL
+#  define CURL_TYPEOF_CURL_SOCKLEN_T int
+
+#elif defined(_WIN32_WCE)
+#  define CURL_TYPEOF_CURL_OFF_T     __int64
+#  define CURL_FORMAT_CURL_OFF_T     "I64d"
+#  define CURL_FORMAT_CURL_OFF_TU    "I64u"
+#  define CURL_SUFFIX_CURL_OFF_T     i64
+#  define CURL_SUFFIX_CURL_OFF_TU    ui64
+#  define CURL_TYPEOF_CURL_SOCKLEN_T int
+
+#elif defined(__MINGW32__)
+#  define CURL_TYPEOF_CURL_OFF_T     long long
+#  define CURL_FORMAT_CURL_OFF_T     "I64d"
+#  define CURL_FORMAT_CURL_OFF_TU    "I64u"
+#  define CURL_SUFFIX_CURL_OFF_T     LL
+#  define CURL_SUFFIX_CURL_OFF_TU    ULL
+#  define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
+#  define CURL_PULL_SYS_TYPES_H      1
+#  define CURL_PULL_WS2TCPIP_H       1
+
+#elif defined(__VMS)
+#  if defined(__VAX)
+#    define CURL_TYPEOF_CURL_OFF_T     long
+#    define CURL_FORMAT_CURL_OFF_T     "ld"
+#    define CURL_FORMAT_CURL_OFF_TU    "lu"
+#    define CURL_SUFFIX_CURL_OFF_T     L
+#    define CURL_SUFFIX_CURL_OFF_TU    UL
+#  else
+#    define CURL_TYPEOF_CURL_OFF_T     long long
+#    define CURL_FORMAT_CURL_OFF_T     "lld"
+#    define CURL_FORMAT_CURL_OFF_TU    "llu"
+#    define CURL_SUFFIX_CURL_OFF_T     LL
+#    define CURL_SUFFIX_CURL_OFF_TU    ULL
+#  endif
+#  define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
+
+#elif defined(__OS400__)
+#  if defined(__ILEC400__)
+#    define CURL_TYPEOF_CURL_OFF_T     long long
+#    define CURL_FORMAT_CURL_OFF_T     "lld"
+#    define CURL_FORMAT_CURL_OFF_TU    "llu"
+#    define CURL_SUFFIX_CURL_OFF_T     LL
+#    define CURL_SUFFIX_CURL_OFF_TU    ULL
+#    define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
+#    define CURL_PULL_SYS_TYPES_H      1
+#    define CURL_PULL_SYS_SOCKET_H     1
+#  endif
+
+#elif defined(__MVS__)
+#  if defined(__IBMC__) || defined(__IBMCPP__)
+#    if defined(_ILP32)
+#    elif defined(_LP64)
+#    endif
+#    if defined(_LONG_LONG)
+#      define CURL_TYPEOF_CURL_OFF_T     long long
+#      define CURL_FORMAT_CURL_OFF_T     "lld"
+#      define CURL_FORMAT_CURL_OFF_TU    "llu"
+#      define CURL_SUFFIX_CURL_OFF_T     LL
+#      define CURL_SUFFIX_CURL_OFF_TU    ULL
+#    elif defined(_LP64)
+#      define CURL_TYPEOF_CURL_OFF_T     long
+#      define CURL_FORMAT_CURL_OFF_T     "ld"
+#      define CURL_FORMAT_CURL_OFF_TU    "lu"
+#      define CURL_SUFFIX_CURL_OFF_T     L
+#      define CURL_SUFFIX_CURL_OFF_TU    UL
+#    else
+#      define CURL_TYPEOF_CURL_OFF_T     long
+#      define CURL_FORMAT_CURL_OFF_T     "ld"
+#      define CURL_FORMAT_CURL_OFF_TU    "lu"
+#      define CURL_SUFFIX_CURL_OFF_T     L
+#      define CURL_SUFFIX_CURL_OFF_TU    UL
+#    endif
+#    define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
+#    define CURL_PULL_SYS_TYPES_H      1
+#    define CURL_PULL_SYS_SOCKET_H     1
+#  endif
+
+#elif defined(__370__)
+#  if defined(__IBMC__) || defined(__IBMCPP__)
+#    if defined(_ILP32)
+#    elif defined(_LP64)
+#    endif
+#    if defined(_LONG_LONG)
+#      define CURL_TYPEOF_CURL_OFF_T     long long
+#      define CURL_FORMAT_CURL_OFF_T     "lld"
+#      define CURL_FORMAT_CURL_OFF_TU    "llu"
+#      define CURL_SUFFIX_CURL_OFF_T     LL
+#      define CURL_SUFFIX_CURL_OFF_TU    ULL
+#    elif defined(_LP64)
+#      define CURL_TYPEOF_CURL_OFF_T     long
+#      define CURL_FORMAT_CURL_OFF_T     "ld"
+#      define CURL_FORMAT_CURL_OFF_TU    "lu"
+#      define CURL_SUFFIX_CURL_OFF_T     L
+#      define CURL_SUFFIX_CURL_OFF_TU    UL
+#    else
+#      define CURL_TYPEOF_CURL_OFF_T     long
+#      define CURL_FORMAT_CURL_OFF_T     "ld"
+#      define CURL_FORMAT_CURL_OFF_TU    "lu"
+#      define CURL_SUFFIX_CURL_OFF_T     L
+#      define CURL_SUFFIX_CURL_OFF_TU    UL
+#    endif
+#    define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
+#    define CURL_PULL_SYS_TYPES_H      1
+#    define CURL_PULL_SYS_SOCKET_H     1
+#  endif
+
+#elif defined(TPF)
+#  define CURL_TYPEOF_CURL_OFF_T     long
+#  define CURL_FORMAT_CURL_OFF_T     "ld"
+#  define CURL_FORMAT_CURL_OFF_TU    "lu"
+#  define CURL_SUFFIX_CURL_OFF_T     L
+#  define CURL_SUFFIX_CURL_OFF_TU    UL
+#  define CURL_TYPEOF_CURL_SOCKLEN_T int
+
+#elif defined(__TINYC__) /* also known as tcc */
+
+#  define CURL_TYPEOF_CURL_OFF_T     long long
+#  define CURL_FORMAT_CURL_OFF_T     "lld"
+#  define CURL_FORMAT_CURL_OFF_TU    "llu"
+#  define CURL_SUFFIX_CURL_OFF_T     LL
+#  define CURL_SUFFIX_CURL_OFF_TU    ULL
+#  define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
+#  define CURL_PULL_SYS_TYPES_H      1
+#  define CURL_PULL_SYS_SOCKET_H     1
+
+#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) /* Oracle Solaris Studio */
+#  if !defined(__LP64) && (defined(__ILP32) ||                          \
+                           defined(__i386) ||                           \
+                           defined(__sparcv8) ||                        \
+                           defined(__sparcv8plus))
+#    define CURL_TYPEOF_CURL_OFF_T     long long
+#    define CURL_FORMAT_CURL_OFF_T     "lld"
+#    define CURL_FORMAT_CURL_OFF_TU    "llu"
+#    define CURL_SUFFIX_CURL_OFF_T     LL
+#    define CURL_SUFFIX_CURL_OFF_TU    ULL
+#  elif defined(__LP64) || \
+        defined(__amd64) || defined(__sparcv9)
+#    define CURL_TYPEOF_CURL_OFF_T     long
+#    define CURL_FORMAT_CURL_OFF_T     "ld"
+#    define CURL_FORMAT_CURL_OFF_TU    "lu"
+#    define CURL_SUFFIX_CURL_OFF_T     L
+#    define CURL_SUFFIX_CURL_OFF_TU    UL
+#  endif
+#  define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
+#  define CURL_PULL_SYS_TYPES_H      1
+#  define CURL_PULL_SYS_SOCKET_H     1
+
+#elif defined(__xlc__) /* IBM xlc compiler */
+#  if !defined(_LP64)
+#    define CURL_TYPEOF_CURL_OFF_T     long long
+#    define CURL_FORMAT_CURL_OFF_T     "lld"
+#    define CURL_FORMAT_CURL_OFF_TU    "llu"
+#    define CURL_SUFFIX_CURL_OFF_T     LL
+#    define CURL_SUFFIX_CURL_OFF_TU    ULL
+#  else
+#    define CURL_TYPEOF_CURL_OFF_T     long
+#    define CURL_FORMAT_CURL_OFF_T     "ld"
+#    define CURL_FORMAT_CURL_OFF_TU    "lu"
+#    define CURL_SUFFIX_CURL_OFF_T     L
+#    define CURL_SUFFIX_CURL_OFF_TU    UL
+#  endif
+#  define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
+#  define CURL_PULL_SYS_TYPES_H      1
+#  define CURL_PULL_SYS_SOCKET_H     1
+
+/* ===================================== */
+/*    KEEP MSVC THE PENULTIMATE ENTRY    */
+/* ===================================== */
+
+#elif defined(_MSC_VER)
+#  if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)
+#    define CURL_TYPEOF_CURL_OFF_T     __int64
+#    define CURL_FORMAT_CURL_OFF_T     "I64d"
+#    define CURL_FORMAT_CURL_OFF_TU    "I64u"
+#    define CURL_SUFFIX_CURL_OFF_T     i64
+#    define CURL_SUFFIX_CURL_OFF_TU    ui64
+#  else
+#    define CURL_TYPEOF_CURL_OFF_T     long
+#    define CURL_FORMAT_CURL_OFF_T     "ld"
+#    define CURL_FORMAT_CURL_OFF_TU    "lu"
+#    define CURL_SUFFIX_CURL_OFF_T     L
+#    define CURL_SUFFIX_CURL_OFF_TU    UL
+#  endif
+#  define CURL_TYPEOF_CURL_SOCKLEN_T int
+
+/* ===================================== */
+/*    KEEP GENERIC GCC THE LAST ENTRY    */
+/* ===================================== */
+
+#elif defined(__GNUC__) && !defined(_SCO_DS)
+#  if !defined(__LP64__) &&                                             \
+  (defined(__ILP32__) || defined(__i386__) || defined(__hppa__) ||      \
+   defined(__ppc__) || defined(__powerpc__) || defined(__arm__) ||      \
+   defined(__sparc__) || defined(__mips__) || defined(__sh__) ||        \
+   defined(__XTENSA__) ||                                               \
+   (defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 4)  ||               \
+   (defined(__LONG_MAX__) && __LONG_MAX__ == 2147483647L))
+#    define CURL_TYPEOF_CURL_OFF_T     long long
+#    define CURL_FORMAT_CURL_OFF_T     "lld"
+#    define CURL_FORMAT_CURL_OFF_TU    "llu"
+#    define CURL_SUFFIX_CURL_OFF_T     LL
+#    define CURL_SUFFIX_CURL_OFF_TU    ULL
+#  elif defined(__LP64__) || \
+        defined(__x86_64__) || defined(__ppc64__) || defined(__sparc64__) || \
+        (defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 8) || \
+        (defined(__LONG_MAX__) && __LONG_MAX__ == 9223372036854775807L)
+#    define CURL_TYPEOF_CURL_OFF_T     long
+#    define CURL_FORMAT_CURL_OFF_T     "ld"
+#    define CURL_FORMAT_CURL_OFF_TU    "lu"
+#    define CURL_SUFFIX_CURL_OFF_T     L
+#    define CURL_SUFFIX_CURL_OFF_TU    UL
+#  endif
+#  define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
+#  define CURL_PULL_SYS_TYPES_H      1
+#  define CURL_PULL_SYS_SOCKET_H     1
+
+#else
+/* generic "safe guess" on old 32 bit style */
+# define CURL_TYPEOF_CURL_OFF_T     long
+# define CURL_FORMAT_CURL_OFF_T     "ld"
+# define CURL_FORMAT_CURL_OFF_TU    "lu"
+# define CURL_SUFFIX_CURL_OFF_T     L
+# define CURL_SUFFIX_CURL_OFF_TU    UL
+# define CURL_TYPEOF_CURL_SOCKLEN_T int
+#endif
+
+#ifdef _AIX
+/* AIX needs <sys/poll.h> */
+#define CURL_PULL_SYS_POLL_H
+#endif
+
+
+/* CURL_PULL_WS2TCPIP_H is defined above when inclusion of header file  */
+/* ws2tcpip.h is required here to properly make type definitions below. */
+#ifdef CURL_PULL_WS2TCPIP_H
+#  include <winsock2.h>
+#  include <windows.h>
+#  include <ws2tcpip.h>
+#endif
+
+/* CURL_PULL_SYS_TYPES_H is defined above when inclusion of header file  */
+/* sys/types.h is required here to properly make type definitions below. */
+#ifdef CURL_PULL_SYS_TYPES_H
+#  include <sys/types.h>
+#endif
+
+/* CURL_PULL_SYS_SOCKET_H is defined above when inclusion of header file  */
+/* sys/socket.h is required here to properly make type definitions below. */
+#ifdef CURL_PULL_SYS_SOCKET_H
+#  include <sys/socket.h>
+#endif
+
+/* CURL_PULL_SYS_POLL_H is defined above when inclusion of header file    */
+/* sys/poll.h is required here to properly make type definitions below.   */
+#ifdef CURL_PULL_SYS_POLL_H
+#  include <sys/poll.h>
+#endif
+
+/* Data type definition of curl_socklen_t. */
+#ifdef CURL_TYPEOF_CURL_SOCKLEN_T
+  typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t;
+#endif
+
+/* Data type definition of curl_off_t. */
+
+#ifdef CURL_TYPEOF_CURL_OFF_T
+  typedef CURL_TYPEOF_CURL_OFF_T curl_off_t;
+#endif
+
+/*
+ * CURL_ISOCPP and CURL_OFF_T_C definitions are done here in order to allow
+ * these to be visible and exported by the external libcurl interface API,
+ * while also making them visible to the library internals, simply including
+ * curl_setup.h, without actually needing to include curl.h internally.
+ * If some day this section would grow big enough, all this should be moved
+ * to its own header file.
+ */
+
+/*
+ * Figure out if we can use the ## preprocessor operator, which is supported
+ * by ISO/ANSI C and C++. Some compilers support it without setting __STDC__
+ * or  __cplusplus so we need to carefully check for them too.
+ */
+
+#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) || \
+  defined(__HP_aCC) || defined(__BORLANDC__) || defined(__LCC__) || \
+  defined(__POCC__) || defined(__SALFORDC__) || defined(__HIGHC__) || \
+  defined(__ILEC400__)
+  /* This compiler is believed to have an ISO compatible preprocessor */
+#define CURL_ISOCPP
+#else
+  /* This compiler is believed NOT to have an ISO compatible preprocessor */
+#undef CURL_ISOCPP
+#endif
+
+/*
+ * Macros for minimum-width signed and unsigned curl_off_t integer constants.
+ */
+
+#if defined(__BORLANDC__) && (__BORLANDC__ == 0x0551)
+#  define __CURL_OFF_T_C_HLPR2(x) x
+#  define __CURL_OFF_T_C_HLPR1(x) __CURL_OFF_T_C_HLPR2(x)
+#  define CURL_OFF_T_C(Val)  __CURL_OFF_T_C_HLPR1(Val) ## \
+                             __CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_T)
+#  define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \
+                             __CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_TU)
+#else
+#  ifdef CURL_ISOCPP
+#    define __CURL_OFF_T_C_HLPR2(Val,Suffix) Val ## Suffix
+#  else
+#    define __CURL_OFF_T_C_HLPR2(Val,Suffix) Val/**/Suffix
+#  endif
+#  define __CURL_OFF_T_C_HLPR1(Val,Suffix) __CURL_OFF_T_C_HLPR2(Val,Suffix)
+#  define CURL_OFF_T_C(Val)  __CURL_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_T)
+#  define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_TU)
+#endif
+
+#endif /* __CURL_SYSTEM_H */

+ 698 - 0
scbc.tools/Include/curl/typecheck-gcc.h

@@ -0,0 +1,698 @@
+#ifndef __CURL_TYPECHECK_GCC_H
+#define __CURL_TYPECHECK_GCC_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* wraps curl_easy_setopt() with typechecking */
+
+/* To add a new kind of warning, add an
+ *   if(_curl_is_sometype_option(_curl_opt))
+ *     if(!_curl_is_sometype(value))
+ *       _curl_easy_setopt_err_sometype();
+ * block and define _curl_is_sometype_option, _curl_is_sometype and
+ * _curl_easy_setopt_err_sometype below
+ *
+ * NOTE: We use two nested 'if' statements here instead of the && operator, in
+ *       order to work around gcc bug #32061.  It affects only gcc 4.3.x/4.4.x
+ *       when compiling with -Wlogical-op.
+ *
+ * To add an option that uses the same type as an existing option, you'll just
+ * need to extend the appropriate _curl_*_option macro
+ */
+#define curl_easy_setopt(handle, option, value)                               \
+__extension__ ({                                                              \
+  __typeof__(option) _curl_opt = option;                                     \
+  if(__builtin_constant_p(_curl_opt)) {                                       \
+    if(_curl_is_long_option(_curl_opt))                                       \
+      if(!_curl_is_long(value))                                               \
+        _curl_easy_setopt_err_long();                                         \
+    if(_curl_is_off_t_option(_curl_opt))                                      \
+      if(!_curl_is_off_t(value))                                              \
+        _curl_easy_setopt_err_curl_off_t();                                   \
+    if(_curl_is_string_option(_curl_opt))                                     \
+      if(!_curl_is_string(value))                                             \
+        _curl_easy_setopt_err_string();                                       \
+    if(_curl_is_write_cb_option(_curl_opt))                                   \
+      if(!_curl_is_write_cb(value))                                           \
+        _curl_easy_setopt_err_write_callback();                               \
+    if((_curl_opt) == CURLOPT_RESOLVER_START_FUNCTION)                        \
+      if(!_curl_is_resolver_start_callback(value))                            \
+        _curl_easy_setopt_err_resolver_start_callback();                      \
+    if((_curl_opt) == CURLOPT_READFUNCTION)                                   \
+      if(!_curl_is_read_cb(value))                                            \
+        _curl_easy_setopt_err_read_cb();                                      \
+    if((_curl_opt) == CURLOPT_IOCTLFUNCTION)                                  \
+      if(!_curl_is_ioctl_cb(value))                                           \
+        _curl_easy_setopt_err_ioctl_cb();                                     \
+    if((_curl_opt) == CURLOPT_SOCKOPTFUNCTION)                                \
+      if(!_curl_is_sockopt_cb(value))                                         \
+        _curl_easy_setopt_err_sockopt_cb();                                   \
+    if((_curl_opt) == CURLOPT_OPENSOCKETFUNCTION)                             \
+      if(!_curl_is_opensocket_cb(value))                                      \
+        _curl_easy_setopt_err_opensocket_cb();                                \
+    if((_curl_opt) == CURLOPT_PROGRESSFUNCTION)                               \
+      if(!_curl_is_progress_cb(value))                                        \
+        _curl_easy_setopt_err_progress_cb();                                  \
+    if((_curl_opt) == CURLOPT_DEBUGFUNCTION)                                  \
+      if(!_curl_is_debug_cb(value))                                           \
+        _curl_easy_setopt_err_debug_cb();                                     \
+    if((_curl_opt) == CURLOPT_SSL_CTX_FUNCTION)                               \
+      if(!_curl_is_ssl_ctx_cb(value))                                         \
+        _curl_easy_setopt_err_ssl_ctx_cb();                                   \
+    if(_curl_is_conv_cb_option(_curl_opt))                                    \
+      if(!_curl_is_conv_cb(value))                                            \
+        _curl_easy_setopt_err_conv_cb();                                      \
+    if((_curl_opt) == CURLOPT_SEEKFUNCTION)                                   \
+      if(!_curl_is_seek_cb(value))                                            \
+        _curl_easy_setopt_err_seek_cb();                                      \
+    if(_curl_is_cb_data_option(_curl_opt))                                    \
+      if(!_curl_is_cb_data(value))                                            \
+        _curl_easy_setopt_err_cb_data();                                      \
+    if((_curl_opt) == CURLOPT_ERRORBUFFER)                                    \
+      if(!_curl_is_error_buffer(value))                                       \
+        _curl_easy_setopt_err_error_buffer();                                 \
+    if((_curl_opt) == CURLOPT_STDERR)                                         \
+      if(!_curl_is_FILE(value))                                               \
+        _curl_easy_setopt_err_FILE();                                         \
+    if(_curl_is_postfields_option(_curl_opt))                                 \
+      if(!_curl_is_postfields(value))                                         \
+        _curl_easy_setopt_err_postfields();                                   \
+    if((_curl_opt) == CURLOPT_HTTPPOST)                                       \
+      if(!_curl_is_arr((value), struct curl_httppost))                        \
+        _curl_easy_setopt_err_curl_httpost();                                 \
+    if((_curl_opt) == CURLOPT_MIMEPOST)                                       \
+      if(!_curl_is_ptr((value), curl_mime))                                   \
+        _curl_easy_setopt_err_curl_mimepost();                                \
+    if(_curl_is_slist_option(_curl_opt))                                      \
+      if(!_curl_is_arr((value), struct curl_slist))                           \
+        _curl_easy_setopt_err_curl_slist();                                   \
+    if((_curl_opt) == CURLOPT_SHARE)                                          \
+      if(!_curl_is_ptr((value), CURLSH))                                      \
+        _curl_easy_setopt_err_CURLSH();                                       \
+  }                                                                           \
+  curl_easy_setopt(handle, _curl_opt, value);                                 \
+})
+
+/* wraps curl_easy_getinfo() with typechecking */
+#define curl_easy_getinfo(handle, info, arg)                                  \
+__extension__ ({                                                              \
+  __typeof__(info) _curl_info = info;                                         \
+  if(__builtin_constant_p(_curl_info)) {                                      \
+    if(_curl_is_string_info(_curl_info))                                      \
+      if(!_curl_is_arr((arg), char *))                                        \
+        _curl_easy_getinfo_err_string();                                      \
+    if(_curl_is_long_info(_curl_info))                                        \
+      if(!_curl_is_arr((arg), long))                                          \
+        _curl_easy_getinfo_err_long();                                        \
+    if(_curl_is_double_info(_curl_info))                                      \
+      if(!_curl_is_arr((arg), double))                                        \
+        _curl_easy_getinfo_err_double();                                      \
+    if(_curl_is_slist_info(_curl_info))                                       \
+      if(!_curl_is_arr((arg), struct curl_slist *))                           \
+        _curl_easy_getinfo_err_curl_slist();                                  \
+    if(_curl_is_tlssessioninfo_info(_curl_info))                              \
+      if(!_curl_is_arr((arg), struct curl_tlssessioninfo *))                  \
+        _curl_easy_getinfo_err_curl_tlssesssioninfo();                        \
+    if(_curl_is_certinfo_info(_curl_info))                                    \
+      if(!_curl_is_arr((arg), struct curl_certinfo *))                        \
+        _curl_easy_getinfo_err_curl_certinfo();                               \
+    if(_curl_is_socket_info(_curl_info))                                      \
+      if(!_curl_is_arr((arg), curl_socket_t))                                 \
+        _curl_easy_getinfo_err_curl_socket();                                 \
+    if(_curl_is_off_t_info(_curl_info))                                       \
+      if(!_curl_is_arr((arg), curl_off_t))                                    \
+        _curl_easy_getinfo_err_curl_off_t();                                  \
+  }                                                                           \
+  curl_easy_getinfo(handle, _curl_info, arg);                                 \
+})
+
+/*
+ * For now, just make sure that the functions are called with three arguments
+ */
+#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param)
+#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param)
+
+
+/* the actual warnings, triggered by calling the _curl_easy_setopt_err*
+ * functions */
+
+/* To define a new warning, use _CURL_WARNING(identifier, "message") */
+#define _CURL_WARNING(id, message)                                            \
+  static void __attribute__((__warning__(message)))                           \
+  __attribute__((__unused__)) __attribute__((__noinline__))                   \
+  id(void) { __asm__(""); }
+
+_CURL_WARNING(_curl_easy_setopt_err_long,
+  "curl_easy_setopt expects a long argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_curl_off_t,
+  "curl_easy_setopt expects a curl_off_t argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_string,
+              "curl_easy_setopt expects a "
+              "string ('char *' or char[]) argument for this option"
+  )
+_CURL_WARNING(_curl_easy_setopt_err_write_callback,
+  "curl_easy_setopt expects a curl_write_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_resolver_start_callback,
+              "curl_easy_setopt expects a "
+              "curl_resolver_start_callback argument for this option"
+  )
+_CURL_WARNING(_curl_easy_setopt_err_read_cb,
+  "curl_easy_setopt expects a curl_read_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_ioctl_cb,
+  "curl_easy_setopt expects a curl_ioctl_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_sockopt_cb,
+  "curl_easy_setopt expects a curl_sockopt_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_opensocket_cb,
+              "curl_easy_setopt expects a "
+              "curl_opensocket_callback argument for this option"
+  )
+_CURL_WARNING(_curl_easy_setopt_err_progress_cb,
+  "curl_easy_setopt expects a curl_progress_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_debug_cb,
+  "curl_easy_setopt expects a curl_debug_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_ssl_ctx_cb,
+  "curl_easy_setopt expects a curl_ssl_ctx_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_conv_cb,
+  "curl_easy_setopt expects a curl_conv_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_seek_cb,
+  "curl_easy_setopt expects a curl_seek_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_cb_data,
+              "curl_easy_setopt expects a "
+              "private data pointer as argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_error_buffer,
+              "curl_easy_setopt expects a "
+              "char buffer of CURL_ERROR_SIZE as argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_FILE,
+  "curl_easy_setopt expects a 'FILE *' argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_postfields,
+  "curl_easy_setopt expects a 'void *' or 'char *' argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_curl_httpost,
+              "curl_easy_setopt expects a 'struct curl_httppost *' "
+              "argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_curl_mimepost,
+              "curl_easy_setopt expects a 'curl_mime *' "
+              "argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_curl_slist,
+  "curl_easy_setopt expects a 'struct curl_slist *' argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_CURLSH,
+  "curl_easy_setopt expects a CURLSH* argument for this option")
+
+_CURL_WARNING(_curl_easy_getinfo_err_string,
+  "curl_easy_getinfo expects a pointer to 'char *' for this info")
+_CURL_WARNING(_curl_easy_getinfo_err_long,
+  "curl_easy_getinfo expects a pointer to long for this info")
+_CURL_WARNING(_curl_easy_getinfo_err_double,
+  "curl_easy_getinfo expects a pointer to double for this info")
+_CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
+  "curl_easy_getinfo expects a pointer to 'struct curl_slist *' for this info")
+_CURL_WARNING(_curl_easy_getinfo_err_curl_tlssesssioninfo,
+              "curl_easy_getinfo expects a pointer to "
+              "'struct curl_tlssessioninfo *' for this info")
+_CURL_WARNING(_curl_easy_getinfo_err_curl_certinfo,
+              "curl_easy_getinfo expects a pointer to "
+              "'struct curl_certinfo *' for this info")
+_CURL_WARNING(_curl_easy_getinfo_err_curl_socket,
+  "curl_easy_getinfo expects a pointer to curl_socket_t for this info")
+_CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
+  "curl_easy_getinfo expects a pointer to curl_off_t for this info")
+
+/* groups of curl_easy_setops options that take the same type of argument */
+
+/* To add a new option to one of the groups, just add
+ *   (option) == CURLOPT_SOMETHING
+ * to the or-expression. If the option takes a long or curl_off_t, you don't
+ * have to do anything
+ */
+
+/* evaluates to true if option takes a long argument */
+#define _curl_is_long_option(option)                                          \
+  (0 < (option) && (option) < CURLOPTTYPE_OBJECTPOINT)
+
+#define _curl_is_off_t_option(option)                                         \
+  ((option) > CURLOPTTYPE_OFF_T)
+
+/* evaluates to true if option takes a char* argument */
+#define _curl_is_string_option(option)                                        \
+  ((option) == CURLOPT_ABSTRACT_UNIX_SOCKET ||                                \
+   (option) == CURLOPT_ACCEPT_ENCODING ||                                     \
+   (option) == CURLOPT_ALTSVC ||                                              \
+   (option) == CURLOPT_CAINFO ||                                              \
+   (option) == CURLOPT_CAPATH ||                                              \
+   (option) == CURLOPT_COOKIE ||                                              \
+   (option) == CURLOPT_COOKIEFILE ||                                          \
+   (option) == CURLOPT_COOKIEJAR ||                                           \
+   (option) == CURLOPT_COOKIELIST ||                                          \
+   (option) == CURLOPT_CRLFILE ||                                             \
+   (option) == CURLOPT_CUSTOMREQUEST ||                                       \
+   (option) == CURLOPT_DEFAULT_PROTOCOL ||                                    \
+   (option) == CURLOPT_DNS_INTERFACE ||                                       \
+   (option) == CURLOPT_DNS_LOCAL_IP4 ||                                       \
+   (option) == CURLOPT_DNS_LOCAL_IP6 ||                                       \
+   (option) == CURLOPT_DNS_SERVERS ||                                         \
+   (option) == CURLOPT_DOH_URL ||                                             \
+   (option) == CURLOPT_EGDSOCKET ||                                           \
+   (option) == CURLOPT_FTPPORT ||                                             \
+   (option) == CURLOPT_FTP_ACCOUNT ||                                         \
+   (option) == CURLOPT_FTP_ALTERNATIVE_TO_USER ||                             \
+   (option) == CURLOPT_INTERFACE ||                                           \
+   (option) == CURLOPT_ISSUERCERT ||                                          \
+   (option) == CURLOPT_KEYPASSWD ||                                           \
+   (option) == CURLOPT_KRBLEVEL ||                                            \
+   (option) == CURLOPT_LOGIN_OPTIONS ||                                       \
+   (option) == CURLOPT_MAIL_AUTH ||                                           \
+   (option) == CURLOPT_MAIL_FROM ||                                           \
+   (option) == CURLOPT_NETRC_FILE ||                                          \
+   (option) == CURLOPT_NOPROXY ||                                             \
+   (option) == CURLOPT_PASSWORD ||                                            \
+   (option) == CURLOPT_PINNEDPUBLICKEY ||                                     \
+   (option) == CURLOPT_PRE_PROXY ||                                           \
+   (option) == CURLOPT_PROXY ||                                               \
+   (option) == CURLOPT_PROXYPASSWORD ||                                       \
+   (option) == CURLOPT_PROXYUSERNAME ||                                       \
+   (option) == CURLOPT_PROXYUSERPWD ||                                        \
+   (option) == CURLOPT_PROXY_CAINFO ||                                        \
+   (option) == CURLOPT_PROXY_CAPATH ||                                        \
+   (option) == CURLOPT_PROXY_CRLFILE ||                                       \
+   (option) == CURLOPT_PROXY_KEYPASSWD ||                                     \
+   (option) == CURLOPT_PROXY_PINNEDPUBLICKEY ||                               \
+   (option) == CURLOPT_PROXY_SERVICE_NAME ||                                  \
+   (option) == CURLOPT_PROXY_SSLCERT ||                                       \
+   (option) == CURLOPT_PROXY_SSLCERTTYPE ||                                   \
+   (option) == CURLOPT_PROXY_SSLKEY ||                                        \
+   (option) == CURLOPT_PROXY_SSLKEYTYPE ||                                    \
+   (option) == CURLOPT_PROXY_SSL_CIPHER_LIST ||                               \
+   (option) == CURLOPT_PROXY_TLS13_CIPHERS ||                                 \
+   (option) == CURLOPT_PROXY_TLSAUTH_PASSWORD ||                              \
+   (option) == CURLOPT_PROXY_TLSAUTH_TYPE ||                                  \
+   (option) == CURLOPT_PROXY_TLSAUTH_USERNAME ||                              \
+   (option) == CURLOPT_RANDOM_FILE ||                                         \
+   (option) == CURLOPT_RANGE ||                                               \
+   (option) == CURLOPT_REFERER ||                                             \
+   (option) == CURLOPT_REQUEST_TARGET ||                                      \
+   (option) == CURLOPT_RTSP_SESSION_ID ||                                     \
+   (option) == CURLOPT_RTSP_STREAM_URI ||                                     \
+   (option) == CURLOPT_RTSP_TRANSPORT ||                                      \
+   (option) == CURLOPT_SERVICE_NAME ||                                        \
+   (option) == CURLOPT_SOCKS5_GSSAPI_SERVICE ||                               \
+   (option) == CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 ||                             \
+   (option) == CURLOPT_SSH_KNOWNHOSTS ||                                      \
+   (option) == CURLOPT_SSH_PRIVATE_KEYFILE ||                                 \
+   (option) == CURLOPT_SSH_PUBLIC_KEYFILE ||                                  \
+   (option) == CURLOPT_SSLCERT ||                                             \
+   (option) == CURLOPT_SSLCERTTYPE ||                                         \
+   (option) == CURLOPT_SSLENGINE ||                                           \
+   (option) == CURLOPT_SSLKEY ||                                              \
+   (option) == CURLOPT_SSLKEYTYPE ||                                          \
+   (option) == CURLOPT_SSL_CIPHER_LIST ||                                     \
+   (option) == CURLOPT_TLS13_CIPHERS ||                                       \
+   (option) == CURLOPT_TLSAUTH_PASSWORD ||                                    \
+   (option) == CURLOPT_TLSAUTH_TYPE ||                                        \
+   (option) == CURLOPT_TLSAUTH_USERNAME ||                                    \
+   (option) == CURLOPT_UNIX_SOCKET_PATH ||                                    \
+   (option) == CURLOPT_URL ||                                                 \
+   (option) == CURLOPT_USERAGENT ||                                           \
+   (option) == CURLOPT_USERNAME ||                                            \
+   (option) == CURLOPT_USERPWD ||                                             \
+   (option) == CURLOPT_XOAUTH2_BEARER ||                                      \
+   0)
+
+/* evaluates to true if option takes a curl_write_callback argument */
+#define _curl_is_write_cb_option(option)                                      \
+  ((option) == CURLOPT_HEADERFUNCTION ||                                      \
+   (option) == CURLOPT_WRITEFUNCTION)
+
+/* evaluates to true if option takes a curl_conv_callback argument */
+#define _curl_is_conv_cb_option(option)                                       \
+  ((option) == CURLOPT_CONV_TO_NETWORK_FUNCTION ||                            \
+   (option) == CURLOPT_CONV_FROM_NETWORK_FUNCTION ||                          \
+   (option) == CURLOPT_CONV_FROM_UTF8_FUNCTION)
+
+/* evaluates to true if option takes a data argument to pass to a callback */
+#define _curl_is_cb_data_option(option)                                       \
+  ((option) == CURLOPT_CHUNK_DATA ||                                          \
+   (option) == CURLOPT_CLOSESOCKETDATA ||                                     \
+   (option) == CURLOPT_DEBUGDATA ||                                           \
+   (option) == CURLOPT_FNMATCH_DATA ||                                        \
+   (option) == CURLOPT_HEADERDATA ||                                          \
+   (option) == CURLOPT_INTERLEAVEDATA ||                                      \
+   (option) == CURLOPT_IOCTLDATA ||                                           \
+   (option) == CURLOPT_OPENSOCKETDATA ||                                      \
+   (option) == CURLOPT_PRIVATE ||                                             \
+   (option) == CURLOPT_PROGRESSDATA ||                                        \
+   (option) == CURLOPT_READDATA ||                                            \
+   (option) == CURLOPT_SEEKDATA ||                                            \
+   (option) == CURLOPT_SOCKOPTDATA ||                                         \
+   (option) == CURLOPT_SSH_KEYDATA ||                                         \
+   (option) == CURLOPT_SSL_CTX_DATA ||                                        \
+   (option) == CURLOPT_WRITEDATA ||                                           \
+   (option) == CURLOPT_RESOLVER_START_DATA ||                                 \
+   (option) == CURLOPT_TRAILERDATA ||                                         \
+   0)
+
+/* evaluates to true if option takes a POST data argument (void* or char*) */
+#define _curl_is_postfields_option(option)                                    \
+  ((option) == CURLOPT_POSTFIELDS ||                                          \
+   (option) == CURLOPT_COPYPOSTFIELDS ||                                      \
+   0)
+
+/* evaluates to true if option takes a struct curl_slist * argument */
+#define _curl_is_slist_option(option)                                         \
+  ((option) == CURLOPT_HTTP200ALIASES ||                                      \
+   (option) == CURLOPT_HTTPHEADER ||                                          \
+   (option) == CURLOPT_MAIL_RCPT ||                                           \
+   (option) == CURLOPT_POSTQUOTE ||                                           \
+   (option) == CURLOPT_PREQUOTE ||                                            \
+   (option) == CURLOPT_PROXYHEADER ||                                         \
+   (option) == CURLOPT_QUOTE ||                                               \
+   (option) == CURLOPT_RESOLVE ||                                             \
+   (option) == CURLOPT_TELNETOPTIONS ||                                       \
+   (option) == CURLOPT_CONNECT_TO ||                                          \
+   0)
+
+/* groups of curl_easy_getinfo infos that take the same type of argument */
+
+/* evaluates to true if info expects a pointer to char * argument */
+#define _curl_is_string_info(info)                                            \
+  (CURLINFO_STRING < (info) && (info) < CURLINFO_LONG)
+
+/* evaluates to true if info expects a pointer to long argument */
+#define _curl_is_long_info(info)                                              \
+  (CURLINFO_LONG < (info) && (info) < CURLINFO_DOUBLE)
+
+/* evaluates to true if info expects a pointer to double argument */
+#define _curl_is_double_info(info)                                            \
+  (CURLINFO_DOUBLE < (info) && (info) < CURLINFO_SLIST)
+
+/* true if info expects a pointer to struct curl_slist * argument */
+#define _curl_is_slist_info(info)                                       \
+  (((info) == CURLINFO_SSL_ENGINES) || ((info) == CURLINFO_COOKIELIST))
+
+/* true if info expects a pointer to struct curl_tlssessioninfo * argument */
+#define _curl_is_tlssessioninfo_info(info)                              \
+  (((info) == CURLINFO_TLS_SSL_PTR) || ((info) == CURLINFO_TLS_SESSION))
+
+/* true if info expects a pointer to struct curl_certinfo * argument */
+#define _curl_is_certinfo_info(info) ((info) == CURLINFO_CERTINFO)
+
+/* true if info expects a pointer to struct curl_socket_t argument */
+#define _curl_is_socket_info(info)                                            \
+  (CURLINFO_SOCKET < (info) && (info) < CURLINFO_OFF_T)
+
+/* true if info expects a pointer to curl_off_t argument */
+#define _curl_is_off_t_info(info)                                             \
+  (CURLINFO_OFF_T < (info))
+
+
+/* typecheck helpers -- check whether given expression has requested type*/
+
+/* For pointers, you can use the _curl_is_ptr/_curl_is_arr macros,
+ * otherwise define a new macro. Search for __builtin_types_compatible_p
+ * in the GCC manual.
+ * NOTE: these macros MUST NOT EVALUATE their arguments! The argument is
+ * the actual expression passed to the curl_easy_setopt macro. This
+ * means that you can only apply the sizeof and __typeof__ operators, no
+ * == or whatsoever.
+ */
+
+/* XXX: should evaluate to true if expr is a pointer */
+#define _curl_is_any_ptr(expr)                                                \
+  (sizeof(expr) == sizeof(void *))
+
+/* evaluates to true if expr is NULL */
+/* XXX: must not evaluate expr, so this check is not accurate */
+#define _curl_is_NULL(expr)                                                   \
+  (__builtin_types_compatible_p(__typeof__(expr), __typeof__(NULL)))
+
+/* evaluates to true if expr is type*, const type* or NULL */
+#define _curl_is_ptr(expr, type)                                              \
+  (_curl_is_NULL(expr) ||                                                     \
+   __builtin_types_compatible_p(__typeof__(expr), type *) ||                  \
+   __builtin_types_compatible_p(__typeof__(expr), const type *))
+
+/* evaluates to true if expr is one of type[], type*, NULL or const type* */
+#define _curl_is_arr(expr, type)                                              \
+  (_curl_is_ptr((expr), type) ||                                              \
+   __builtin_types_compatible_p(__typeof__(expr), type []))
+
+/* evaluates to true if expr is a string */
+#define _curl_is_string(expr)                                                 \
+  (_curl_is_arr((expr), char) ||                                              \
+   _curl_is_arr((expr), signed char) ||                                       \
+   _curl_is_arr((expr), unsigned char))
+
+/* evaluates to true if expr is a long (no matter the signedness)
+ * XXX: for now, int is also accepted (and therefore short and char, which
+ * are promoted to int when passed to a variadic function) */
+#define _curl_is_long(expr)                                                   \
+  (__builtin_types_compatible_p(__typeof__(expr), long) ||                    \
+   __builtin_types_compatible_p(__typeof__(expr), signed long) ||             \
+   __builtin_types_compatible_p(__typeof__(expr), unsigned long) ||           \
+   __builtin_types_compatible_p(__typeof__(expr), int) ||                     \
+   __builtin_types_compatible_p(__typeof__(expr), signed int) ||              \
+   __builtin_types_compatible_p(__typeof__(expr), unsigned int) ||            \
+   __builtin_types_compatible_p(__typeof__(expr), short) ||                   \
+   __builtin_types_compatible_p(__typeof__(expr), signed short) ||            \
+   __builtin_types_compatible_p(__typeof__(expr), unsigned short) ||          \
+   __builtin_types_compatible_p(__typeof__(expr), char) ||                    \
+   __builtin_types_compatible_p(__typeof__(expr), signed char) ||             \
+   __builtin_types_compatible_p(__typeof__(expr), unsigned char))
+
+/* evaluates to true if expr is of type curl_off_t */
+#define _curl_is_off_t(expr)                                                  \
+  (__builtin_types_compatible_p(__typeof__(expr), curl_off_t))
+
+/* evaluates to true if expr is abuffer suitable for CURLOPT_ERRORBUFFER */
+/* XXX: also check size of an char[] array? */
+#define _curl_is_error_buffer(expr)                                           \
+  (_curl_is_NULL(expr) ||                                                     \
+   __builtin_types_compatible_p(__typeof__(expr), char *) ||                  \
+   __builtin_types_compatible_p(__typeof__(expr), char[]))
+
+/* evaluates to true if expr is of type (const) void* or (const) FILE* */
+#if 0
+#define _curl_is_cb_data(expr)                                                \
+  (_curl_is_ptr((expr), void) ||                                              \
+   _curl_is_ptr((expr), FILE))
+#else /* be less strict */
+#define _curl_is_cb_data(expr)                                                \
+  _curl_is_any_ptr(expr)
+#endif
+
+/* evaluates to true if expr is of type FILE* */
+#define _curl_is_FILE(expr)                                             \
+  (_curl_is_NULL(expr) ||                                              \
+   (__builtin_types_compatible_p(__typeof__(expr), FILE *)))
+
+/* evaluates to true if expr can be passed as POST data (void* or char*) */
+#define _curl_is_postfields(expr)                                             \
+  (_curl_is_ptr((expr), void) ||                                              \
+   _curl_is_arr((expr), char) ||                                              \
+   _curl_is_arr((expr), unsigned char))
+
+/* helper: __builtin_types_compatible_p distinguishes between functions and
+ * function pointers, hide it */
+#define _curl_callback_compatible(func, type)                                 \
+  (__builtin_types_compatible_p(__typeof__(func), type) ||                    \
+   __builtin_types_compatible_p(__typeof__(func) *, type))
+
+/* evaluates to true if expr is of type curl_resolver_start_callback */
+#define _curl_is_resolver_start_callback(expr)       \
+  (_curl_is_NULL(expr) || \
+   _curl_callback_compatible((expr), curl_resolver_start_callback))
+
+/* evaluates to true if expr is of type curl_read_callback or "similar" */
+#define _curl_is_read_cb(expr)                                          \
+  (_curl_is_NULL(expr) ||                                                     \
+   _curl_callback_compatible((expr), __typeof__(fread) *) ||                  \
+   _curl_callback_compatible((expr), curl_read_callback) ||                   \
+   _curl_callback_compatible((expr), _curl_read_callback1) ||                 \
+   _curl_callback_compatible((expr), _curl_read_callback2) ||                 \
+   _curl_callback_compatible((expr), _curl_read_callback3) ||                 \
+   _curl_callback_compatible((expr), _curl_read_callback4) ||                 \
+   _curl_callback_compatible((expr), _curl_read_callback5) ||                 \
+   _curl_callback_compatible((expr), _curl_read_callback6))
+typedef size_t (*_curl_read_callback1)(char *, size_t, size_t, void *);
+typedef size_t (*_curl_read_callback2)(char *, size_t, size_t, const void *);
+typedef size_t (*_curl_read_callback3)(char *, size_t, size_t, FILE *);
+typedef size_t (*_curl_read_callback4)(void *, size_t, size_t, void *);
+typedef size_t (*_curl_read_callback5)(void *, size_t, size_t, const void *);
+typedef size_t (*_curl_read_callback6)(void *, size_t, size_t, FILE *);
+
+/* evaluates to true if expr is of type curl_write_callback or "similar" */
+#define _curl_is_write_cb(expr)                                               \
+  (_curl_is_read_cb(expr) ||                                            \
+   _curl_callback_compatible((expr), __typeof__(fwrite) *) ||                 \
+   _curl_callback_compatible((expr), curl_write_callback) ||                  \
+   _curl_callback_compatible((expr), _curl_write_callback1) ||                \
+   _curl_callback_compatible((expr), _curl_write_callback2) ||                \
+   _curl_callback_compatible((expr), _curl_write_callback3) ||                \
+   _curl_callback_compatible((expr), _curl_write_callback4) ||                \
+   _curl_callback_compatible((expr), _curl_write_callback5) ||                \
+   _curl_callback_compatible((expr), _curl_write_callback6))
+typedef size_t (*_curl_write_callback1)(const char *, size_t, size_t, void *);
+typedef size_t (*_curl_write_callback2)(const char *, size_t, size_t,
+                                       const void *);
+typedef size_t (*_curl_write_callback3)(const char *, size_t, size_t, FILE *);
+typedef size_t (*_curl_write_callback4)(const void *, size_t, size_t, void *);
+typedef size_t (*_curl_write_callback5)(const void *, size_t, size_t,
+                                       const void *);
+typedef size_t (*_curl_write_callback6)(const void *, size_t, size_t, FILE *);
+
+/* evaluates to true if expr is of type curl_ioctl_callback or "similar" */
+#define _curl_is_ioctl_cb(expr)                                         \
+  (_curl_is_NULL(expr) ||                                                     \
+   _curl_callback_compatible((expr), curl_ioctl_callback) ||                  \
+   _curl_callback_compatible((expr), _curl_ioctl_callback1) ||                \
+   _curl_callback_compatible((expr), _curl_ioctl_callback2) ||                \
+   _curl_callback_compatible((expr), _curl_ioctl_callback3) ||                \
+   _curl_callback_compatible((expr), _curl_ioctl_callback4))
+typedef curlioerr (*_curl_ioctl_callback1)(CURL *, int, void *);
+typedef curlioerr (*_curl_ioctl_callback2)(CURL *, int, const void *);
+typedef curlioerr (*_curl_ioctl_callback3)(CURL *, curliocmd, void *);
+typedef curlioerr (*_curl_ioctl_callback4)(CURL *, curliocmd, const void *);
+
+/* evaluates to true if expr is of type curl_sockopt_callback or "similar" */
+#define _curl_is_sockopt_cb(expr)                                       \
+  (_curl_is_NULL(expr) ||                                                     \
+   _curl_callback_compatible((expr), curl_sockopt_callback) ||                \
+   _curl_callback_compatible((expr), _curl_sockopt_callback1) ||              \
+   _curl_callback_compatible((expr), _curl_sockopt_callback2))
+typedef int (*_curl_sockopt_callback1)(void *, curl_socket_t, curlsocktype);
+typedef int (*_curl_sockopt_callback2)(const void *, curl_socket_t,
+                                      curlsocktype);
+
+/* evaluates to true if expr is of type curl_opensocket_callback or
+   "similar" */
+#define _curl_is_opensocket_cb(expr)                                    \
+  (_curl_is_NULL(expr) ||                                                     \
+   _curl_callback_compatible((expr), curl_opensocket_callback) ||             \
+   _curl_callback_compatible((expr), _curl_opensocket_callback1) ||           \
+   _curl_callback_compatible((expr), _curl_opensocket_callback2) ||           \
+   _curl_callback_compatible((expr), _curl_opensocket_callback3) ||           \
+   _curl_callback_compatible((expr), _curl_opensocket_callback4))
+typedef curl_socket_t (*_curl_opensocket_callback1)
+  (void *, curlsocktype, struct curl_sockaddr *);
+typedef curl_socket_t (*_curl_opensocket_callback2)
+  (void *, curlsocktype, const struct curl_sockaddr *);
+typedef curl_socket_t (*_curl_opensocket_callback3)
+  (const void *, curlsocktype, struct curl_sockaddr *);
+typedef curl_socket_t (*_curl_opensocket_callback4)
+  (const void *, curlsocktype, const struct curl_sockaddr *);
+
+/* evaluates to true if expr is of type curl_progress_callback or "similar" */
+#define _curl_is_progress_cb(expr)                                      \
+  (_curl_is_NULL(expr) ||                                                     \
+   _curl_callback_compatible((expr), curl_progress_callback) ||               \
+   _curl_callback_compatible((expr), _curl_progress_callback1) ||             \
+   _curl_callback_compatible((expr), _curl_progress_callback2))
+typedef int (*_curl_progress_callback1)(void *,
+    double, double, double, double);
+typedef int (*_curl_progress_callback2)(const void *,
+    double, double, double, double);
+
+/* evaluates to true if expr is of type curl_debug_callback or "similar" */
+#define _curl_is_debug_cb(expr)                                         \
+  (_curl_is_NULL(expr) ||                                                     \
+   _curl_callback_compatible((expr), curl_debug_callback) ||                  \
+   _curl_callback_compatible((expr), _curl_debug_callback1) ||                \
+   _curl_callback_compatible((expr), _curl_debug_callback2) ||                \
+   _curl_callback_compatible((expr), _curl_debug_callback3) ||                \
+   _curl_callback_compatible((expr), _curl_debug_callback4) ||                \
+   _curl_callback_compatible((expr), _curl_debug_callback5) ||                \
+   _curl_callback_compatible((expr), _curl_debug_callback6) ||                \
+   _curl_callback_compatible((expr), _curl_debug_callback7) ||                \
+   _curl_callback_compatible((expr), _curl_debug_callback8))
+typedef int (*_curl_debug_callback1) (CURL *,
+    curl_infotype, char *, size_t, void *);
+typedef int (*_curl_debug_callback2) (CURL *,
+    curl_infotype, char *, size_t, const void *);
+typedef int (*_curl_debug_callback3) (CURL *,
+    curl_infotype, const char *, size_t, void *);
+typedef int (*_curl_debug_callback4) (CURL *,
+    curl_infotype, const char *, size_t, const void *);
+typedef int (*_curl_debug_callback5) (CURL *,
+    curl_infotype, unsigned char *, size_t, void *);
+typedef int (*_curl_debug_callback6) (CURL *,
+    curl_infotype, unsigned char *, size_t, const void *);
+typedef int (*_curl_debug_callback7) (CURL *,
+    curl_infotype, const unsigned char *, size_t, void *);
+typedef int (*_curl_debug_callback8) (CURL *,
+    curl_infotype, const unsigned char *, size_t, const void *);
+
+/* evaluates to true if expr is of type curl_ssl_ctx_callback or "similar" */
+/* this is getting even messier... */
+#define _curl_is_ssl_ctx_cb(expr)                                       \
+  (_curl_is_NULL(expr) ||                                                     \
+   _curl_callback_compatible((expr), curl_ssl_ctx_callback) ||                \
+   _curl_callback_compatible((expr), _curl_ssl_ctx_callback1) ||              \
+   _curl_callback_compatible((expr), _curl_ssl_ctx_callback2) ||              \
+   _curl_callback_compatible((expr), _curl_ssl_ctx_callback3) ||              \
+   _curl_callback_compatible((expr), _curl_ssl_ctx_callback4) ||              \
+   _curl_callback_compatible((expr), _curl_ssl_ctx_callback5) ||              \
+   _curl_callback_compatible((expr), _curl_ssl_ctx_callback6) ||              \
+   _curl_callback_compatible((expr), _curl_ssl_ctx_callback7) ||              \
+   _curl_callback_compatible((expr), _curl_ssl_ctx_callback8))
+typedef CURLcode (*_curl_ssl_ctx_callback1)(CURL *, void *, void *);
+typedef CURLcode (*_curl_ssl_ctx_callback2)(CURL *, void *, const void *);
+typedef CURLcode (*_curl_ssl_ctx_callback3)(CURL *, const void *, void *);
+typedef CURLcode (*_curl_ssl_ctx_callback4)(CURL *, const void *,
+                                            const void *);
+#ifdef HEADER_SSL_H
+/* hack: if we included OpenSSL's ssl.h, we know about SSL_CTX
+ * this will of course break if we're included before OpenSSL headers...
+ */
+typedef CURLcode (*_curl_ssl_ctx_callback5)(CURL *, SSL_CTX, void *);
+typedef CURLcode (*_curl_ssl_ctx_callback6)(CURL *, SSL_CTX, const void *);
+typedef CURLcode (*_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX, void *);
+typedef CURLcode (*_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX,
+                                           const void *);
+#else
+typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback5;
+typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback6;
+typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback7;
+typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback8;
+#endif
+
+/* evaluates to true if expr is of type curl_conv_callback or "similar" */
+#define _curl_is_conv_cb(expr)                                          \
+  (_curl_is_NULL(expr) ||                                                     \
+   _curl_callback_compatible((expr), curl_conv_callback) ||                   \
+   _curl_callback_compatible((expr), _curl_conv_callback1) ||                 \
+   _curl_callback_compatible((expr), _curl_conv_callback2) ||                 \
+   _curl_callback_compatible((expr), _curl_conv_callback3) ||                 \
+   _curl_callback_compatible((expr), _curl_conv_callback4))
+typedef CURLcode (*_curl_conv_callback1)(char *, size_t length);
+typedef CURLcode (*_curl_conv_callback2)(const char *, size_t length);
+typedef CURLcode (*_curl_conv_callback3)(void *, size_t length);
+typedef CURLcode (*_curl_conv_callback4)(const void *, size_t length);
+
+/* evaluates to true if expr is of type curl_seek_callback or "similar" */
+#define _curl_is_seek_cb(expr)                                          \
+  (_curl_is_NULL(expr) ||                                                     \
+   _curl_callback_compatible((expr), curl_seek_callback) ||                   \
+   _curl_callback_compatible((expr), _curl_seek_callback1) ||                 \
+   _curl_callback_compatible((expr), _curl_seek_callback2))
+typedef CURLcode (*_curl_seek_callback1)(void *, curl_off_t, int);
+typedef CURLcode (*_curl_seek_callback2)(const void *, curl_off_t, int);
+
+
+#endif /* __CURL_TYPECHECK_GCC_H */

+ 123 - 0
scbc.tools/Include/curl/urlapi.h

@@ -0,0 +1,123 @@
+#ifndef __CURL_URLAPI_H
+#define __CURL_URLAPI_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2018 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl.h"
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/* the error codes for the URL API */
+typedef enum {
+  CURLUE_OK,
+  CURLUE_BAD_HANDLE,          /* 1 */
+  CURLUE_BAD_PARTPOINTER,     /* 2 */
+  CURLUE_MALFORMED_INPUT,     /* 3 */
+  CURLUE_BAD_PORT_NUMBER,     /* 4 */
+  CURLUE_UNSUPPORTED_SCHEME,  /* 5 */
+  CURLUE_URLDECODE,           /* 6 */
+  CURLUE_OUT_OF_MEMORY,       /* 7 */
+  CURLUE_USER_NOT_ALLOWED,    /* 8 */
+  CURLUE_UNKNOWN_PART,        /* 9 */
+  CURLUE_NO_SCHEME,           /* 10 */
+  CURLUE_NO_USER,             /* 11 */
+  CURLUE_NO_PASSWORD,         /* 12 */
+  CURLUE_NO_OPTIONS,          /* 13 */
+  CURLUE_NO_HOST,             /* 14 */
+  CURLUE_NO_PORT,             /* 15 */
+  CURLUE_NO_QUERY,            /* 16 */
+  CURLUE_NO_FRAGMENT          /* 17 */
+} CURLUcode;
+
+typedef enum {
+  CURLUPART_URL,
+  CURLUPART_SCHEME,
+  CURLUPART_USER,
+  CURLUPART_PASSWORD,
+  CURLUPART_OPTIONS,
+  CURLUPART_HOST,
+  CURLUPART_PORT,
+  CURLUPART_PATH,
+  CURLUPART_QUERY,
+  CURLUPART_FRAGMENT,
+  CURLUPART_ZONEID /* added in 7.65.0 */
+} CURLUPart;
+
+#define CURLU_DEFAULT_PORT (1<<0)       /* return default port number */
+#define CURLU_NO_DEFAULT_PORT (1<<1)    /* act as if no port number was set,
+                                           if the port number matches the
+                                           default for the scheme */
+#define CURLU_DEFAULT_SCHEME (1<<2)     /* return default scheme if
+                                           missing */
+#define CURLU_NON_SUPPORT_SCHEME (1<<3) /* allow non-supported scheme */
+#define CURLU_PATH_AS_IS (1<<4)         /* leave dot sequences */
+#define CURLU_DISALLOW_USER (1<<5)      /* no user+password allowed */
+#define CURLU_URLDECODE (1<<6)          /* URL decode on get */
+#define CURLU_URLENCODE (1<<7)          /* URL encode on set */
+#define CURLU_APPENDQUERY (1<<8)        /* append a form style part */
+#define CURLU_GUESS_SCHEME (1<<9)       /* legacy curl-style guessing */
+
+typedef struct Curl_URL CURLU;
+
+/*
+ * curl_url() creates a new CURLU handle and returns a pointer to it.
+ * Must be freed with curl_url_cleanup().
+ */
+CURL_EXTERN CURLU *curl_url(void);
+
+/*
+ * curl_url_cleanup() frees the CURLU handle and related resources used for
+ * the URL parsing. It will not free strings previously returned with the URL
+ * API.
+ */
+CURL_EXTERN void curl_url_cleanup(CURLU *handle);
+
+/*
+ * curl_url_dup() duplicates a CURLU handle and returns a new copy. The new
+ * handle must also be freed with curl_url_cleanup().
+ */
+CURL_EXTERN CURLU *curl_url_dup(CURLU *in);
+
+/*
+ * curl_url_get() extracts a specific part of the URL from a CURLU
+ * handle. Returns error code. The returned pointer MUST be freed with
+ * curl_free() afterwards.
+ */
+CURL_EXTERN CURLUcode curl_url_get(CURLU *handle, CURLUPart what,
+                                   char **part, unsigned int flags);
+
+/*
+ * curl_url_set() sets a specific part of the URL in a CURLU handle. Returns
+ * error code. The passed in string will be copied. Passing a NULL instead of
+ * a part string, clears that part.
+ */
+CURL_EXTERN CURLUcode curl_url_set(CURLU *handle, CURLUPart what,
+                                   const char *part, unsigned int flags);
+
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif

+ 376 - 0
scbc.tools/Log4C/GlobalMacro.h

@@ -0,0 +1,376 @@
+/************** Begin of GlobalMacro.h *******************************************/
+/**********************************************************
+* 版权所有 (C)2008, 51.com
+*
+* 文件名称:GlobalMacro.h
+* 内容摘要:全局宏定义的头文件
+*			本文件包含了所有要用到的全局宏的定义
+* 其它说明:
+* 当前版本:
+* 作    者:温辉敏
+* 完成日期:2009-1-02
+*
+* 修改记录1:
+*    修改日期:
+*    版 本 号:
+*    修 改 人:
+*    修改内容:
+**********************************************************/
+#if !defined(AFX_GLOBALMACRO_H__DD58A78D_C125_410F_B4C8_F0067B797121__INCLUDED_)
+#define AFX_GLOBALMACRO_H__DD58A78D_C125_410F_B4C8_F0067B797121__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+// 获取数组的维数 [7/1/2008 温辉敏]
+#define PARRAYSIZE(array) ((sizeof(array)/sizeof(array[0])))
+
+/** Declare all the standard PWlib class information.
+This macro is used to provide the basic run-time typing capability needed
+by the library. All descendent classes from the #PObject# class require
+these functions for correct operation. Either use ptrThis macro or the
+#PDECLARE_CLASS# macro.
+
+The use of the #PDECLARE_CLASS# macro is no longer recommended for reasons
+of compatibility with documentation systems.
+*/
+#define CLASSINFO(cls, par) \
+  public: \
+	static const char * Class() \
+	{ return #cls; } \
+	virtual const char * GetClass(unsigned ancestor = 0) const \
+	{ return ancestor > 0 ? par::GetClass(ancestor-1) : cls::Class(); } \
+	virtual BOOL IsClass(const char * clsName) const \
+	{ return strcmp(clsName, cls::Class()) == 0; } \
+	virtual BOOL IsDescendant(const char * clsName) const \
+	{ return strcmp(clsName, cls::Class()) == 0 || \
+	  par::IsDescendant(clsName); } 
+
+
+/** Declare all the standard PWlib class information.
+This macro is used to provide the basic run-time typing capability needed
+by the library. All descendent classes from the #PObject# class require
+these functions for correct operation. Either use ptrThis macro or the
+#PDECLARE_CLASS# macro.
+
+The use of the #PDECLARE_CLASS# macro is no longer recommended for reasons
+of compatibility with documentation systems.
+*/
+#define CLASSINFO_BASE(cls) \
+  public: \
+	static const char * Class() \
+	{ return #cls; } \
+	virtual const char * GetClass(unsigned ancestor = 0) const \
+	{ return cls::Class(); } \
+	virtual BOOL IsClass(const char * clsName) const \
+	{ return strcmp(clsName, cls::Class()) == 0; } \
+	virtual BOOL IsDescendant(const char * clsName) const \
+	{ return strcmp(clsName, cls::Class()) == 0; } 
+
+
+/* 函数返回基本状态信息  */
+#ifdef OK
+#undef OK
+#endif /* #ifdef OK */
+#ifndef OK
+#define OK               (0)    /* 成功返回	*/
+#endif /* #ifndef OK */
+
+/* 函数返回基本状态信息  */
+#ifdef FAILURE
+#undef FAILURE
+#endif /* #ifdef FAILURE */
+#ifndef FAILURE
+#define FAILURE           (-1)    /* 失败返回	*/
+#endif /* #ifndef FAILURE */
+
+//////////////////////////////////////////////////////////////////////////
+///一些宏定义
+
+///删除一个数组指针的宏定义
+//lint -emacro(774, DELETEA)
+#ifndef DELETEA
+#define DELETEA(ptr) \
+	if(NULL != ptr) \
+	{ \
+		delete[] ptr; \
+		ptr = NULL; \
+	}
+#endif
+
+///删除一个指针的宏定义
+#ifndef FREEP
+#define FREEP(ptr)		\
+	if(NULL != ptr)		\
+	{					\
+		free(ptr) ;		\
+		ptr = NULL;		\
+	}
+#endif
+
+///删除一个指针的宏定义
+//lint -emacro(774, DELETEP)
+#define DELETEP(ptr)	\
+	if(NULL != (ptr))		\
+	{					\
+		delete (ptr);		\
+		(ptr) = NULL;		\
+	}
+
+///删除一个GDI对象的宏定义
+//lint -emacro(774, DELETEOBJECT)
+#define DELETEOBJECT(ptr)	\
+	if(NULL != (ptr))		\
+	{					\
+		::DeleteObject (ptr);		\
+		(ptr) = NULL;		\
+	}
+
+///Destroy一个Window
+//lint -emacro(774, DESTROYWINDOW)
+#define DESTROYWINDOW(hWnd)	\
+	if (IsWindow(hWnd)) \
+	{ \
+		DestroyWindow(hWnd); \
+	}
+
+///删除一个指针的宏定义
+//lint -emacro(774, FREEP)
+#undef  FREEP
+#define FREEP(ptr)		\
+	if(NULL != ptr)		\
+	{					\
+		free(ptr) ;		\
+		ptr = NULL;		\
+	}
+
+
+/** 定义的根据输入类型来删除不同类型的指针的宏定义
+*/
+#define DELETE_TYPE_P(Type, ptrEvent) \
+	{\
+		Type *ptrEventLocal = (Type *)ptrEvent; \
+		DELETEP(ptrEventLocal); \
+		ptrEvent = NULL; \
+	}
+
+
+/** This macro is used to assert that a condition must be TRUE.
+若condition条件不成立则执行statement语句,然后以return_value值return
+*/
+#define PAssert_ReturnWithValue(condition, return_value) \
+	{  \
+		if (!(condition)) \
+		{ \
+			return (return_value); \
+		} \
+	}
+
+/** This macro is used to assert that a condition must be TRUE.
+若condition条件不成立则执行statement语句,然后return
+*/
+#define PAssert_Return(condition) \
+	{  \
+		if (!(condition)) \
+		{ \
+			return ; \
+		} \
+	}
+
+#ifndef VOS_DELETE_SEM
+#define VOS_DELETE_SEM(semId)	\
+	if (NULL != semId)			\
+	{							\
+		VOS_DeleteSem(semId);	\
+		semId = NULL;			\
+	}
+#endif
+
+/** This macro is used to assert that a condition must be TRUE.
+若condition条件不成立则执行statement语句,然后以return_value值return
+*/
+#define PAssert_Statement_ReturnWithValue(condition, statement, return_value) \
+	{  \
+		if (!(condition)) \
+		{ \
+			statement; \
+			return (return_value); \
+		} \
+	}
+
+/** This macro is used to assert that a condition must be TRUE.
+若condition条件不成立则执行statement语句,然后return
+*/
+#define PAssert_Statement_Return(condition, statement) \
+	{  \
+		if (!(condition)) \
+		{ \
+			statement; \
+			return ; \
+		} \
+	}
+
+/** This macro is used to assert that a pointer must be non-null.
+若指针ptr为NULL则执行statement语句,然后以return_value值return
+*/
+#define PAssertNotNull_Statement_ReturnWithValue(ptr, statement, return_value) \
+	{ \
+		if( (ptr) == NULL) \
+		{ \
+			statement; \
+			return (return_value); \
+		} \
+	}
+
+
+/** This macro is used to assert that a pointer must be non-null.
+若指针ptr为NULL则执行statement语句,然后return
+*/
+#define PAssertNotNull_Statement_Return(ptr, statement) \
+	{ \
+		if( (ptr) == NULL) \
+		{ \
+			statement; \
+			return ; \
+		} \
+	}
+
+/** This macro is used to assert that a pointer must be non-null.
+若指针ptr为NULL则执行statement语句,然后以return_value值return
+*/
+#define PAssertNotNull_ReturnWithValue(ptr, return_value) \
+	{ \
+		if( (ptr) == NULL) \
+		{ \
+			return (return_value); \
+		} \
+	}
+
+
+/** This macro is used to assert that a pointer must be non-null.
+若指针ptr为NULL则执行statement语句,然后return
+*/
+#define PAssertNotNull_Return(ptr) \
+	{ \
+		if( (ptr) == NULL) \
+		{ \
+			return ; \
+		} \
+	}
+
+/** This macro is used to do something and return 
+执行一个语句statement,然后return return_value
+*/
+#define PStatement_Return(statement, return_value) \
+{ \
+	statement; \
+	return return_value; \
+}
+
+/** This macro is used to assert that a condition must be TRUE.
+若condition条件不成立则执行break语句
+*/
+#define PAssert_Break(condition) \
+{  \
+	if (!(condition)) \
+	{ \
+		break ; \
+	} \
+}
+
+/** This macro is used to do something and break 
+执行一个语句statement,然后break
+*/
+#define PStatement_Break(statement) \
+{ \
+	statement; \
+	break; \
+}
+
+/** This macro is used to assert that a condition must be TRUE.
+若condition条件不成立则执行statement语句,然后执行break语句
+*/
+#define PAssert_Statement_Break(condition, statement) \
+{  \
+	if (!(condition)) \
+	{ \
+		statement; \
+		break ; \
+	} \
+}
+
+/** 空操作
+*/
+#define NULL_OPERATION
+
+// 获取数组的维数 
+#define PARRAYSIZE(array) ((sizeof(array)/sizeof(array[0])))
+
+/** Declare all the standard RTTI class information.
+This macro is used to provide the basic run-time typing capability needed
+by the library. All descendent classes from the #PObject# class require
+these functions for correct operation. Either use ptrThis macro or the
+#PDECLARE_CLASS# macro.
+
+The use of the #PDECLARE_CLASS# macro is no longer recommended for reasons
+of compatibility with documentation systems.
+*/
+#define CLASSINFO(cls, par) \
+  public: \
+	static const char * Class() \
+	{ return #cls; } \
+	virtual const char * GetClass(unsigned ancestor = 0) const \
+	{ return ancestor > 0 ? par::GetClass(ancestor-1) : cls::Class(); } \
+	virtual BOOL IsClass(const char * clsName) const \
+	{ return strcmp(clsName, cls::Class()) == 0; } \
+	virtual BOOL IsDescendant(const char * clsName) const \
+	{ return strcmp(clsName, cls::Class()) == 0 || \
+	par::IsDescendant(clsName); } 
+
+
+///memset缺省构造函数
+#ifndef MEMSET_CONSTRUCTOR
+#define MEMSET_CONSTRUCTOR(ClassType) \
+	ClassType() \
+	{ \
+		memset(this, 0, sizeof(ClassType)); \
+	}
+#endif
+
+#if 0
+#ifdef __cplusplus
+/** 
+按照特定数据类型删除该数据类型的数组指针
+*/
+#ifndef DELETE_ARRAY_TEMPLATE
+#define DELETE_ARRAY_TEMPLATE
+template <class classType>
+void DeleteArray(void *&ptr)
+{
+	classType *ptrClassType = (classType *)ptr;
+	DELETEA(ptrClassType);
+	ptr = NULL;
+}
+#endif
+
+/** 
+按照特定数据类型删除该数据类型的指针
+*/
+#ifndef DELETE_TEMPLATE
+#define DELETE_TEMPLATE
+template <class classType>
+void Delete(void *&ptr)
+{
+	classType *ptrClassType = (classType *)ptr;
+	DELETEP(ptrClassType);
+	ptr = NULL;
+}
+#endif
+#endif
+#endif
+
+
+#endif // !defined(AFX_GLOBALMACRO_H__DD58A78D_C125_410F_B4C8_F0067B797121__INCLUDED_)
+
+/************** End of GlobalMacro.h *******************************************/

+ 479 - 0
scbc.tools/Log4C/Log4C.vcproj

@@ -0,0 +1,479 @@
+<?xml version="1.0" encoding="gb2312"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9.00"
+	Name="Log4C"
+	ProjectGUID="{2CE4A92D-3CF6-4BFA-975A-C72EE8536141}"
+	Keyword="Win32Proj"
+	TargetFrameworkVersion="131072"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="2"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\Log4C"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LOG4C_EXPORTS;XML_STATIC;LOG4C_ENABLE"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="2"
+				ModuleDefinitionFile="log4c.def"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/Log4C.pdb"
+				SubSystem="2"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
+				ImportLibrary="lib/Log4C.lib"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+				CommandLine=""
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="2"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalIncludeDirectories="..\Log4C"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LOG4C_EXPORTS;XML_STATIC;LOG4C_ENABLE"
+				RuntimeLibrary="0"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="1"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
+				ImportLibrary="lib/Log4C.lib"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+				CommandLine=""
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Ô´Îļþ"
+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath=".\appender.c"
+				>
+			</File>
+			<File
+				RelativePath=".\appender_type_rollingfile.c"
+				>
+			</File>
+			<File
+				RelativePath=".\appender_type_stream.c"
+				>
+			</File>
+			<File
+				RelativePath=".\appender_type_stream2.c"
+				>
+			</File>
+			<File
+				RelativePath=".\category.c"
+				>
+			</File>
+			<File
+				RelativePath=".\init.c"
+				>
+			</File>
+			<File
+				RelativePath=".\layout.c"
+				>
+			</File>
+			<File
+				RelativePath=".\layout_type_basic.c"
+				>
+			</File>
+			<File
+				RelativePath=".\layout_type_basic_r.c"
+				>
+			</File>
+			<File
+				RelativePath=".\layout_type_dated.c"
+				>
+			</File>
+			<File
+				RelativePath=".\layout_type_dated_r.c"
+				>
+			</File>
+			<File
+				RelativePath=".\layout_type_dated_threadid.c"
+				>
+			</File>
+			<File
+				RelativePath=".\log.c"
+				>
+			</File>
+			<File
+				RelativePath=".\log4c.def"
+				>
+			</File>
+			<File
+				RelativePath=".\logging_event.c"
+				>
+			</File>
+			<File
+				RelativePath=".\priority.c"
+				>
+			</File>
+			<File
+				RelativePath=".\rc.c"
+				>
+			</File>
+			<File
+				RelativePath=".\rollingpolicy.c"
+				>
+			</File>
+			<File
+				RelativePath=".\rollingpolicy_type_sizewin.c"
+				>
+			</File>
+			<File
+				RelativePath=".\sharedmemory.c"
+				>
+			</File>
+			<File
+				RelativePath=".\version.c"
+				>
+			</File>
+			<File
+				RelativePath=".\vosnt.c"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Í·Îļþ"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+		</Filter>
+		<Filter
+			Name="×ÊÔ´Îļþ"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+		</Filter>
+		<Filter
+			Name="sd"
+			>
+			<File
+				RelativePath=".\sd\defs.h"
+				>
+			</File>
+			<File
+				RelativePath=".\sd\domnode-xml-parser.c"
+				>
+			</File>
+			<File
+				RelativePath=".\sd\domnode-xml-parser.h"
+				>
+			</File>
+			<File
+				RelativePath=".\sd\domnode-xml-scanner.c"
+				>
+			</File>
+			<File
+				RelativePath=".\sd\domnode-xml-scanner.h"
+				>
+			</File>
+			<File
+				RelativePath=".\sd\domnode-xml.c"
+				>
+			</File>
+			<File
+				RelativePath=".\sd\domnode-xml.h"
+				>
+			</File>
+			<File
+				RelativePath=".\sd\domnode.c"
+				>
+			</File>
+			<File
+				RelativePath=".\sd\domnode.h"
+				>
+			</File>
+			<File
+				RelativePath=".\sd\error.c"
+				>
+			</File>
+			<File
+				RelativePath=".\sd\error.h"
+				>
+			</File>
+			<File
+				RelativePath=".\sd\expat.h"
+				>
+			</File>
+			<File
+				RelativePath=".\sd\expat_external.h"
+				>
+			</File>
+			<File
+				RelativePath=".\sd\factory.c"
+				>
+			</File>
+			<File
+				RelativePath=".\sd\factory.h"
+				>
+			</File>
+			<File
+				RelativePath=".\sd\hash.c"
+				>
+			</File>
+			<File
+				RelativePath=".\sd\hash.h"
+				>
+			</File>
+			<File
+				RelativePath=".\sd\list.c"
+				>
+			</File>
+			<File
+				RelativePath=".\sd\list.h"
+				>
+			</File>
+			<File
+				RelativePath=".\sd\malloc.c"
+				>
+			</File>
+			<File
+				RelativePath=".\sd\malloc.h"
+				>
+			</File>
+			<File
+				RelativePath=".\sd\sd_xplatform.c"
+				>
+			</File>
+			<File
+				RelativePath=".\sd\sd_xplatform.h"
+				>
+			</File>
+			<File
+				RelativePath=".\sd\sprintf.c"
+				>
+			</File>
+			<File
+				RelativePath=".\sd\sprintf.h"
+				>
+			</File>
+			<File
+				RelativePath=".\sd\stack.c"
+				>
+			</File>
+			<File
+				RelativePath=".\sd\stack.h"
+				>
+			</File>
+			<Filter
+				Name="include"
+				>
+				<File
+					RelativePath=".\log4c\appender.h"
+					>
+				</File>
+				<File
+					RelativePath=".\log4c\appender_type_rollingfile.h"
+					>
+				</File>
+				<File
+					RelativePath=".\log4c\appender_type_stream.h"
+					>
+				</File>
+				<File
+					RelativePath=".\log4c\appender_type_stream2.h"
+					>
+				</File>
+				<File
+					RelativePath=".\log4c\buffer.h"
+					>
+				</File>
+				<File
+					RelativePath=".\log4c\category.h"
+					>
+				</File>
+				<File
+					RelativePath=".\log4c\config-win32.h"
+					>
+				</File>
+				<File
+					RelativePath=".\log4c\defs.h"
+					>
+				</File>
+				<File
+					RelativePath=".\log4c\init.h"
+					>
+				</File>
+				<File
+					RelativePath=".\log4c\layout.h"
+					>
+				</File>
+				<File
+					RelativePath=".\log4c\layout_type_basic.h"
+					>
+				</File>
+				<File
+					RelativePath=".\log4c\layout_type_dated.h"
+					>
+				</File>
+				<File
+					RelativePath=".\log4c\location_info.h"
+					>
+				</File>
+				<File
+					RelativePath=".\log4c\logging_event.h"
+					>
+				</File>
+				<File
+					RelativePath=".\log4c\priority.h"
+					>
+				</File>
+				<File
+					RelativePath=".\log4c\rc.h"
+					>
+				</File>
+				<File
+					RelativePath=".\log4c\rollingpolicy.h"
+					>
+				</File>
+				<File
+					RelativePath=".\log4c\rollingpolicy_type_sizewin.h"
+					>
+				</File>
+				<File
+					RelativePath=".\log4c\version.h"
+					>
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>

+ 3 - 0
scbc.tools/Log4C/log4c.def

@@ -0,0 +1,3 @@
+EXPORTS
+	log4c_init
+	log4c_fini

+ 27 - 0
scbc.tools/Log4C/log4c.h

@@ -0,0 +1,27 @@
+/* $Id$
+ *
+ * log4c.h
+ *
+ * Copyright 2001-2002, Meiosys (www.meiosys.com). All rights reserved.
+ *
+ * See the COPYING file for the terms of usage and distribution.
+ */
+
+#ifndef log4c_log4c_h
+#define log4c_log4c_h
+
+#define IMPLEMENT_LOG4C
+
+#include <log4c/version.h>
+#include <log4c/init.h>
+#include <log4c/rc.h>
+#include <log4c/appender.h>
+#include <log4c/rollingpolicy.h>
+#include <log4c/category.h>
+#include <log4c/layout.h>
+#include <log4c/logging_event.h>
+#include <log4c/priority.h>
+#include <log4c/log.h>
+
+#endif
+

+ 251 - 0
scbc.tools/Log4C/log4c/appender.h

@@ -0,0 +1,251 @@
+/* $Id$
+ *
+ * appender.h
+ * 
+ * Copyright 2001-2003, Meiosys (www.meiosys.com). All rights reserved.
+ *
+ * See the COPYING file for the terms of usage and distribution.
+ */
+
+#ifndef log4c_appender_h
+#define log4c_appender_h
+
+/**
+ * @file appender.h
+ *
+ * @brief Implement this interface for your own strategies for printing log
+ * statements.
+ *
+ * @todo the appender interface needs a better configuration system
+ * depending on the layout type. The udata field is a just a trick.
+ **/
+
+#include <log4c/defs.h>
+#include <log4c/layout.h>
+#include <stdio.h>
+
+__LOG4C_BEGIN_DECLS
+
+struct __log4c_appender;
+
+/**
+ * log4c appender class 
+ **/
+typedef struct __log4c_appender log4c_appender_t;
+
+/**
+ * @brief log4c appender type class
+ *
+ * Attributes description:
+ * 
+ * @li @c name appender type name 
+ * @li @c open
+ * @li @c append
+ * @li @c close
+ **/
+typedef struct log4c_appender_type {
+    const char*	  name;
+    int (*open)	  (log4c_appender_t*);
+    int (*append) (log4c_appender_t*, const log4c_logging_event_t*);
+    int (*close)  (log4c_appender_t*);
+} log4c_appender_type_t;
+
+/**
+ * Get a pointer to an existing appender type.
+ *
+ * @param a_name the name of the appender type to return.  
+ * @returns a pointer to an existing appender type, or NULL if no appender
+ * type with the specified name exists.
+ **/
+LOG4C_API const log4c_appender_type_t* log4c_appender_type_get(const char* a_name);
+
+/**
+ * Use this function to register an appender type with log4c.
+ * Once this is done you may refer to this type by name both 
+ * programmatically and in the log4c
+ * configuration file.
+ *
+ * @param a_type a pointer to the new appender type to set.
+ * @returns a pointer to the previous appender type of same name.
+ * 
+ * Example code fragment: 
+ * @code
+ * 
+ * const log4c_appender_type_t log4c_appender_type_s13_file = {
+ *   "s13_file",
+ *   s13_file_open,
+ *   s13_file_append,
+ *   s13_file_close,
+ * };
+ *  
+ *  log4c_appender_type_set(&log4c_appender_type_s13_file);
+ * @endcode
+ **/
+LOG4C_API const log4c_appender_type_t* log4c_appender_type_set(
+    const log4c_appender_type_t* a_type);
+
+/**
+ * Get a pointer to an existing appender.
+ *
+ * @param a_name the name of the appender to return.
+ * @returns a pointer to an existing appender, or NULL if no appender
+ * with the specfied name exists.
+ **/
+LOG4C_API log4c_appender_t* log4c_appender_get(const char* a_name);
+
+/**
+ * Constructor for log4c_appender_t. 
+ **/
+LOG4C_API log4c_appender_t* log4c_appender_new(const char* a_name);
+
+/**
+ * Destructor for log4c_appender_t.
+ **/
+LOG4C_API void log4c_appender_delete(log4c_appender_t* a_appender);
+
+/**
+ * @param a_appender the log4c_appender_t object
+ * @return the appender name
+ **/
+LOG4C_API const char* log4c_appender_get_name(const log4c_appender_t* a_appender);
+
+/**
+ * @param a_appender the log4c_appender_t object
+ * @return the appender operations
+ **/
+LOG4C_API const log4c_appender_type_t* log4c_appender_get_type(
+    const log4c_appender_t* a_appender);
+
+/**
+ * @param a_appender the log4c_appender_t object
+ * @return the appender layout
+ **/
+LOG4C_API const log4c_layout_t* log4c_appender_get_layout(
+    const log4c_appender_t* a_appender);
+
+/**
+ * @param a_appender the log4c_appender_t object
+ * @return the appender user data
+ **/
+LOG4C_API void* log4c_appender_get_udata(const log4c_appender_t* a_appender);
+
+/**
+ * sets the appender type
+ *
+ * @param a_appender the log4c_appender_t object
+ * @param a_type the new appender type
+ * @return the previous appender type
+ **/
+LOG4C_API const log4c_appender_type_t* log4c_appender_set_type(
+    log4c_appender_t* a_appender,
+    const log4c_appender_type_t* a_type);
+
+/**
+ * sets the appender user data
+ *
+ * @param a_appender the log4c_appender_t object
+ * @param a_udata the new appender user data
+ * @return the previous appender user data
+ **/
+LOG4C_API void* log4c_appender_set_udata(log4c_appender_t*	a_appender, 
+				      void* a_udata);
+
+/**
+ * sets the appender layout
+ *
+ * @param a_appender the log4c_appender_t object
+ * @param a_layout the new appender layout
+ * @return the previous appender layout
+ **/
+LOG4C_API const log4c_layout_t* log4c_appender_set_layout(
+    log4c_appender_t* a_appender,
+    const log4c_layout_t* a_layout);
+
+/**
+ * opens the appender.
+ *
+ * @param a_appender the log4c_appender_t object
+ **/
+LOG4C_API int log4c_appender_open(log4c_appender_t* a_appender);
+
+/**
+ * log in appender specific way.
+ *
+ * @param a_appender the log4c_appender object
+ * @param a_event the log4c_logging_event_t object to log.
+ **/
+LOG4C_API int log4c_appender_append(
+    log4c_appender_t* a_appender,
+    log4c_logging_event_t* a_event);
+
+/**
+* log in appender specific way.
+*
+* @param a_appender the log4c_appender object
+* @param a_event the log4c_logging_event_t object to log.
+**/
+LOG4C_API int log4c_appender_append_no_file_num_no_layout(
+	log4c_appender_t* a_appender,
+	log4c_logging_event_t* a_event);
+
+/**
+ * closes the appender
+ *
+ * @param a_appender the log4c_appender_t object
+ * @return zero if successful, -1 otherwise
+ **/
+LOG4C_API int log4c_appender_close(log4c_appender_t* a_appender);
+
+/**
+ * prints the appender on a stream
+ *
+ * @param a_appender the log4c_appender_t object
+ * @param a_stream the stream
+ **/
+LOG4C_API void log4c_appender_print(const log4c_appender_t* a_appender, 
+				 FILE* a_stream);
+     
+/**
+ * prints all the current registered appender types on a stream
+ *
+ * @param fp the stream
+ **/                            
+LOG4C_API void log4c_appender_types_print(FILE *fp);
+
+/** 删除本appender.c文件中定义的全局和静态的指针指向的内存,防止内存泄漏
+如:
+1.gs_types.
+2.
+@return void.
+作者:jesse 日期:2008.09.08
+*/
+LOG4C_API void log4c_appender_delete_global();
+
+/**
+ * Helper macro to define static appender types.
+ *
+ * @param a_type the log4c_appender_type_t object to define
+ * @warning needs GCC support: otherwise this macro does nothing
+ * @deprecated This macro, and the static initialialization
+ * of appenders in general, is deprecated. Use rather
+ * the log4c_appender_type_set() function to initialize your appenders
+ * before calling log4c_init() 
+ *
+ **/
+#ifdef __GNUC__
+#   define log4c_appender_type_define(a_type) \
+    typedef int log4c_appender_type_define_##a_type __attribute__((deprecated)); \
+    static log4c_appender_type_define_##a_type __unsused_var __attribute__ ((unused));
+#else
+#   define log4c_appender_type_define(a_type)
+#endif
+
+/**
+ * @internal
+ **/
+struct __sd_factory;
+LOG4C_API struct __sd_factory* log4c_appender_factory;
+
+__LOG4C_END_DECLS
+
+#endif

+ 71 - 0
scbc.tools/Log4C/log4c/appender_typ_stream.h

@@ -0,0 +1,71 @@
+/************** Begin of log4c/appender_type_stream.h *******************************************/
+/* $Id$
+*
+* appender_type_stream.h
+* 
+* Copyright 2001-2003, Meiosys (www.meiosys.com). All rights reserved.
+*
+* See the COPYING file for the terms of usage and distribution.
+*/
+
+#ifndef log4c_appender_type_stream_h
+#define log4c_appender_type_stream_h
+
+/**
+* @file appender_type_stream.h
+*
+* @brief Log4c stream appender interface.
+*
+* The stream appender uses a file handle @c FILE* for logging. The
+* appender's name is used as the file name which will be opened at first
+* log. An appender can also be associated to an opened file handle using
+* the log4c_appender_set_udata() method to update the appender user data
+* field. In ptrThis last case, the appender name has no meaning. 2 default
+* stream appenders are defined: @c "stdout" and @c "stderr".
+*
+* The following examples shows how to define and use stream appenders.
+* 
+* @li the simple way
+* @code
+*
+* log4c_appender_t* myappender;
+*
+* myappender = log4c_appender_get("myfile.log");
+* log4c_appender_set_type(myappender, &log4c_appender_type_stream);
+* 
+* @endcode
+*
+* @li the sophisticated way
+* @code
+*
+* log4c_appender_t* myappender;
+*
+* myappender = log4c_appender_get("myappender");
+*    
+* log4c_appender_set_type(myappender, &log4c_appender_type_stream);
+* log4c_appender_set_udata(myappender, fopen("myfile.log", "w"));
+*
+* @endcode
+*
+**/
+
+///#include <log4c/defs.h>
+///#include <log4c/appender.h>
+
+__LOG4C_BEGIN_DECLS
+
+/**
+* Stream appender type definition.
+*
+* This should be used as a parameter to the log4c_appender_set_type()
+* routine to set the type of the appender.
+*
+**/
+extern const log4c_appender_type_t log4c_appender_type_stream;
+
+__LOG4C_END_DECLS
+
+#endif
+
+
+/************** End of log4c/appender_type_stream.h *******************************************/

+ 58 - 0
scbc.tools/Log4C/log4c/appender_type_mmap.h

@@ -0,0 +1,58 @@
+/************** Begin of appender_type_mmap.h *******************************************/
+/* $Id$
+*
+* appender_type_mmap.h
+* 
+* Copyright 2001-2003, Meiosys (www.meiosys.com). All rights reserved.
+*
+* See the COPYING file for the terms of usage and distribution.
+*/
+
+#ifndef log4c_appender_type_mmap_h
+#define log4c_appender_type_mmap_h
+
+/**
+* @file appender_type_mmap.h
+*
+* @brief Log4c mmap(2) appender interface.
+*
+* The mmap appender uses a fixed length memory mapped file for
+* logging. The appender's name is used as the file name which will be
+* opened and mapped to memory at first use. The memory mapped file is then
+* used as a rotating buffer in which logging events are written.
+*
+* The following examples shows how to define and use mmap appenders.
+* 
+* @code
+*
+* log4c_appender_t* myappender;
+*
+* myappender = log4c_appender_get("myfile.log");
+* log4c_appender_set_type(myappender, &log4c_appender_type_mmap);
+* 
+* @endcode
+*
+* @warning the file is not created at first use. It should already exist
+* and have a reasonable size, a mutilple of a page size.
+*
+**/
+///#include <log4c/defs.h>
+///#include <log4c/appender.h>
+
+__LOG4C_BEGIN_DECLS
+
+/**
+* Mmap appender type definition.
+*
+* This should be used as a parameter to the log4c_appender_set_type()
+* routine to set the type of the appender.
+*
+**/
+extern const log4c_appender_type_t log4c_appender_type_mmap;
+
+__LOG4C_END_DECLS
+
+#endif
+
+
+/************** End of appender_type_mmap.h *******************************************/

+ 120 - 0
scbc.tools/Log4C/log4c/appender_type_rollingfile.h

@@ -0,0 +1,120 @@
+/* $Id: appender_type_rollingfile.h
+ *
+ * appender_type_rollingfile.h
+ * 
+ *
+ * See the COPYING file for the terms of usage and distribution.
+ */
+
+#ifndef log4c_appender_type_rollingfile_h
+#define log4c_appender_type_rollingfile_h
+
+/**
+ * @file appender_type_rollingfile.h
+ *
+ * @brief Log4c rolling file appender interface.
+ *
+ * The rolling file appender implements a logging mechanism of
+ * a list of files up to a maximum number.
+ *
+ * The files are written by default to the current directory with logging
+ * names folowing the pattern log.1, log.2 etc.  These parameters may
+ * be changed using the appropriate setter functions.
+ *
+ * If the appender fails to open logfiles for writing then the
+ * messages are logged to stderr--it will continue to try to open
+ * the zero-th file for writing at rollover events so if it succeeds
+ * at some point to open that file the messages will start to appear therein
+ * and will no longer be sent to stderr.
+ *
+ * Switching from logging from one file
+ * to the next is referred to as a 'rollover event'.
+ *
+ * The policy that determines when a rollover event should happen is
+ * called a 'rolling policy'.
+ *
+ * A mechanism is provided to allow different rolling policies to be defined.
+ *
+ * Log4c ships with (and defaults to) the classic size-window rollover policy:
+ * this triggers rollover when files reach a maximum size.  The first file in
+ * the list is
+ * always the current file; when a rollover event occurs files are shifted up
+ * by one position in the list--if the number of files in the list has already
+ * reached the max then the oldest file is rotated out of the window.
+ *
+ * See the documentation in the rollingpolicy_type_sizewin.h file for
+ * more details on the size-win rollover policy.
+ *
+*/
+
+#include <log4c/defs.h>
+#include <log4c/appender.h>
+#include <log4c/rollingpolicy.h>
+
+__LOG4C_BEGIN_DECLS
+
+/**
+ * rollingfile appender type definition.
+ *
+ * This should be used as a parameter to the log4c_appender_set_type()
+ * routine to set the type of the appender.
+ *
+ **/
+LOG4C_API const log4c_appender_type_t log4c_appender_type_rollingfile;
+
+/**
+ * Get a new rolling file appender configuration object.
+ * @return a new rolling file appender configuration object, otherwise NULL.
+*/
+LOG4C_API rollingfile_udata_t *rollingfile_make_udata(void);
+
+/**
+ * Set the logging directory in this rolling file appender configuration.
+ * @param rfudatap the rolling file appender configuration object.
+ * @param logdir the logging directory to set.
+ * @return zero if successful, non-zero otherwise.
+ */
+LOG4C_API int rollingfile_udata_set_logdir(rollingfile_udata_t *rfudatap,char* logdir);
+/**
+ * Set the prefix string in this rolling file appender configuration.
+ * @param rfudatap the rolling file appender configuration object.
+ * @param prefix the logging files prfix to use.
+ * @return zero if successful, non-zero otherwise.
+ */                            
+LOG4C_API int rollingfile_udata_set_files_prefix(rollingfile_udata_t *rfudatap, char * prefix);
+
+LOG4C_API int rollingfile_udata_set_files_ext(rollingfile_udata_t *rfudatap, char * ext);
+/**
+ * Set the rolling policy in this rolling file appender configuration.
+ * @param rfudatap the rolling file appender configuration object.
+ * @param policyp the logging files prfix to use.
+ * @return zero if successful, non-zero otherwise.
+ */                          
+LOG4C_API int rollingfile_udata_set_policy(rollingfile_udata_t* rfudatap,log4c_rollingpolicy_t* policyp);                       
+/**
+ * Get the logging directory in this rolling file appender configuration.
+ * @param rfudatap the rolling file appender configuration object.
+ * @return the logging directory.
+ */                              
+LOG4C_API const char* rollingfile_udata_get_logdir(rollingfile_udata_t* rfudatap);
+              
+/**
+ * Get the prefix string in this rolling file appender configuration.
+ * @param rfudatap the rolling file appender configuration object.
+ * @return the prefix.
+ */ 
+LOG4C_API const char* rollingfile_udata_get_files_prefix(rollingfile_udata_t* rfudatap);
+
+
+LOG4C_API const char* rollingfile_udata_get_files_ext(rollingfile_udata_t* rfudatap);
+
+/**
+ * Get the prefix string in this rolling file appender configuration.
+ * @param rfudatap the rolling file appender configuration object.
+ * @return the current size of the file being logged to.
+ */ 
+LOG4C_API long  rollingfile_get_current_file_size( rollingfile_udata_t* rfudatap);
+
+__LOG4C_END_DECLS
+
+#endif

+ 67 - 0
scbc.tools/Log4C/log4c/appender_type_stream.h

@@ -0,0 +1,67 @@
+/* $Id$
+ *
+ * appender_type_stream.h
+ * 
+ * Copyright 2001-2003, Meiosys (www.meiosys.com). All rights reserved.
+ *
+ * See the COPYING file for the terms of usage and distribution.
+ */
+
+#ifndef log4c_appender_type_stream_h
+#define log4c_appender_type_stream_h
+
+/**
+ * @file appender_type_stream.h
+ *
+ * @brief Log4c stream appender interface.
+ *
+ * The stream appender uses a file handle @c FILE* for logging. The
+ * appender's name is used as the file name which will be opened at first
+ * log. An appender can also be associated to an opened file handle using
+ * the log4c_appender_set_udata() method to update the appender user data
+ * field. In this last case, the appender name has no meaning. 2 default
+ * stream appenders are defined: @c "stdout" and @c "stderr".
+ *
+ * The following examples shows how to define and use stream appenders.
+ * 
+ * @li the simple way
+ * @code
+ *
+ * log4c_appender_t* myappender;
+ *
+ * myappender = log4c_appender_get("myfile.log");
+ * log4c_appender_set_type(myappender, &log4c_appender_type_stream);
+ * 
+ * @endcode
+ *
+ * @li the sophisticated way
+ * @code
+ *
+ * log4c_appender_t* myappender;
+ *
+ * myappender = log4c_appender_get("myappender");
+ *    
+ * log4c_appender_set_type(myappender, &log4c_appender_type_stream);
+ * log4c_appender_set_udata(myappender, fopen("myfile.log", "w"));
+ *
+ * @endcode
+ *
+ **/
+
+#include <log4c/defs.h>
+#include <log4c/appender.h>
+
+__LOG4C_BEGIN_DECLS
+
+/**
+ * Stream appender type definition.
+ *
+ * This should be used as a parameter to the log4c_appender_set_type()
+ * routine to set the type of the appender.
+ *
+ **/
+extern const log4c_appender_type_t log4c_appender_type_stream;
+
+__LOG4C_END_DECLS
+
+#endif

+ 130 - 0
scbc.tools/Log4C/log4c/appender_type_stream2.h

@@ -0,0 +1,130 @@
+/* 
+ *
+ * appender_type_stream.h
+ * 
+ * Copyright 2001-2003, Meiosys (www.meiosys.com). All rights reserved.
+ *
+ * See the COPYING file for the terms of usage and distribution.
+ */
+
+#ifndef log4c_appender_type_stream2_h
+#define log4c_appender_type_stream2_h
+
+/**
+ * @file appender_type_stream2.h
+ *
+ * @brief Log4c stream2 appender interface.
+ *
+ * The stream2 appender uses a file handle @c FILE* for logging.
+ * It can be used with @c stdout, @c stderr or a normal file.
+ * It is pretty primitive as it does not do file rotation, or have a maximum
+ * configurable file size etc. It improves on the stream appender in a few
+ * ways that make it a better starting point for new stream based appenders.
+ *
+ * It enhances the stream appender by allowing
+ * the default file pointer to be used in buffered or unbuffered mode.
+ * Also when you set the file pointer stream2 will not attempt to close
+ * it on exit which avoids it fighting with the owner of the file pointer.
+ * stream2 is configured via setter functions--the udata is
+ * not exposed directly.  This means that new options (eg. configure the open
+ * mode ) could be added to stream2 while maintaining backward compatability.
+ *
+ * The appender can be used with default values, for example as follows:
+ *
+ * @code
+ * log4c_appender_t* myappender;
+ *
+ * myappender = log4c_appender_get("/var/logs/mylog.log");
+ * log4c_appender_set_type(myappender,log4c_appender_type_get("stream2"));
+ *
+ * @endcode
+ *
+ * In this case the appender will  be configured automatically with default 
+ * values: 
+ * @li the filename is the same as the name of the appender,
+ * @c "/var/logs/mymlog.log"
+ * @li the file is opened in "w+" mode
+ * @li the default system buffer is used (cf; @c setbuf() ) in buffered mode
+ *
+ * The stream2 appender can be configured by passing it a file pointer
+ * to use.  In this case you manage the file pointer yourself--open,
+ * option setting, closing.  If you set the file pointer log4c will
+ * not close the file on exiting--you must do this:
+ * 
+ * @code
+ * log4c_appender_t* myappender;
+ * FILE * fp = fopen("myfile.log", "w");
+ *
+ * myappender = log4c_appender_get("myappender");
+ * log4c_appender_set_type(myappender, log4c_appender_type_get("stream2"));
+ * log4c_stream2_set_fp(stream2_appender,myfp);
+ *
+ * @endcode
+ *
+ * The default file pointer can be configured to use unbuffered mode.
+ * Buffered mode is typically 25%-50% faster than unbuffered mode but
+ * unbuffered mode is useful if your preference is for a more synchronized 
+ * log file:
+ *
+ * @code log4c_appender_t* myappender;
+ *
+ * myappender = log4c_appender_get("/var/logs/mylog.log");
+ * log4c_appender_set_type(myappender,log4c_appender_type_get("stream2"));
+ * log4c_stream2_set_flags(myappender, LOG4C_STREAM2_UNBUFFERED);
+ *
+ * @endcode
+ *
+ **/
+
+#include <log4c/defs.h>
+#include <log4c/appender.h>
+
+__LOG4C_BEGIN_DECLS
+
+/**
+ * Stream2 appender type definition.
+ *
+ * This should be used as a parameter to the log4c_appender_set_type()
+ * routine to set the type of the appender.
+ *
+ **/
+LOG4C_API const log4c_appender_type_t log4c_appender_type_stream2;
+
+/**
+ * Set the file pointer for this appender.
+ * @param this a pointer to the appender
+ * @param fp the file pointer this appender will use.  The caller is
+ * responsible for managing the file pointer (open, option setting, closing).
+ */      
+LOG4C_API void log4c_stream2_set_fp(log4c_appender_t* a_this, FILE *fp);
+
+/**
+ * Get the file pointer for this appender.
+ * @param this a pointer to the appender
+ * @return the file pointer for this appender.  If there's a problem
+ * returns NULL.
+ * 
+ */ 
+LOG4C_API FILE * log4c_stream2_get_fp(log4c_appender_t* a_this);
+
+
+/**
+ * Set the flags for this appender.
+ * @param this a pointer to the appender
+ * @param flags ar teh flags to set. These will overwrite the existing flags.
+ * Currently supported flags:  LOG4C_STREAM2_UNBUFFERED
+ * 
+ */
+LOG4C_API void log4c_stream2_set_flags(log4c_appender_t* a_this, int flags);
+#define LOG4C_STREAM2_UNBUFFERED 0x01
+
+/**
+ * Get the flags for this appender.
+ * @param this a pointer to the appender
+ * @return the flags for this appender. returns -1 if there was a problem.
+ */
+LOG4C_API int log4c_stream2_get_flags(log4c_appender_t* a_this);
+
+__LOG4C_END_DECLS
+
+#endif

+ 56 - 0
scbc.tools/Log4C/log4c/appender_type_syslog.h

@@ -0,0 +1,56 @@
+/************** Begin of appender_type_syslog.h *******************************************/
+/* $Id$
+*
+* appender_type_syslog.h
+* 
+* Copyright 2001-2003, Meiosys (www.meiosys.com). All rights reserved.
+*
+* See the COPYING file for the terms of usage and distribution.
+*/
+
+#ifndef log4c_appender_type_syslog_h
+#define log4c_appender_type_syslog_h
+
+/**
+* @file appender_type_syslog.h
+*
+* @brief Log4c syslog(3) appender interface.
+*
+* The syslog appender uses the syslog(3) interface for logging. The log4c
+* priorities are mapped to the syslog priorities and the appender name is
+* used as a syslog identifier. 1 default syslog appender is defined: @c
+* "syslog".
+*
+* The following examples shows how to define and use syslog appenders.
+* 
+* @code
+*
+* log4c_appender_t* myappender;
+*
+* myappender = log4c_appender_get("myappender");
+* log4c_appender_set_type(myappender, &log4c_appender_type_syslog);
+* 
+* @endcode
+*
+**/
+
+///#include <log4c/defs.h>
+///#include <log4c/appender.h>
+
+__LOG4C_BEGIN_DECLS
+
+	/**
+	* Syslog appender type definition.
+	*
+	* This should be used as a parameter to the log4c_appender_set_type()
+	* routine to set the type of the appender.
+	*
+	**/
+	extern const log4c_appender_type_t log4c_appender_type_syslog;
+
+__LOG4C_END_DECLS
+
+#endif
+
+
+	/************** End of appender_type_syslog.h *******************************************/

+ 46 - 0
scbc.tools/Log4C/log4c/buffer.h

@@ -0,0 +1,46 @@
+/* $Id$
+ *
+ * buffer.h
+ *
+ * See the COPYING file for the terms of usage and distribution.
+ */
+
+#ifndef __log4c_buffer_h
+#define __log4c_buffer_h
+
+/**
+ * @file buffer.h
+ *
+ * @brief log4c buffer
+ *
+ **/
+
+#include <log4c/defs.h>
+#include <stddef.h>
+
+__LOG4C_BEGIN_DECLS
+
+/**
+ * @brief buffer object
+ *
+ * Attributes description:
+ *
+ * @li @c size current size of the buffer
+ * @li @c maxsize maximum size of the buffer. 0 means no limitation.
+ * @li @c data raw data
+ **/
+typedef struct
+{
+    size_t buf_size;
+    size_t buf_maxsize;
+    char*  buf_data;
+
+} log4c_buffer_t;
+
+#define LOG4C_BUFFER_SIZE_DEFAULT  1024
+
+#define LOG4C_BUFFER_SIZE_MAX 1024*10
+
+__LOG4C_END_DECLS
+
+#endif

+ 651 - 0
scbc.tools/Log4C/log4c/category.h

@@ -0,0 +1,651 @@
+/* $Id$
+ *
+ * category.h
+ * 
+ * Copyright 2001-2003, Meiosys (www.meiosys.com). All rights reserved.
+ *
+ * See the COPYING file for the terms of usage and distribution.
+ */
+
+#ifndef log4c_category_h
+#define log4c_category_h
+
+/**
+ * @file category.h
+ *
+ * @brief central class in the log4c package. 
+ * 
+ * One of the distintive features of log4j (and hence log4c) are
+ * hierarchical categories and their evaluation.
+ *
+ **/   
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <log4c/defs.h>
+#include <log4c/priority.h>
+#include <log4c/location_info.h>
+
+__LOG4C_BEGIN_DECLS
+
+struct __log4c_appender;
+struct __log4c_category;
+
+/**
+ * log4c category class 
+ **/
+typedef struct __log4c_category	log4c_category_t;
+
+/**
+ * Instantiate a log4c_category_t with name @a name. This method
+ * does not set priority of the category which is by default @c
+ * LOG4C_PRIORITY_NOTSET.
+ * 
+ * @param a_name The name of the category to retrieve.
+ **/
+LOG4C_API log4c_category_t* log4c_category_get(const char* a_name);
+
+/**
+ * Fill in an array with the log4c categories.
+ *
+ * @param a_cats array of categories that will be filled
+ * @param a_ncats number of categories in the array
+ *
+ * @returns -1 if it fails or the number of available categories in
+ * log4c.
+ **/
+LOG4C_API int log4c_category_list(log4c_category_t** a_cats, int a_ncats);
+
+/**
+ * Constructor for a log4c_category_t.
+ *
+ * @param a_name the category name
+ * @returns a log4c_category object
+ * @warning this method should not be called directly. You should use the
+ * log4c_category_get() method in order to preserve the categories
+ * hierarchy.
+ **/
+LOG4C_API log4c_category_t* log4c_category_new(const char* a_name);
+
+/**
+ * Destructor for a log4c_category_t.
+ *
+ * @param a_category the log4c_category_t object
+ **/
+LOG4C_API void log4c_category_delete(log4c_category_t* a_category);
+
+/**
+ * Return the category name.
+ * @param a_category the log4c_category_t object
+ * @returns the category name.
+ */       
+LOG4C_API const char* log4c_category_get_name(const log4c_category_t* a_category);
+
+/**
+ * Returns the Appender for this log4c_category_t, or NULL if no Appender has
+ * been set.
+ * @param a_category the log4c_category_t object
+ * @returns The Appender.
+ **/
+LOG4C_API const struct __log4c_appender* log4c_category_get_appender(
+    const log4c_category_t* a_category);
+
+/**
+ * Get the additivity flag for this log4c_category_t..
+ *
+ * @param a_category the log4c_category_t object
+ * @return the category additivity
+ **/
+LOG4C_API int log4c_category_get_additivity(const log4c_category_t* a_category);
+
+/**
+ * Returns the assigned Priority, if any, for this log4c_category_t.
+ * @param a_category the log4c_category_t object
+ * @return Priority - the assigned Priority, can be LOG4C_PRIORITY_NOTSET
+ **/
+LOG4C_API int log4c_category_get_priority(const log4c_category_t* a_category);
+
+/**
+ * Starting from this category, search the category hierarchy for a set
+ * priority and return it. Otherwise, return the priority of the root
+ * category.
+ *
+ * @param a_category the log4c_category_t object
+ *
+ * @todo the log4c_category_t is designed so that this method executes as
+ * quickly as possible. It could even be faster if the set priority was
+ * propagated through the children hierarchy of a category.
+ **/
+LOG4C_API int log4c_category_get_chainedpriority(const log4c_category_t* a_category);
+
+/**
+ * Sets a new appender for this category.
+ *
+ * @param a_category the log4c_category_t object
+ * @param a_appender the new category appender
+ * @return the previous category appender
+ **/
+LOG4C_API const struct __log4c_appender* log4c_category_set_appender(
+    log4c_category_t* a_category,
+    struct __log4c_appender* a_appender);
+/**
+ * Sets a new priority of this category.
+ *
+ * @param a_category the log4c_category_t object
+ * @param a_priority the new priority to set. Use LOG4C_PRIORITY_NOTSET to
+ * let the category use its parents priority as effective priority.
+ * @return the previous category priority
+ **/
+LOG4C_API int log4c_category_set_priority(log4c_category_t* a_category,
+                                       int a_priority);
+
+/**
+ * Sets a new additivity flag for this category.
+ *
+ * @param a_category the log4c_category_t object
+ * @param a_additivity the new category additivity
+ * @return the previous category additivity
+ **/
+LOG4C_API int log4c_category_set_additivity(log4c_category_t* a_category,
+                                         int a_additivity);
+/**
+ * prints the log4c_category_t object on a stream
+ *
+ * @param a_category the log4c_category_t object
+ * @param a_stream The stream
+ **/ 
+LOG4C_API void log4c_category_print(const log4c_category_t* a_category, FILE* a_stream); 
+
+/** 
+ * Returns true if the chained priority of the log4c_category_t is equal to
+ * or higher than given priority.
+ * @param a_category the log4c_category_t object
+ * @param a_priority The priority to compare with.
+ * @returns whether logging is enable for this priority.
+ **/
+#if !defined(_WIN32) && !defined(__HP_cc)
+static inline int log4c_category_is_priority_enabled(const log4c_category_t* a_category,
+						     int a_priority)
+{
+    return log4c_category_get_chainedpriority(a_category) >= a_priority;
+}
+#else
+#define log4c_category_is_priority_enabled(a,b) \
+  (log4c_category_get_chainedpriority(a) >= b)
+#endif
+
+/**
+ * Return true if the category will log messages with priority @c
+ * LOG4C_PRIORITY_FATAL.
+ *
+ * @param a_category the log4c_category_t object
+ * @returns Whether the category will log.
+ **/ 
+#if !defined(_WIN32) && !defined(__HP_cc)
+static inline int log4c_category_is_fatal_enabled(const log4c_category_t* a_category)
+{	
+  return log4c_category_is_priority_enabled(a_category, LOG4C_PRIORITY_FATAL);
+}
+#else
+#define log4c_category_is_fatal_enabled(a)  \
+  (log4c_category_is_priority_enabled(a,LOG4C_PRIORITY_FATAL))
+#endif
+ 
+/**
+ * Return true if the category will log messages with priority @c
+ * LOG4C_PRIORITY_ALERT.
+ *
+ * @param a_category the log4c_category_t object
+ * @returns Whether the category will log.
+ **/ 
+#if !defined(_WIN32) && !defined(__HP_cc)
+static inline int log4c_category_is_alert_enabled(const log4c_category_t* a_category) 
+{	
+    return log4c_category_is_priority_enabled(a_category, LOG4C_PRIORITY_ALERT); 
+}
+#else
+#define log4c_category_is_alert_enabled(a) \
+  (log4c_category_is_priority_enabled(a,LOG4C_PRIORITY_ALERT))
+#endif
+ 
+/**
+ * Return true if the category will log messages with priority @c
+ * LOG4C_PRIORITY_CRIT.
+ *
+ * @param a_category the log4c_category_t object
+ * @returns Whether the category will log.
+ **/ 
+#if !defined(_WIN32) && !defined(__HP_cc)
+static inline int log4c_category_is_crit_enabled(const log4c_category_t* a_category) 
+{	
+    return log4c_category_is_priority_enabled(a_category, LOG4C_PRIORITY_CRIT); 
+}
+#else
+#define log4c_category_is_crit_enabled(a) \
+  (log4c_category_is_priority_enabled(a, LOG4C_PRIORITY_CRIT))
+#endif
+ 
+/**
+ * Return true if the category will log messages with priority @c
+ * LOG4C_PRIORITY_ERROR.
+ *
+ * @param a_category the log4c_category_t object
+ * @returns Whether the category will log.
+ **/ 
+#if !defined(_WIN32) && !defined(__HP_cc)
+static inline int log4c_category_is_error_enabled(const log4c_category_t* a_category) 
+{	
+    return log4c_category_is_priority_enabled(a_category, LOG4C_PRIORITY_ERROR); 
+}
+#else
+#define log4c_category_is_error_enabled(a) \
+  (log4c_category_is_priority_enabled(a, LOG4C_PRIORITY_ERROR))
+#endif
+ 
+/**
+ * Return true if the category will log messages with priority @c
+ * LOG4C_PRIORITY_WARN.
+ *
+ * @param a_category the log4c_category_t object
+ * @returns Whether the category will log.
+ **/ 
+#if !defined(_WIN32) && !defined(__HP_cc)
+static inline int log4c_category_is_warn_enabled(const log4c_category_t* a_category) 
+{	
+    return log4c_category_is_priority_enabled(a_category, LOG4C_PRIORITY_WARN); 
+}
+#else
+#define log4c_category_is_warn_enabled(a) \
+  log4c_category_is_warn_enabled(a) \
+    (log4c_category_is_priority_enabled(a, LOG4C_PRIORITY_WARN))
+#endif
+ 
+/**
+ * Return true if the category will log messages with priority @c
+ * LOG4C_PRIORITY_NOTICE.
+ *
+ * @param a_category the log4c_category_t object
+ * @returns Whether the category will log.
+ **/ 
+#if !defined(_WIN32) && !defined(__HP_cc)
+static inline int log4c_category_is_notice_enabled(const log4c_category_t* a_category) 
+{	
+    return log4c_category_is_priority_enabled(a_category, LOG4C_PRIORITY_NOTICE); 
+}
+#else 
+#define log4c_category_is_notice_enabled(a) \
+  (log4c_category_is_priority_enabled(a, LOG4C_PRIORITY_NOTICE))
+#endif
+ 
+/**
+ * Return true if the category will log messages with priority @c
+ * LOG4C_PRIORITY_INFO.
+ *
+ * @param a_category the log4c_category_t object
+ * @returns Whether the category will log.
+ **/ 
+#if !defined(_WIN32) && !defined(__HP_cc)
+static inline int log4c_category_is_info_enabled(const log4c_category_t* a_category) 
+{	
+    return log4c_category_is_priority_enabled(a_category, LOG4C_PRIORITY_INFO); 
+}
+#else
+#define log4c_category_is_info_enabled(a) \
+  (log4c_category_is_priority_enabled(a, LOG4C_PRIORITY_INFO))
+#endif
+ 
+/**
+ * Return true if the category will log messages with priority @c
+ * LOG4C_PRIORITY_DEBUG.
+ *
+ * @param a_category the log4c_category_t object
+ * @returns Whether the category will log.
+ **/ 
+#if !defined(_WIN32) && !defined(__HP_cc)
+static inline int log4c_category_is_debug_enabled(const log4c_category_t* a_category) 
+{	
+    return log4c_category_is_priority_enabled(a_category, LOG4C_PRIORITY_DEBUG); 
+}
+#else
+#define log4c_category_is_debug_enabled(a) \
+  (log4c_category_is_priority_enabled(a, LOG4C_PRIORITY_DEBUG))
+#endif
+ 
+/**
+ * Return true if the category will log messages with priority @c
+ * LOG4C_PRIORITY_TRACE.
+ *
+ * @param a_category the log4c_category_t object
+ * @returns Whether the category will log.
+ **/ 
+#if !defined(_WIN32) && !defined(__HP_cc)
+static inline int log4c_category_is_trace_enabled(const log4c_category_t* a_category) 
+{	
+    return log4c_category_is_priority_enabled(a_category, LOG4C_PRIORITY_TRACE); 
+}
+#else
+#define log4c_category_is_trace_enabled(a) \
+  (log4c_category_is_priority_enabled(a, LOG4C_PRIORITY_TRACE))
+#endif
+ 
+/**
+ * @internal
+ **/
+LOG4C_API void __log4c_category_vlog(const log4c_category_t* a_category, 
+				  const log4c_location_info_t* a_locinfo, 
+				  int a_priority,
+				  const char* a_format, 
+				  va_list a_args);
+
+/**
+ * @internal
+**/
+LOG4C_API void __log4c_category_vlog_no_file_num_no_layout(
+	const log4c_category_t* a_category, 
+	const log4c_location_info_t* a_locinfo, 
+	int a_priority,
+	const char* a_format, 
+	va_list a_args);
+
+
+/**
+ * @internal
+ *
+ * @bug the log4c_location_info_t object is not set correctly. A macro is
+ * needed.
+ **/
+
+/* msvc doesn't allow "inline" nor variable args in a macro
+ * so cannot #define these ones.
+ */
+
+static LOG4C_INLINE void log4c_category_vlog(const log4c_category_t* a_category, 
+				       int a_priority,
+				       const char* a_format, 
+				       va_list a_args)
+{
+    const log4c_location_info_t locinfo = LOG4C_LOCATION_INFO_INITIALIZER(NULL);
+
+    __log4c_category_vlog(a_category, &locinfo, a_priority, a_format, a_args);
+}
+
+/** 
+* @internal
+*
+* @bug the log4c_location_info_t object is not set correctly. A macro is
+* needed.
+**/
+
+/* msvc doesn't allow "inline" nor variable args in a macro
+* so cannot #define these ones.
+*/
+
+static LOG4C_INLINE void log4c_category_vlog_no_file_num_no_layout(const log4c_category_t* a_category, 
+																   int a_priority,
+																   const char* a_format, 
+																   va_list a_args)
+{
+	const log4c_location_info_t locinfo = LOG4C_LOCATION_INFO_INITIALIZER(NULL);
+
+	__log4c_category_vlog_no_file_num_no_layout(a_category, &locinfo, a_priority, a_format, a_args);
+}
+
+
+/** 
+ * Log a message with the specified priority.
+ * @param a_category the log4c_category_t object
+ * @param a_priority The priority of this log message.
+ * @param a_format Format specifier for the string to write 
+ * in the log file.
+ * @param ... The arguments for a_format 
+ **/  
+static LOG4C_INLINE void log4c_category_log(const log4c_category_t* a_category,
+				      int a_priority,
+				      const char* a_format,
+				      ...)
+{
+    if (log4c_category_is_priority_enabled(a_category, a_priority)) {
+	va_list va;
+	va_start(va, a_format);
+	log4c_category_vlog(a_category, a_priority, a_format, va);
+	va_end(va);
+    }
+}
+
+/** 
+ * Log a message with the specified priority and a user location info.
+ * @param a_category the log4c_category_t object
+ * @param a_locinfo a user  location info
+ * @param a_priority The priority of this log message.
+ * @param a_format Format specifier for the string to write 
+ * in the log file.
+ * @param ... The arguments for a_format 
+ **/  
+static LOG4C_INLINE void log4c_category_log_locinfo(
+	const log4c_category_t* a_category,
+	const log4c_location_info_t* a_locinfo, 
+	int a_priority,
+	const char* a_format,
+	...)
+{
+	if (log4c_category_is_priority_enabled(a_category, a_priority)) {
+		va_list va;
+		va_start(va, a_format);
+		__log4c_category_vlog(a_category, a_locinfo, a_priority, a_format, va);
+		va_end(va);
+	}
+}
+
+/** 
+ * Log a message with fatal priority.
+ * @param a_category the log4c_category_t object
+ * @param a_format Format specifier for the string to write 
+ * in the log file.
+ * @param ... The arguments for a_format 
+ **/  
+static LOG4C_INLINE void log4c_category_fatal(const log4c_category_t* a_category,
+					const char* a_format,
+					...)
+{
+    if (log4c_category_is_priority_enabled(a_category, LOG4C_PRIORITY_FATAL)) {
+	va_list va;
+	va_start(va, a_format);
+	log4c_category_vlog(a_category, LOG4C_PRIORITY_FATAL, a_format, va);
+	va_end(va);
+    }
+}
+
+/** 
+ * Log a message with alert priority.
+ * @param a_category the log4c_category_t object
+ * @param a_format Format specifier for the string to write 
+ * in the log file.
+ * @param ... The arguments for a_format 
+ **/  
+static LOG4C_INLINE void log4c_category_alert(const log4c_category_t* a_category,
+					const char* a_format,
+					...)
+{
+    if (log4c_category_is_priority_enabled(a_category, LOG4C_PRIORITY_ALERT)) {
+	va_list va;
+	va_start(va, a_format);
+	log4c_category_vlog(a_category, LOG4C_PRIORITY_ALERT, a_format, va);
+	va_end(va);
+    }
+}
+
+/** 
+ * Log a message with crit priority.
+ * @param a_category the log4c_category_t object
+ * @param a_format Format specifier for the string to write 
+ * in the log file.
+ * @param ... The arguments for a_format 
+ **/  
+static LOG4C_INLINE void log4c_category_crit(const log4c_category_t* a_category,
+				       const char* a_format,
+				       ...)
+{
+    if (log4c_category_is_priority_enabled(a_category, LOG4C_PRIORITY_CRIT)) {
+	va_list va;
+	va_start(va, a_format);
+	log4c_category_vlog(a_category, LOG4C_PRIORITY_CRIT, a_format, va);
+	va_end(va);
+    }
+}
+
+/** 
+ * Log a message with error priority.
+ * @param a_category the log4c_category_t object
+ * @param a_format Format specifier for the string to write 
+ * in the log file.
+ * @param ... The arguments for a_format 
+ **/  
+static LOG4C_INLINE void log4c_category_error(const log4c_category_t* a_category,
+					const char* a_format,
+					...)
+{
+    if (log4c_category_is_priority_enabled(a_category, LOG4C_PRIORITY_ERROR)) {
+	va_list va;
+	va_start(va, a_format);
+	log4c_category_vlog(a_category, LOG4C_PRIORITY_ERROR, a_format, va);
+	va_end(va);
+    }
+}
+
+/** 
+ * Log a message with warn priority.
+ * @param a_category the log4c_category_t object
+ * @param a_format Format specifier for the string to write 
+ * in the log file.
+ * @param ... The arguments for a_format 
+ **/  
+static LOG4C_INLINE void log4c_category_warn(const log4c_category_t* a_category,
+				       const char* a_format,
+				       ...)
+{
+    if (log4c_category_is_priority_enabled(a_category, LOG4C_PRIORITY_WARN)) {
+	va_list va;
+	va_start(va, a_format);
+	log4c_category_vlog(a_category, LOG4C_PRIORITY_WARN, a_format, va);
+	va_end(va);
+    }
+}
+
+/** 
+ * Log a message with notice priority.
+ * @param a_category the log4c_category_t object
+ * @param a_format Format specifier for the string to write 
+ * in the log file.
+ * @param ... The arguments for a_format 
+ **/  
+static LOG4C_INLINE void log4c_category_notice(const log4c_category_t* a_category,
+					 const char* a_format,
+					 ...)
+{
+    if (log4c_category_is_priority_enabled(a_category, LOG4C_PRIORITY_NOTICE)) {
+	va_list va;
+	va_start(va, a_format);
+	log4c_category_vlog(a_category, LOG4C_PRIORITY_NOTICE, a_format, va);
+	va_end(va);
+    }
+}
+
+/** 
+ * Log a message with info priority.
+ * @param a_category the log4c_category_t object
+ * @param a_format Format specifier for the string to write 
+ * in the log file.
+ * @param ... The arguments for a_format 
+ **/  
+static LOG4C_INLINE void log4c_category_info(const log4c_category_t* a_category,
+				       const char* a_format,
+				       ...)
+{
+    if (log4c_category_is_priority_enabled(a_category, LOG4C_PRIORITY_INFO)) {
+	va_list va;
+	va_start(va, a_format);
+	log4c_category_vlog(a_category, LOG4C_PRIORITY_INFO, a_format, va);
+	va_end(va);
+    }
+}
+
+/** 
+ * Log a message with debug priority.
+ * @param a_category the log4c_category_t object
+ * @param a_format Format specifier for the string to write 
+ * in the log file.
+ * @param ... The arguments for a_format 
+ **/  
+static LOG4C_INLINE void log4c_category_debug(const log4c_category_t* a_category,
+					const char* a_format,
+					...)
+{
+    if (log4c_category_is_priority_enabled(a_category, LOG4C_PRIORITY_DEBUG)) {
+	va_list va;
+	va_start(va, a_format);
+	log4c_category_vlog(a_category, LOG4C_PRIORITY_DEBUG, a_format, va);
+	va_end(va);
+    }
+}
+
+/** 
+ * Log a message with trace priority.
+ * @param a_category the log4c_category_t object
+ * @param a_format Format specifier for the string to write 
+ * in the log file.
+ * @param ... The arguments for a_format 
+ **/  
+static LOG4C_INLINE void __log4c_category_trace(const log4c_category_t* a_category,
+					  const char* a_format,
+					  ...)
+{
+    if (log4c_category_is_priority_enabled(a_category, LOG4C_PRIORITY_TRACE)) {
+	va_list va;
+	va_start(va, a_format);
+	log4c_category_vlog(a_category, LOG4C_PRIORITY_TRACE, a_format, va);
+	va_end(va);
+    }
+}
+
+#ifdef __GNUC__
+
+#ifdef OLD_VARIADIC_MACRO
+
+#  define log4c_category_trace(a_category, a_format, args...) \
+    __log4c_category_trace(a_category, log4c_location "\n" a_format, ##args )
+
+#else
+
+#  define log4c_category_trace(a_category, a_format, ...) \
+    __log4c_category_trace(a_category, log4c_location "\n" a_format, ##__VA_ARGS__ )
+
+#endif /* OLD_VARIADIC_MACRO */
+
+
+#else
+#  define log4c_category_trace __log4c_category_trace
+#endif  /* __GNUC__ */
+
+/**
+ * Helper macro to define static categories.
+ *
+ * @param a_category the log4c_category_t pointer name
+ * @param a_name the category name
+ **/
+#ifdef __GNUC__
+#   define log4c_category_define(a_category, a_name) \
+    typedef log4c_category_t log4c_category_define_##a_category __attribute__((deprecated)); \
+    static log4c_category_define_##a_category* a_category  __attribute__ ((unused)) = NULL;
+#else
+#   define log4c_category_define(a_category, a_name)
+#endif
+
+/**
+ * @internal
+ **/
+struct __sd_factory;
+LOG4C_API struct __sd_factory* log4c_category_factory;
+
+__LOG4C_END_DECLS
+
+#endif

+ 41 - 0
scbc.tools/Log4C/log4c/config-win32.h

@@ -0,0 +1,41 @@
+/* $Id$
+ *
+ * See the COPYING file for the terms of usage and distribution.
+ */
+
+/* This file defines some labels as required for
+   compiling with Microsoft Visual C++ 6
+*/
+
+#ifndef __log4c_config_win32_h
+#define __log4c_config_win32_h
+
+#include <time.h>
+#include <winsock2.h>
+
+#undef LOG4C_API
+#ifdef LOG4C_EXPORTS
+#    define LOG4C_API         __declspec(dllexport)
+#else
+#    define LOG4C_API       extern __declspec(dllimport)
+#endif
+
+#undef LOG4C_DATA
+#ifdef LOG4C_EXPORTS
+#    define LOG4C_DATA        __declspec(dllexport)
+#else
+#    define LOG4C_DATA       extern __declspec(dllimport)
+#endif
+
+
+/* This is defined to be 'inline' by default,
+   but with msvc6 undef it so that inlined
+   functions are just normal functions.
+*/
+#undef LOG4C_INLINE
+#define LOG4C_INLINE
+
+#define WITH_ROLLINGFILE 1
+
+
+#endif /* __log4c_config_win32_h */

+ 26 - 0
scbc.tools/Log4C/log4c/config.h

@@ -0,0 +1,26 @@
+/************** Begin of config.h *******************************************/
+
+/* $Id$
+*
+* config.h created by wenhm in 2006-11-9
+*
+* Copyright 2001-2002, Meiosys (www.meiosys.com). All rights reserved.
+*
+* See the COPYING file for the terms of usage and distribution.
+*/
+
+#ifndef log4c_config_h
+#define log4c_config_h
+
+
+///#ifdef _WIN32
+#define LOG4C_RCPATH	"."
+#define VERSION			"1.2.1"
+///#endif
+
+#define WITH_ROLLINGFILE 1
+#endif
+
+
+
+/************** End of config.h *******************************************/

+ 46 - 0
scbc.tools/Log4C/log4c/defs.h

@@ -0,0 +1,46 @@
+/* $Id$
+ *
+ * Copyright 2001-2003, Meiosys (www.meiosys.com). All rights reserved.
+ *
+ * See the COPYING file for the terms of usage and distribution.
+ */
+
+#ifndef __log4c_defs_h
+#define __log4c_defs_h
+
+/**
+ * @file defs.h
+ *
+ * @brief types and declarations enclosures for C++.
+ *
+ **/   
+
+#ifdef  __cplusplus
+# define __LOG4C_BEGIN_DECLS  extern "C" {
+# define __LOG4C_END_DECLS    }
+#else
+# define __LOG4C_BEGIN_DECLS
+# define __LOG4C_END_DECLS
+#endif
+
+#define LOG4C_INLINE inline
+#define LOG4C_API    extern
+#define LOG4C_DATA    extern
+
+#ifdef __HP_cc
+#define inline __inline
+#endif
+
+#ifdef _WIN32
+# include <log4c/config-win32.h>
+#endif
+
+#ifndef GCC_VERSION
+#define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
+#endif /* GCC_VERSION */
+
+#if GCC_VERSION < 2009
+#define OLD_VARIADIC_MACRO 1
+#endif
+
+#endif /* __log4c_defs_h */

+ 65 - 0
scbc.tools/Log4C/log4c/init.h

@@ -0,0 +1,65 @@
+/* $Id$
+ *
+ * Copyright 2001-2003, Meiosys (www.meiosys.com). All rights reserved.
+ *
+ * See the COPYING file for the terms of usage and distribution.
+ */
+
+#ifndef __log4c_init_h
+#define __log4c_init_h
+
+#include <log4c/defs.h>
+#include <stdio.h>
+
+/**
+ * @file init.h
+ *
+ * @brief log4c constructors and destructors
+ *
+ **/   
+
+/**
+ * constructor
+ * 
+ * @returns 0 for success 
+ **/
+LOG4C_API int log4c_init(void);
+
+/**
+* another constructor
+* 
+* 带有配置文件名的初始化函数
+* 完成功能和log4c_init完全一致,只是这里的配置文件名以参数形式传入的
+* @returns 0 for success .
+* 作者:jesse 日期:2008-9-6
+*/
+LOG4C_API int log4c_init_with_cfg_file(const char *strCfgFileName);
+
+/**
+ * destructor
+ *
+ * @returns 0 for success 
+ **/
+LOG4C_API int log4c_fini(void);
+
+/*
+ * Dumps all the current appender, layout and rollingpolicy types
+ * known by log4c.
+ * @param stream to write to
+ */
+LOG4C_API void log4c_dump_all_types(FILE *fp);
+
+/*
+ * Dumps all the current instances of categories, appenders, layouts
+ * and rollingpolicy objects.
+ * An instances of a type consists of the base
+ * type information (name plus function table) and an instance name and
+ * configuration.  For example one can have an instance of the rollingfile
+ * appender which logs to /var/tmp and another instance which logs to 
+ * /usr/tmp.  They are both of type rollingfile, but are distinct instances of
+ * it
+ * @param stream to write t
+ */
+LOG4C_API void log4c_dump_all_instances(FILE *fp);
+
+#endif

+ 204 - 0
scbc.tools/Log4C/log4c/layout.h

@@ -0,0 +1,204 @@
+/* $Id$
+ *
+ * layout.h
+ * 
+ * Copyright 2001-2003, Meiosys (www.meiosys.com). All rights reserved.
+ *
+ * See the COPYING file for the terms of usage and distribution.
+ */
+
+#ifndef log4c_layout_h
+#define log4c_layout_h
+
+/**
+ * @file layout.h
+ *
+ * @brief Interface for user specific layout format of log4c_logging_event
+ * events. 
+ *
+ * @todo the layout interface needs a better configuration system
+ * depending on the layout type. The udata field is a just a trick.
+ *
+ * @todo a pattern layout would be welcomed !!
+ **/
+
+#include <log4c/defs.h>
+#include <log4c/logging_event.h>
+#include <stdio.h>
+
+__LOG4C_BEGIN_DECLS
+
+struct __log4c_layout;
+
+/**
+ * log4c layout class 
+ **/
+typedef struct __log4c_layout log4c_layout_t;
+
+/**
+ * @brief log4c layout type class
+ *
+ * Attributes description:
+ * 
+ * @li @c name layout type name 
+ * @li @c format 
+ **/
+typedef struct log4c_layout_type {
+    const char* name;
+    const char* (*format) (const log4c_layout_t*, const log4c_logging_event_t*);
+} log4c_layout_type_t;
+
+/**
+ * Get a pointer to an existing layout type.
+ *
+ * @param a_name the name of the layout type to return.  
+ * @returns a pointer to an existing layout type, or NULL if no layout
+ * type with the specified name exists.
+ **/
+LOG4C_API const log4c_layout_type_t* log4c_layout_type_get(const char* a_name);
+
+/**
+ * Use this function to register a layout type with log4c.
+ * Once this is done you may refer to this type by name both 
+ * programatically and in the log4c configuration file.
+ *
+ * @param a_type a pointer to the new layout type to set.
+ * @returns a pointer to the previous layout type of same name.
+ *
+ * Example code fragment: 
+ * @code
+ * 
+ * const log4c_layout_type_t log4c_layout_type_xml = {
+ *    "s13_xml",
+ *    xml_format,
+ * };
+ *  
+ * log4c_layout_type_set(&log4c_layout_type_xml);
+ *
+ * @endcode
+ **/
+LOG4C_API const log4c_layout_type_t* log4c_layout_type_set(
+    const log4c_layout_type_t* a_type);
+
+/**
+ * Get a pointer to an existing layout.
+ *
+ * @param a_name the name of the layout to return.
+ * @returns a pointer to an existing layout, or NULL if no layout
+ * with the specfied name exists.
+ **/
+LOG4C_API log4c_layout_t* log4c_layout_get(const char* a_name);
+
+/**
+ * Constructor for layout. 
+ **/
+LOG4C_API log4c_layout_t* log4c_layout_new(const char* a_name);
+
+/**
+ * Destructor for layout.
+ **/
+LOG4C_API void log4c_layout_delete(log4c_layout_t* a_layout);
+
+/**
+ * @param a_layout the log4c_layout_t object
+ * @return the layout name
+ **/
+LOG4C_API const char* log4c_layout_get_name(const log4c_layout_t* a_layout);
+
+/**
+ * @param a_layout the log4c_layout_t object
+ * @return a log4c_layout_type_t object
+ **/
+LOG4C_API const log4c_layout_type_t* log4c_layout_get_type(
+    const log4c_layout_t* a_layout);
+
+/**
+ * sets the layout type
+ *
+ * @param a_layout the log4c_layout_t object
+ * @param a_type the new layout type
+ * @return the previous layout type
+ *
+ **/
+LOG4C_API const log4c_layout_type_t* log4c_layout_set_type(
+    log4c_layout_t* a_layout,
+    const log4c_layout_type_t* a_type);
+
+/**
+ * @param a_layout the log4c_layout_t object
+ * @return the layout user data
+ **/
+LOG4C_API void* log4c_layout_get_udata(const log4c_layout_t* a_layout);
+
+/**
+ * sets the layout user data
+ *
+ * @param a_layout the log4c_layout_t object
+ * @param a_udata the new layout user data
+ * @return the previous layout user data
+ **/
+LOG4C_API void* log4c_layout_set_udata(log4c_layout_t*	a_layout, 
+				    void*		a_udata);
+/**
+ * format a log4c_logging_event events to a string.
+ *
+ * @param a_layout the log4c_layout_t object
+ * @param a_event a logging_event_t object
+ * @returns an appendable string.
+ **/
+LOG4C_API const char* log4c_layout_format(
+    const log4c_layout_t*		a_layout,
+    const log4c_logging_event_t*	a_event);
+
+/**
+ * prints the layout on a stream
+ * @param a_layout the log4c_layout_t object
+ * @param a_stream the stream
+ **/
+LOG4C_API void log4c_layout_print(
+    const log4c_layout_t* a_layout, FILE* a_stream);
+
+/**
+ * prints all the current registered layout types on a stream
+ *
+ * @param fp the stream
+ **/                            
+LOG4C_API void log4c_layout_types_print(FILE *fp);
+
+/** 删除本layout.c文件中定义的全局和静态的指针指向的内存,防止内存泄漏
+如:
+1.gs_types.
+2.
+@return void.
+作者:jesse 日期:2008.09.08
+*/
+LOG4C_API void log4c_layout_delete_global();
+
+
+/**
+ * Helper macro to define static layout types.
+ *
+ * @param a_type the log4c_layout_type_t object to define
+ * @warning needs GCC support: otherwise this macro does nothing
+ * @deprecated This macro, and the static initialialization
+ * of layouts in general, is deprecated. Use rather
+ * the log4c_layout_type_set() function to initialize your appenders
+ * before calling log4c_init() 
+ **/
+#ifdef __GNUC__
+#   define log4c_layout_type_define(a_type) \
+    typedef int log4c_layout_type_define_##a_type __attribute__((deprecated)); \
+    static log4c_layout_type_define_##a_type __unsused_var __attribute__((unused));
+#else
+#   define log4c_layout_type_define(a_type)
+#endif
+
+/**
+ * @internal
+ **/
+struct __sd_factory;
+LOG4C_API struct __sd_factory* log4c_layout_factory;
+
+__LOG4C_END_DECLS
+
+#endif

+ 38 - 0
scbc.tools/Log4C/log4c/layout_type_basic.h

@@ -0,0 +1,38 @@
+/* $Id$
+ *
+ * layout_type_basic.h
+ * 
+ * Copyright 2001-2003, Meiosys (www.meiosys.com). All rights reserved.
+ *
+ * See the COPYING file for the terms of usage and distribution.
+ */
+
+#ifndef log4c_layout_type_basic_h
+#define log4c_layout_type_basic_h
+
+/**
+ * @file layout_type_basic.h
+ *
+ * @brief Implement a basic layout.
+ *
+ * In @c log4j.PatternLayout conventions, the basic layout has the following
+ * conversion pattern: @c "%P %c - %m\n".
+ *
+ * Where 
+ * @li @c "%P" is the priority of the logging event
+ * @li @c "%c" is the category of the logging event
+ * @li @c "%m" is the application supplied message associated with the
+ * logging event
+ * 
+ **/
+
+#include <log4c/defs.h>
+#include <log4c/layout.h>
+
+__LOG4C_BEGIN_DECLS
+
+extern const log4c_layout_type_t log4c_layout_type_basic;
+
+__LOG4C_END_DECLS
+
+#endif

+ 42 - 0
scbc.tools/Log4C/log4c/layout_type_basic_r.h

@@ -0,0 +1,42 @@
+		/************** Begin of layout_type_basic_r.h *******************************************/
+		/* $Id$
+		*
+		* layout_type_basic_r.h
+		*
+		* Copyright 2001-2003, Meiosys (www.meiosys.com). All rights reserved.
+		*
+		* See the COPYING file for the terms of usage and distribution.
+		*/
+
+#ifndef log4c_layout_type_basic_r_h
+#define log4c_layout_type_basic_r_h
+
+		/**
+		* @file layout_type_basic_r.h
+		*
+		* @brief Implement a basic_r layout.
+		*
+		* In @c log4j.PatternLayout conventions, the basic_r layout has the following
+		* conversion pattern: @c "%P %c - %m\n".
+		*
+		* Where
+		* @li @c "%P" is the priority of the logging event
+		* @li @c "%c" is the category of the logging event
+		* @li @c "%m" is the application supplied message associated with the
+		* logging event
+		*
+		**/
+
+#include <log4c/defs.h>
+#include <log4c/layout.h>
+
+		__LOG4C_BEGIN_DECLS
+
+		extern const log4c_layout_type_t log4c_layout_type_basic_r;
+
+	__LOG4C_END_DECLS
+
+#endif
+
+
+		/************** End of layout_type_basic_r.h *******************************************/

+ 43 - 0
scbc.tools/Log4C/log4c/layout_type_dated.h

@@ -0,0 +1,43 @@
+/* $Id$
+ *
+ * layout_type_dated.h
+ * 
+ * Copyright 2001-2003, Meiosys (www.meiosys.com). All rights reserved.
+ *
+ * See the COPYING file for the terms of usage and distribution.
+ */
+
+#ifndef log4c_layout_type_dated_h
+#define log4c_layout_type_dated_h
+
+/**
+ * @file layout_type_dated.h
+ *
+ * @brief Implement a dated layout.
+ *
+ * In @c log4j.PatternLayout conventions, the dated layout has the following
+ * conversion pattern: @c "%d %P %c - %m\n".
+ *
+ * Where 
+ * @li @c "%d" is the date of the logging event
+ * @li @c "%P" is the priority of the logging event
+ * @li @c "%c" is the category of the logging event
+ * @li @c "%m" is the application supplied message associated with the
+ * logging event
+ *
+ * 
+ * 
+ **/
+
+#include <log4c/defs.h>
+#include <log4c/layout.h>
+
+__LOG4C_BEGIN_DECLS
+
+extern const log4c_layout_type_t log4c_layout_type_dated;
+extern const log4c_layout_type_t log4c_layout_type_dated_r;
+extern const log4c_layout_type_t log4c_layout_type_dated_threadid;
+
+__LOG4C_END_DECLS
+
+#endif

+ 45 - 0
scbc.tools/Log4C/log4c/layout_type_dated_r.h

@@ -0,0 +1,45 @@
+/************** Begin of log4c/layout_type_dated_r.h *******************************************/
+/* $Id$
+*
+* layout_type_dated_r.h
+*
+* Copyright 2001-2003, Meiosys (www.meiosys.com). All rights reserved.
+*
+* See the COPYING file for the terms of usage and distribution.
+*/
+
+#ifndef log4c_layout_type_dated_r_h
+#define log4c_layout_type_dated_r_h
+
+/**
+* @file layout_type_dated_r.h
+*
+* @brief Implement a dated_r layout.
+*
+* In @c log4j.PatternLayout conventions, the dated_r layout has the following
+* conversion pattern: @c "%d %P %c - %m\n".
+*
+* Where
+* @li @c "%d" is the date of the logging event
+* @li @c "%P" is the priority of the logging event
+* @li @c "%c" is the category of the logging event
+* @li @c "%m" is the application supplied message associated with the
+* logging event
+*
+*
+*
+**/
+
+#include <log4c/defs.h>
+#include <log4c/layout.h>
+
+__LOG4C_BEGIN_DECLS
+
+extern const log4c_layout_type_t log4c_layout_type_dated_r;
+
+__LOG4C_END_DECLS
+
+#endif
+
+
+/************** End of log4c/layout_type_dated_r.h *******************************************/

+ 45 - 0
scbc.tools/Log4C/log4c/layout_type_dated_threadid.h

@@ -0,0 +1,45 @@
+/************** Begin of log4c/layout_type_dated_threadid.h *******************************************/
+/* $Id$
+*
+* layout_type_dated_threadid.h
+* 
+* Copyright 2001-2003, Meiosys (www.meiosys.com). All rights reserved.
+*
+* See the COPYING file for the terms of usage and distribution.
+*/
+
+#ifndef log4c_layout_type_dated_threadid_h
+#define log4c_layout_type_dated_threadid_h
+
+/**
+* @file layout_type_dated_threadid.h
+*
+* @brief Implement a dated layout.
+*
+* In @c log4j.PatternLayout conventions, the dated layout has the following
+* conversion pattern: @c "%d %P %c - %m\n".
+*
+* Where 
+* @li @c "%d" is the date of the logging event
+* @li @c "%P" is the priority of the logging event
+* @li @c "%c" is the category of the logging event
+* @li @c "%m" is the application supplied message associated with the
+* logging event
+*
+* 
+* 
+**/
+
+#include <log4c/defs.h>
+#include <log4c/layout.h>
+
+__LOG4C_BEGIN_DECLS
+
+extern const log4c_layout_type_t log4c_layout_type_dated_threadid;
+
+__LOG4C_END_DECLS
+
+#endif
+
+
+/************** End of log4c/layout_type_dated_threadid.h *******************************************/

+ 73 - 0
scbc.tools/Log4C/log4c/location_info.h

@@ -0,0 +1,73 @@
+/* $Id$
+ *
+ * location_info.h
+ * 
+ * Copyright 2001-2003, Meiosys (www.meiosys.com). All rights reserved.
+
+
+ * See the COPYING file for the terms of usage and distribution.
+ */
+
+#ifndef log4c_location_info_h
+#define log4c_location_info_h
+
+/**
+ * @file location_info.h
+ *
+ * @brief The internal representation of caller location information.
+ * 
+ * When a affirmative logging decision is made a log4c_location_info_t is
+ * created and is passed around the different log4c components.
+ **/
+
+///#include <log4c/defs.h>
+
+__LOG4C_BEGIN_DECLS
+
+/**
+ * @brief logging location information
+ *
+ * Attributes description:
+ * 
+ * @li @c loc_file file name
+ * @li @c loc_line file line
+ * @li @c loc_function function name
+ * @li @c loc_data user data
+ *
+ * @todo this is not used
+ **/
+typedef struct 
+{
+    const char* loc_file;
+    int loc_line;
+    const char* loc_function;
+    void* loc_data;
+
+} log4c_location_info_t;
+
+/**
+ * log4c_location_info_t initializer 
+ **/
+#ifdef __GNUC__
+#   define LOG4C_LOCATION_INFO_INITIALIZER(user_data) { __FILE__, __LINE__, __FUNCTION__, user_data }
+#else
+#   define LOG4C_LOCATION_INFO_INITIALIZER(user_data) { __FILE__, __LINE__, "(nil)", user_data }
+#endif
+
+#define __log4c_str(n) #n
+
+#ifdef __GNUC__
+#   define __log4c_location(n)	__FUNCTION__ "() at " __FILE__ ":" __log4c_str(n)
+#else
+#   define __log4c_location(n)	__FILE__ ":" __log4c_str(n)
+#endif
+
+/**
+ * This macro returns the literal representation of a logging event
+ * location
+ **/
+#define log4c_location __log4c_location(__LINE__)
+
+__LOG4C_END_DECLS
+
+#endif

+ 553 - 0
scbc.tools/Log4C/log4c/log.h

@@ -0,0 +1,553 @@
+/************** Begin of Log.h *******************************************/
+/************************************************************************
+ * Log.h
+ *
+ * edit by jesse in 2010-07-22
+ * 日志相关代码的头文件
+ ************************************************************************/
+#if !defined(LOG_H_INCLUDED_)
+#define LOG_H_INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+
+///用户不需要使用日志,不要定义LOG_USELOG4CXX和LOG4C_ENABLE宏命令就可以了
+#if !defined(LOG_USELOG4CXX) && !defined(LOG4C_ENABLE)
+
+#define LOG4C(X) 
+#define LOG4C_INIT()
+
+#define LOG4C_PARAM_CFG_FILE_NAME(strCfgFileName) 
+#define LOG4C_PARAM_LOG_LEVEL(strLogLevel) 
+#define LOG4C_PARAM_LOG_FILE_NAME(strLogFileName) 
+#define LOG4C_PARAM_LOG_FILE_SIZE(iFileSize) 
+#define LOG4C_PARAM_LOG_FILE_NUM(iFileNum)
+#define LOG4C_PARAM_REREAD_LOG_CFG_FILE(bReReadLogCfgFile)
+#define LOG4C_INIT_WITH_PARAM()
+#define LOG4C_INIT_WITH_PARAM_MULTI_PROCESS()
+
+#define LOG4C_FINI()
+#define LOG4C_INIT_DEFAULT()
+
+#define LOG4C_NO_FILENUM(X) 
+#define LOG4C_NO_FILENUM_NO_LAYOUT(X)
+#define LOG4C_ORIGIN LOG4C_NO_FILENUM_NO_LAYOUT
+#define LOG4C_BLOCK_BEGIN(X)
+#define LOG4C_BLOCK_END(X) 
+#define LOG4C_FUN(X) 
+#define LOG4C_IF(X)
+#define LOG4C_LINE()
+#define LOG4C_HEX_DUMP(X)
+#define LOG4C_RETURN(X)
+#define LOG4C_RETURN_WITH_VALUE(X, reurnValue)
+
+#else
+
+#include <stdlib.h>
+
+/**日志记录模块初始化宏定义
+注意事项: 必须初始化日志模块后才能正确记录日志
+本初始化不要求应用程序所在目录有日志配置文件log4crc,会自动生成一个缺省的log4crc文件
+使用例子: LOG4C_INIT_DEFAULT();
+作者:Jesse  日期:2010-07-22
+*/
+#define LOG4C_INIT_DEFAULT() \
+	log_init_with_string("", "")
+
+/**日志记录模块初始化宏定义
+注意事项: 必须初始化日志模块后才能正确记录日志
+本初始化要求应用程序所在目录有日志配置文件log4crc才行
+使用例子: LOG4C_INIT();
+作者:Jesse  日期:2010-07-22
+*/
+#define LOG4C_INIT() \
+	log_init()
+
+/************************************************************************
+下面的为通过设置参数设置日志模块参数的宏定义(功能和LOG4C_INIT和LOG4C_INIT_DEFAULT类似):
+1.必须先调用LOG_PARAM_XXXX系列宏定义设置参数,
+1.1.如设置日志记录级别、生成日志文件名等。
+1.2.若不LOG_PARAM_XXXX系列宏定义则将使用默认设置参数。
+2.然后调用LOG_INIT_WITH_PARAM宏定义来初始化日志模块。
+3.此时就可以记录日志了。
+*/
+#define LOG4C_PARAM_CFG_FILE_NAME(strCfgFileName) \
+	log_set_log_cfg_file_name(strCfgFileName)
+
+#define LOG4C_PARAM_LOG_LEVEL(strLogLevel) \
+	log_set_log_level(strLogLevel)
+
+#define LOG4C_PARAM_LOG_FILE_NAME(strLogFileName) \
+	log_set_log_file_name(strLogFileName)
+
+#define LOG4C_PARAM_LOG_FILE_SIZE(iFileSize) \
+	log_set_log_file_size(iFileSize)
+
+#define LOG4C_PARAM_LOG_FILE_NUM(iFileNum) \
+	log_set_log_file_num(iFileNum)
+
+#define LOG4C_PARAM_REREAD_LOG_CFG_FILE(bReReadLogCfgFile) \
+	log_set_reread_log_cfg_file(bReReadLogCfgFile)
+
+#define LOG4C_INIT_WITH_PARAM() \
+	log_init_with_param()
+
+#define LOG4C_INIT_WITH_PARAM_MULTI_PROCESS() \
+	log_init_with_param_multi_process()
+
+/************************************************************************/
+
+/**日志记录模块结束宏定义
+注意事项: 必须正确结束日志模块后才不会造成内存、资源泄漏
+使用例子: LOG4C_FINI();
+作者:Jesse  日期:2010-07-22
+*/
+#define LOG4C_FINI() \
+	log_fini()
+
+///进行LOG宏定义参数获取的结果
+typedef struct __LOG_PARAM
+{
+	char strMsg[LOG4C_BUFFER_SIZE_DEFAULT];
+	int iPriority;
+
+	///LOG4C_IF时的条件参数
+	int iCondition;
+
+	///LOG4C_HEX_DUMP时的参数
+	char *strHexBuf;
+	int iHexBufLen;
+}LOG_PARAM;
+
+#define LOG4C(X) \
+{ \
+	const LOG_PARAM log_param = log_vsprintf_wrapper X; \
+	log_msg( __FILE__, __LINE__, DEFAULT_LOG_CATEGORY_NAME, log_param.iPriority, log_param.strMsg ); \
+}
+
+#define LOG4C_NO_FILENUM(X) \
+{ \
+	const LOG_PARAM log_param = log_vsprintf_wrapper X; \
+	log_msg_no_file_num( DEFAULT_LOG_CATEGORY_NAME, log_param.iPriority, log_param.strMsg );  \
+}
+
+#define LOG4C_NO_FILENUM_NO_LAYOUT(X) \
+{ \
+	const LOG_PARAM log_param = log_vsprintf_wrapper X; \
+	log_msg_no_file_num_no_layout( DEFAULT_LOG_CATEGORY_NAME, log_param.iPriority, log_param.strMsg ); \
+}
+
+#define LOG4C_ORIGIN LOG4C_NO_FILENUM_NO_LAYOUT
+
+#define LOG4C_BLOCK_BEGIN(X) \
+{ \
+	const LOG_PARAM log_param = log_vsnprintf_wrapper_msg X; \
+	log4c_block_begin(__FILE__, __LINE__, log_param.strMsg); \
+}
+
+#define LOG4C_BLOCK_END(X) \
+{	\
+	const LOG_PARAM log_param = log_vsnprintf_wrapper_msg X; \
+	log4c_block_end(__FILE__, __LINE__, log_param.strMsg); \
+}
+
+#define LOG4C_FUN(X) \
+{ \
+	const LOG_PARAM log_param = log_vsnprintf_wrapper_msg X; \
+	log_msg_func(__FILE__, __FUNCTION__, __LINE__, DEFAULT_LOG_CATEGORY_NAME, LOG4C_PRIORITY_TRACE, log_param.strMsg ); \
+}
+
+/** Output trace on condition.
+This macro outputs a trace of any information needed, using standard stream
+output operators. The output is only made if the conditional is TRUE. 
+example: LOG4C_IF((4>3, LOG4C_PRIORITY_TRACE, "HELLO"));
+*/
+#define LOG4C_IF(X) \
+{ \
+	const LOG_PARAM log_param = log_condition_vsnprintf_wrapper X; \
+	if( log_param.iCondition ) {\
+		log_msg( \
+			__FILE__, \
+			__LINE__, \
+			DEFAULT_LOG_CATEGORY_NAME, \
+			log_param.iPriority, \
+			log_param.strMsg\
+		); 	\
+	}\
+}
+
+/** Trace the execution of a line.
+This macro outputs a trace of a source file line execution.
+*/
+#define LOG4C_LINE() \
+{ \
+	char strBuffer[128] = {0}; \
+	snprintf(strBuffer, sizeof(strBuffer), "line:%d", __LINE__); \
+	log_msg( \
+		__FILE__, \
+		__LINE__, \
+		DEFAULT_LOG_CATEGORY_NAME, \
+		LOG4C_PRIORITY_TRACE, \
+		strBuffer \
+		); \
+}
+
+/**将内存中数据以十六进制方式打印出来的一个宏定义
+example:LOG4C_HEX_DUMP((LOG4C_PRIORITY_TRACE, strHexBuf, iHexBufLen));
+作者:Jesse 日期:2010-07-22
+*/
+#define LOG4C_HEX_DUMP(X)	\
+{	\
+	log_hex_dump_vsnprintf_wrapper X; \
+}
+
+/** 输出文件名和行号的日志输出宏,记录完日志直接return
+然后再输入到LOG宏定义中
+作者:Jesse 日期:2010-07-22
+*/ 
+#define LOG4C_RETURN(X) \
+{ \
+	LOG4C(X); \
+	return; \
+}
+
+/** 输出文件名和行号的日志输出宏,记录完日志直接return returnValue;
+然后再输入到LOG宏定义中
+example:LOG4C_RETURN_WITH_VALUE(( LOG4C_PRIORITY_TRACE, "message%d", 1), returnValue);
+作者:Jesse 日期:2010-07-22
+*/ 
+#define LOG4C_RETURN_WITH_VALUE(X, returnValue) \
+{ \
+	LOG4C(X); \
+	return returnValue; \
+}
+
+#endif ///!defined(LOG_USELOG4CXX) 	&& 	!defined(LOG4C_ENABLE)
+
+#if ((defined(LOG_USELOG4CXX) && defined(__cplusplus)) || defined(LOG4C_ENABLE)) 
+
+#ifdef _WIN32
+///log4c正确使用必须的一些宏定义
+#define snprintf _snprintf
+
+#ifndef HAVE_CONFIG_H
+	#define HAVE_CONFIG_H
+#endif
+///#define LOG4C_EXPORTS
+#endif
+
+///定义linux下使用到而不存在的类型
+#ifdef linux
+	///typedef int BOOL;
+#ifndef BOOL 
+	#define BOOL int
+	#define FALSE 0
+	#define TRUE 1
+#endif
+	#define sprintf_s snprintf
+	///#define strcpy_s strncpy
+#endif
+
+
+/// 日志输出缺省category
+#ifndef DEFAULT_LOG_CATEGORY_NAME
+	#define DEFAULT_LOG_CATEGORY_NAME "root"
+#endif
+
+/** 日志记录级别
+*/
+/** fatal */	#define LOG_FATAL		LOG4C_PRIORITY_FATAL	
+/** alert */	#define LOG_ALERT		LOG4C_PRIORITY_ALERT	
+/** crit */	    #define LOG_CRIT		LOG4C_PRIORITY_CRIT		
+/** error */	#define LOG_ERROR		LOG4C_PRIORITY_ERROR	
+/** warn */	    #define LOG_WARN		LOG4C_PRIORITY_WARN		
+/** notice */	#define LOG_NOTICE		LOG4C_PRIORITY_NOTICE	
+/** info */	    #define LOG_INFO		LOG4C_PRIORITY_INFO		
+/** debug */	#define LOG_DEBUG		LOG4C_PRIORITY_DEBUG	
+/** trace */	#define LOG_TRACE		LOG4C_PRIORITY_TRACE	
+/** notset */	#define LOG_NOTSET		LOG4C_PRIORITY_NOTSET	
+/** unknown */	#define LOG_UNKNOWN		LOG4C_PRIORITY_UNKNOWN
+
+#include <log4c/defs.h>
+
+__LOG4C_BEGIN_DECLS
+
+/** 日志模块初始化
+@return int:return 0 for success 
+作者:Jesse  日期:2010-07-22
+*/
+LOG4C_API int log_init();
+
+/** 日志模块初始化,指定配置文件名称
+@return int:return 0 for success 
+作者:Jesse  日期:2010-07-22
+*/
+LOG4C_API int log_init_with_cfg_file(const char *strCfgFileName);
+
+/** 日志模块清理
+@return int:return 0 for success 
+作者:Jesse  日期:2010-07-22
+*/
+LOG4C_API int log_fini();
+
+/**宏参数抽取priority函数
+本函数接受LOG_DEBUG(X)的参数,并从该宏定义的参数中返回priority的值
+@return const int : iPriority.
+作者:Jesse  日期:2010-07-22
+*/
+LOG4C_API const int log_get_priority_wrapper(
+	const int iPriority,	///日志记录级别
+	const char* strFormat,	///日志内容格式
+	...						///日志内容
+	);
+
+/**
+将大小为count的缓冲区中内容按字节以16进制字符串打印出来,
+返回值即为指向相应的字符串,
+该返回指向的存储区域要调用本函数的用户显示的进行删除
+*/
+LOG4C_API void log4c_sprintf_data(char *buff, int count, char *dest_buffer);
+
+/**日志记录宏定义
+注意事项: 使用时参数必须使用两个括号括起来,LOG4C((X));见下面例子
+使用例子: LOG4C((LOG_ERROR, "Hello World! My Name is %s, and my age is %d ", "Jess", "28" ));
+作者:Jesse  日期:2010-07-22
+*/
+
+LOG4C_API const LOG_PARAM  log_vsprintf_wrapper(
+	const int iPriority,	///日志记录级别
+	const char* strFormat,	///日志内容格式
+	...						///日志内容
+	);
+
+LOG4C_API const LOG_PARAM  log_condition_vsnprintf_wrapper(
+	const int iCondition,	///条件
+	const int iPriority,	///日志记录级别
+	const char* strFormat,	///日志内容格式
+	...						///日志内容
+	);
+
+LOG4C_API void log_hex_dump_vsnprintf_wrapper(
+	const int iPriority,	///日志记录级别
+	const char* strFormat,  ///日志内容格式
+	const char* strHexBuf,	///缓冲区首地址
+	const int iHexBufLen,	///缓冲区长度
+	...						///日志内容
+	);
+
+LOG4C_API const LOG_PARAM log_vsnprintf_wrapper_msg(
+	const char* strFormat,	///日志内容格式
+	...						///日志内容
+);
+
+/** 日志记录
+日志记录为一个字符串指针指向的内容
+@return void
+作者:Jesse  日期:2010-07-22
+*/
+LOG4C_API void log_msg(
+			const char *strFile,	///文件名
+			const int iLineNum,		///行号
+			const char *strCatName,	///category名
+			const int iPriority,	///日志记录级别
+			const char *strFormat,	///日志内容格式
+			...						///日志内容
+			);
+
+LOG4C_API void log_msg_func(
+	const char *strFile,	///文件名
+	const char *strFuncName,///函数名
+	const int iLineNum,		///行号
+	const char *strCatName,	///category名
+	const int iPriority,	///日志记录级别
+	const char *strFormat,	///日志内容格式
+	...						///日志内容
+	);
+
+/** 日志记录,不记录文件名和行号
+日志记录为一个字符串指针指向的内容
+@return void
+作者:Jesse  日期:2010-07-22
+*/
+LOG4C_API void log_msg_no_file_num(
+			const char *strCatName,	///category名
+			const int iPriority,	///日志记录级别
+			const char *strFormat,	///日志内容格式
+			...						///日志内容
+			);
+
+/** 日志记录,不记录文件名和行号,没有任何layout转换,直接输出相应的字符文本到日志中
+此条记录没有行号,也没有线程号,也没有回车等
+日志记录为一个字符串指针指向的内容
+@return void
+作者:Jesse  日期:2010-07-22
+*/
+LOG4C_API void log_msg_no_file_num_no_layout(
+		   const char *strCatName,	///category名
+		   const int iPriority,		///日志记录级别
+		   const char *strFormat,		///日志内容格式
+		   ...						///日志内容
+		   );
+
+
+/** 日志模块初始化
+以日志配置文件字符串内容和日志配置文件命作为参数
+若相应配置文件存在则使用,否则按照给定内容和文件名创建日志配置文件并使用之
+@return int,0 表成功
+作者:Jesse  日期:2010-07-22
+*/
+LOG4C_API int log_init_with_string(
+			const char *strFileContent,
+			const char *strFileName 
+			);
+
+/** 日志模块初始化
+以日志配置文件命作为参数
+@return int,0 表成功
+作者:Jesse  日期:2010-07-22
+*/
+LOG4C_API int log_init_with_cfg_file_wrapper(
+			const char * strConfigFile
+			);
+
+/** 日志模块初始化-日志配置文件的文件名设置
+以日志配置文件命作为参数
+@return void
+作者:Jesse  日期:2010-07-22
+*/
+LOG4C_API void log_set_log_cfg_file_name(const char *strFileName);
+
+/** 日志模块初始化-生成的日志文件的文件名设置
+以日志文件命作为参数
+@return void
+作者:Jesse  日期:2010-07-22
+*/
+LOG4C_API void log_set_log_file_name(const char *strFileName);
+
+/** 日志模块初始化-日志记录级别设置
+@return void
+作者:Jesse  日期:2010-07-22
+*/
+LOG4C_API void log_set_log_level(const char *strLogLevel);
+
+/** 日志模块初始化-日志记录文件的大设置
+@return void
+作者:Jesse  日期:2010-07-22
+*/
+LOG4C_API void log_set_log_file_size(const int iFileSize);
+
+/** 日志模块初始化-日志记录文件的个数设置
+记录到最大个数后将回滚重复覆盖第一个日志文件,依次类推
+@return void
+作者:Jesse  日期:2010-07-22
+*/
+LOG4C_API void log_set_log_file_num(const int iFileNum);
+
+/** 日志模块初始化-是否实时读取日志配置文件
+设置是否每次记录时都读取日志配置文件
+@param:const BOOL m_bReReadLogCfgFile
+@return void
+作者:Jesse  日期:2010-07-22
+*/
+LOG4C_API void log_set_reread_log_cfg_file(const BOOL bReReadLogCfgFile);
+
+/** 日志模块初始化-带参数进行日志模块初始化
+这里的参数则为上面的几个API设置的参数,
+所以本函数一定要在日志配置参数设置好之后调用设置的参数才能生效的
+@return int,OK,成功;FAILURE,失败
+作者:Jesse  日期:2010-07-22
+*/
+LOG4C_API int log_init_with_param();
+
+/** 日志模块初始化-带参数进行日志模块初始化,程序的多个运行实例产生的日志不互相冲突
+这里的参数则为上面的几个API设置的参数,
+所以本函数一定要在日志配置参数设置好之后调用设置的参数才能生效的
+@return int,OK,成功;FAILURE,失败
+作者:Jesse  日期:2010-07-22
+*/
+LOG4C_API int log_init_with_param_multi_process();
+
+/** 日志记录Block方式能清楚的表明调用层次
+类似下面这种B-Entry类型日志:
+main.cpp(87) B-Entry	==> main
+main.cpp(90) B-Entry	====> main_01
+main.cpp(92) B-Entry	======> main_02
+main.cpp(92) B-Exit	<====== main_02 
+main.cpp(90) B-Exit	<==== main_01
+@return void
+作者:Jesse  日期:2010-07-22
+*/
+LOG4C_API void log4c_block_begin(const char * fileName, int lineNum, const char * traceName);
+
+/** 日志记录Block方式能清楚的表明调用层次
+类似下面这种B-Exit类型日志:
+main.cpp(87) B-Entry	==> main
+main.cpp(90) B-Entry	====> main_01
+main.cpp(92) B-Entry	======> main_02
+main.cpp(92) B-Exit	<====== main_02 
+main.cpp(90) B-Exit	<==== main_01
+@return void
+作者:Jesse  日期:2010-07-22
+*/
+LOG4C_API void log4c_block_end(const char * fileName, int lineNum, const char * traceName);
+
+/**检测配置文件是否存在
+@return const int : iPriority.
+作者:Jesse  日期:2010-07-22
+*/
+extern const int log_check(void);
+
+/**检测配置文件是否存在,只检测传入的配置文件名
+@return const int : iPriority.
+作者:Jesse  日期:2010-07-22
+*/
+extern const int log_check_with_cfg_file(const char *strCfgFileName);
+
+/**宏参数抽取format函数
+本函数接受LOG_DEBUG(X)的参数,并从该宏定义的参数中返回format的值
+@return const char* : strFormat
+作者:Jesse  日期:2010-07-22
+*/
+extern const char* log_get_format_wrapper(
+	const int iPriority,	///日志记录级别
+	const char* strFormat,	///日志内容格式
+	...						///日志内容
+	);
+
+
+/** 设置appender
+@return int:
+作者:Jesse  日期:2010-07-22
+*/
+extern int log_setappender(
+			const char *strCatName,		///category名
+			const char *strAppenderName ///appender名
+			);
+
+/** 日志记录
+支持类似printf函数的带格式输出
+@return void
+作者:Jesse  日期:2010-07-22
+*/
+extern void log_log(
+			const char *strCatName,	///category名
+			const int iPriority,	///日志记录级别
+			const char *strFormat,	///日志内容格式
+			...						///日志内容
+			);
+
+/** 日志模块初始化-日志模块使用实例个数自增
+@return void
+作者:Jesse  日期:2010-07-22
+*/
+extern void IncreaseLogModuleUsage();
+
+__LOG4C_END_DECLS
+
+///#include "log4c.h"
+#endif ///((defined(LOG_USELOG4CXX) && defined(__cplusplus)) || defined(LOG4C_ENABLE))
+
+#endif // !defined(LOG_H_INCLUDED_)
+/************** End of Log.h *******************************************/

+ 89 - 0
scbc.tools/Log4C/log4c/logging_event.h

@@ -0,0 +1,89 @@
+/* $Id$
+ *
+ * logging_event.h
+ * 
+ * Copyright 2001-2003, Meiosys (www.meiosys.com). All rights reserved.
+ *
+ * See the COPYING file for the terms of usage and distribution.
+ */
+
+#ifndef log4c_logging_event_h
+#define log4c_logging_event_h
+
+/**
+ * @file logging_event.h
+ *
+ * @brief the internal representation of logging events. 
+ * 
+ * When a affirmative logging decision is made a log4c_logging_event
+ * instance is created. This instance is passed around the different log4c
+ * components.
+ **/
+
+#include <log4c/defs.h>
+#include <log4c/buffer.h>
+#include <log4c/location_info.h>
+#ifndef _WIN32
+#include <sys/time.h>
+#endif
+
+__LOG4C_BEGIN_DECLS
+
+struct __log4c_category;
+
+/**
+ * @brief logging event object
+ * 
+ * Attributes description:
+ * 
+ * @li @c evt_category category name. 
+ * @li @c evt_priority priority of logging event.
+ * @li @c evt_msg The application supplied message of logging event.
+ * @li @c evt_buffer a pre allocated buffer to be used by layouts to
+ *        format in a multi-thread environment.
+ * @li @c evt_rendered_msg The application supplied message after layout format.
+ * @li @c evt_timestamp The number of seconds elapsed since the epoch
+ * (1/1/1970 00:00:00 UTC) until logging event was created.
+ * @li @c evt_loc The event's location information 
+ **/
+typedef struct 
+{
+    const char* evt_category;
+    int	evt_priority;
+    const char* evt_msg;
+    const char* evt_rendered_msg;
+    log4c_buffer_t evt_buffer;
+/* ok, this is probably not a good way to do it--should define a common type here
+and have the base acessor function do the mapping
+*/
+#ifndef _WIN32
+    struct timeval evt_timestamp;
+#else
+    FILETIME evt_timestamp;
+#endif
+    const log4c_location_info_t* evt_loc;
+
+} log4c_logging_event_t;
+
+/**
+ * Constructor for a logging event.
+ *
+ * @param a_category the category name
+ * @param a_priority the category initial priority
+ * @param a_message the message of this event
+ *
+ * @todo need to handle multi-threading (NDC)
+ **/
+LOG4C_API log4c_logging_event_t* log4c_logging_event_new(
+    const char* a_category,
+    int		a_priority,
+    const char*	a_message);
+/**
+ * Destructor for a logging event.
+ * @param a_event the logging event object
+ **/
+LOG4C_API void log4c_logging_event_delete(log4c_logging_event_t* a_event);
+
+__LOG4C_END_DECLS
+
+#endif

+ 56 - 0
scbc.tools/Log4C/log4c/priority.h

@@ -0,0 +1,56 @@
+/* $Id$
+ *
+ * priority.h
+ * 
+ * Copyright 2001-2003, Meiosys (www.meiosys.com). All rights reserved.
+ *
+ * See the COPYING file for the terms of usage and distribution.
+ */
+
+#ifndef log4c_priority_h
+#define log4c_priority_h
+
+/**
+ * @file priority.h
+ *
+ * @brief The priority class provides importance levels with which one can
+ * categorize log messages.
+ **/
+
+#include <log4c/defs.h>
+
+__LOG4C_BEGIN_DECLS
+
+/**
+ * Predefined Levels of priorities. These correspond to the priority levels
+ * used by syslog(3).
+ **/
+ typedef enum {
+    /** fatal */	LOG4C_PRIORITY_FATAL	= 000, 
+    /** alert */	LOG4C_PRIORITY_ALERT	= 100, 
+    /** crit */	      	LOG4C_PRIORITY_CRIT	= 200, 
+    /** error */	LOG4C_PRIORITY_ERROR	= 300, 
+    /** warn */	      	LOG4C_PRIORITY_WARN	= 400, 
+    /** notice */	LOG4C_PRIORITY_NOTICE	= 500, 
+    /** info */	      	LOG4C_PRIORITY_INFO	= 600, 
+    /** debug */	LOG4C_PRIORITY_DEBUG	= 700,
+    /** trace */	LOG4C_PRIORITY_TRACE	= 800,
+    /** notset */	LOG4C_PRIORITY_NOTSET	= 900,
+    /** unknown */	LOG4C_PRIORITY_UNKNOWN	= 1000
+} log4c_priority_level_t;
+
+/**
+ * @param a_priority a numeric value of the priority.
+ * @returns the given priority string name.
+ **/
+LOG4C_API const char* log4c_priority_to_string(int a_priority);
+
+/**
+ * @param a_priority_name a priority string name.
+ * @returns the given numeric value of the priority.
+ **/
+LOG4C_API int log4c_priority_to_int(const char* a_priority_name);
+
+__LOG4C_END_DECLS
+
+#endif

+ 70 - 0
scbc.tools/Log4C/log4c/rc.h

@@ -0,0 +1,70 @@
+/* $Id$
+ *
+ * rc.h
+ *
+ * Copyright 2001-2003, Meiosys (www.meiosys.com). All rights reserved.
+ *
+ * See the COPYING file for the terms of usage and distribution.
+ */
+
+#ifndef __log4c_rc_h
+#define __log4c_rc_h
+
+/**
+ * @file rc.h
+ *
+ * @brief log4c resource configuration
+ *
+ **/
+
+#include <log4c/defs.h>
+
+__LOG4C_BEGIN_DECLS
+
+/**
+ * @brief resource configuration object
+ *
+ * Attributes description:
+ * 
+ * @li @c nocleanup don't perform memory cleanup in log4c library 
+ *        destructor or in log4c_fini()
+ * @li @c bufsize maximum logging buffer size. 0 for no limits
+ * @li @c debug activate log4c debugging
+ **/
+typedef struct 
+{
+    struct 
+    {
+	int nocleanup;
+	int bufsize;
+	int debug;
+	int reread;
+    } config;
+
+} log4c_rc_t;
+
+/**
+ * default log4c resource configuration object
+ **/
+LOG4C_API log4c_rc_t * const	log4c_rc;
+
+/**
+ * load log4c resource configuration file
+ *
+ * @param a_filename name of file to load
+ **/
+LOG4C_API int		log4c_load(const char* a_filename);
+
+/**
+ * @internal
+ **/
+LOG4C_API int		log4c_rc_load(log4c_rc_t* a_rc, const char* a_filename);
+
+/*
+ * Rereads any log4crc files that have changed
+ */
+LOG4C_API void log4c_reread(void);
+
+__LOG4C_END_DECLS
+
+#endif

+ 215 - 0
scbc.tools/Log4C/log4c/rollingpolicy.h

@@ -0,0 +1,215 @@
+
+/*
+ * rollingpolicy.h
+ *
+ * See the COPYING file for the terms of usage and distribution.
+*/
+
+#ifndef log4c_rollingpolicy_h
+#define log4c_rollingpolicy_h
+
+/**
+ * @file rollingpolicy.h
+ *
+ * @brief Log4c rolling policy interface. Defines the interface for
+ * managing and providing rolling policies.
+ *
+ * A rolling policy is used to confogure a rollingfile appender to tell
+ * it when to trigger a rolover event.
+*/ 
+
+#include <stdio.h>
+#include <log4c/defs.h>
+#include <log4c/layout.h>
+
+__LOG4C_BEGIN_DECLS
+
+struct __log4c_rollingpolicy;
+
+/**
+ * log4c rollingpolicy type 
+ */
+typedef struct __log4c_rollingpolicy log4c_rollingpolicy_t;
+
+
+#define ROLLINGFILE_DEFAULT_LOG_DIR "."
+#define ROLLINGFILE_DEFAULT_LOG_PREFIX "log"
+#define ROLLINGFILE_DEFAULT_LOG_EXT "txt"
+
+typedef struct __rollingfile_udata rollingfile_udata_t; /* opaque */
+
+
+/**
+ * @brief log4c rollingpolicy type.  Defines the interface a specific policy
+ * must provide to the rollingfile appender.
+ *
+ * Attributes description:
+ * 
+ * @li @c name rollingpolicy type name 
+ * @li @c init() init the rollingpolicy
+ * @li @c is_triggering_event()
+ * @li @c rollover()
+ *
+ **/
+typedef struct log4c_rollingpolicy_type {
+  const char*	name;
+  int (*init)(log4c_rollingpolicy_t *a_this, rollingfile_udata_t* rfudatap );
+  int (*is_triggering_event)( log4c_rollingpolicy_t* a_policy,
+			      const log4c_logging_event_t*,
+			      long current_file_size );
+  int (*rollover)(log4c_rollingpolicy_t* a_policy, FILE **);  
+  int (*fini)(log4c_rollingpolicy_t *a_this);
+} log4c_rollingpolicy_type_t;
+
+/**
+ * Get a new rolling policy
+ * @param policy_name a name for the policy
+ * @return a new rolling policy, otherwise NULL.
+ */ 
+LOG4C_API log4c_rollingpolicy_t* log4c_rollingpolicy_get(
+                                  const char* policy_name);
+
+/**
+ * Use this function to register a rollingpolicy type with log4c.
+ * Once this is done you may refer to this type by name both 
+ * programmatically and in the log4c configuration file.
+ *
+ * @param a_type a pointer to the new rollingpolicy type to register.
+ * @returns a pointer to the previous rollingpolicy type of same name.
+ *
+ * Example code fragment: 
+ * @code
+ * 
+ * const log4c_rollingpolicy_type_t log4c_rollingpolicy_type_sizewin = {
+ *   "sizewin",
+ *   sizewin_init,
+ *   sizewin_is_triggering_event,
+ *   sizewin_rollover
+ * };
+ *
+ * log4c_rollingpolicy_type_set(&log4c_rollingpolicy_type_sizewin);
+ * @endcode
+ * 
+ */
+LOG4C_API const log4c_rollingpolicy_type_t* log4c_rollingpolicy_type_set(
+                                    const log4c_rollingpolicy_type_t* a_type);
+                                  
+/**
+ * Configure a rolling policy with a specific policy.
+ * @param policyp pointer to the rolling policy
+ * @param udatap a specific policy type, for example sizewin.
+ * @return zero if successful, non-zero otherwise.
+ */                                  
+LOG4C_API void log4c_rollingpolicy_set_udata(log4c_rollingpolicy_t* policyp,
+					  void *udatap);
+/**
+ * Call the initialization code of a rolling policy.
+ * @param policyp pointer to the rolling policy
+ * @param app the rolling appender this policy is used with
+ * @return zero if successful, non-zero otherwise.
+*/
+LOG4C_API int log4c_rollingpolicy_init(log4c_rollingpolicy_t *policyp,
+                                       rollingfile_udata_t* rfup );
+
+/**
+ * Call the un initialization code of a rolling policy.
+ * This will call the fini routine of the particular rollingpolicy type
+ * to allow it to free up resources.  If the call to fini in the 
+ * rollingpolicy type fails then the rollingpolicy is not uninitialized.
+ * Try again later model...
+ * @param policyp pointer to the rolling policy
+ * @return zero if successful, non-zero otherwise.
+*/
+LOG4C_API int log4c_rollingpolicy_fini(log4c_rollingpolicy_t *a_this);
+
+/**
+ * Determine if a logging event should trigger a rollover according to
+ * the given policy.
+ * @param policyp pointer to the rolling policy
+ * @param evtp the logging event pointer.
+ * @param current_file_size the size of the current file being logged to.
+ * @return non-zero if rollover required, zero otherwise.
+ */ 
+LOG4C_API int log4c_rollingpolicy_is_triggering_event(
+		     log4c_rollingpolicy_t* policyp,
+                     const log4c_logging_event_t* evtp,
+		     long current_file_size );
+/**
+ * Effect a rollover according to policyp on the given file stream.
+ * @param policyp pointer to the rolling policy
+ * @param fp filestream to rollover.
+ * @return zero if successful, non-zero otherwise.
+ * The policy can return an indication that something went wrong but
+ * that the rollingfile appender can stull go ahead and log by returning an
+ * error code <= ROLLINGPOLICY_ROLLOVER_ERR_CAN_LOG.  Anything greater than
+ * means that the rolling file appender will not try to log it's message.
+ */        
+
+#define  ROLLINGPOLICY_ROLLOVER_ERR_CAN_LOG 0x05
+LOG4C_API int log4c_rollingpolicy_rollover(log4c_rollingpolicy_t* policyp,
+                                            FILE ** fp);
+
+/**
+ * sets the rolling policy type
+ *
+ * @param a_rollingpolicy the log4c_rollingpolicy_t object
+ * @param a_type the new rollingpolicy type
+ * @return the previous appender type
+ **/
+LOG4C_API const log4c_rollingpolicy_type_t* log4c_rollingpolicy_set_type(
+    log4c_rollingpolicy_t* a_rollingpolicy,
+    const log4c_rollingpolicy_type_t* a_type);
+    
+/**
+ * Get a pointer to an existing rollingpolicy type.
+ *
+ * @param a_name the name of the rollingpolicy type to return.  
+ * @returns a pointer to an existing rollingpolicy type, or NULL if no 
+ * rollingpolicy type with the specified name exists.
+ */
+LOG4C_API const log4c_rollingpolicy_type_t* log4c_rollingpolicy_type_get(
+    const char* a_name);
+                                            
+/**
+ * Get the rolling policy configuration.
+ * @param policyp pointer to the rolling policy
+ * @return pointer to the rolling policy configuration.
+*/                                             
+LOG4C_API void* log4c_rollingpolicy_get_udata(
+                        const log4c_rollingpolicy_t* policyp);
+                        
+/**
+ * Get the rollingfile appender associated with this policy.
+ * @param policyp pointer to the rolling policy
+ * @return pointer to the rolling file appender associated with this policy
+*/                          
+LOG4C_API rollingfile_udata_t* log4c_rollingpolicy_get_rfudata(
+                        const log4c_rollingpolicy_t* policyp);
+                        
+LOG4C_API void* log4c_rollingpolicy_get_name(const log4c_rollingpolicy_t* a_this);                        
+
+LOG4C_API log4c_rollingpolicy_t* log4c_rollingpolicy_new(const char* a_name);
+LOG4C_API void log4c_rollingpolicy_delete(log4c_rollingpolicy_t* a_this);
+LOG4C_API void log4c_rollingpolicy_print(const log4c_rollingpolicy_t* a_this,
+FILE* a_stream);
+
+LOG4C_API int log4c_rollingpolicy_is_initialized(log4c_rollingpolicy_t* a_this);
+LOG4C_API void log4c_rollingpolicy_types_print(FILE *fp);
+
+/** 删除本rollingpolicy.c文件中定义的全局和静态的指针指向的内存,防止内存泄漏
+如:
+1.gs_types.
+2.
+@return void.
+作者:jesse 日期:2008.09.08
+*/
+LOG4C_API void log4c_rollingpolicy_delete_global();
+
+/**
+ * @internal
+ **/
+struct __sd_factory;
+LOG4C_API struct __sd_factory* log4c_rollingpolicy_factory;
+
+__LOG4C_END_DECLS
+#endif

+ 86 - 0
scbc.tools/Log4C/log4c/rollingpolicy_type_sizewin.h

@@ -0,0 +1,86 @@
+
+/*
+ * rollingpolicy_type_sizewin.h
+ *
+ * See the COPYING file for the terms of usage and distribution.
+*/
+
+#ifndef log4c_policy_type_sizewin_h
+#define log4c_policy_type_sizewin_h
+
+/**
+ * @file rollingpolicy_type_sizewin.h
+ *
+ * @brief Log4c rolling file size-win interface.
+ * Log4c ships with (and defaults to) the classic size-window rollover policy:
+ * this triggers rollover when files reach a maximum size.  The first file in
+ * the list is
+ * always the current file; when a rollover event occurs files are shifted up
+ * by one position in the list--if the number of files in the list has already
+ * reached the max then the oldest file is rotated out of the window.
+ *
+ * If the max file size is set to zero, this means 'no-limit'.
+ *
+ * The default parameters for the size-win policy are 5 files of maximum
+ * size of 20kilobytes each.  These parameters may be changed using the
+ * appropriate setter functions.
+ */
+ 
+#include <log4c/defs.h>
+#include <log4c/rollingpolicy.h>
+
+__LOG4C_BEGIN_DECLS
+
+LOG4C_API const log4c_rollingpolicy_type_t log4c_rollingpolicy_type_sizewin;
+
+/**
+ * log4c size-win rolling policy type 
+*/
+typedef struct __sizewin_udata rollingpolicy_sizewin_udata_t;
+
+#define ROLLINGPOLICY_SIZE_DEFAULT_MAX_FILE_SIZE 1024*20
+#define ROLLINGPOLICY_SIZE_DEFAULT_MAX_NUM_FILES 5
+
+/**
+ * Get a new size-win rolling policy
+ * @return a new size-win rolling policy, otherwise NULL.
+ */
+LOG4C_API rollingpolicy_sizewin_udata_t *sizewin_make_udata(void);
+
+/**
+ * Set the maximum file size in this rolling policy configuration.
+ * @param swup the size-win configuration object.
+ * @param max_size the approximate maximum size any logging file will
+ * attain.
+ * If you set zero then it means 'no-limit' and so only one file
+ * of unlimited size will be used for logging.
+ * @return zero if successful, non-zero otherwise.
+ */
+LOG4C_API int sizewin_udata_set_file_maxsize(
+                              rollingpolicy_sizewin_udata_t * swup,
+			      long max_size);
+                                                            
+/**
+ * Set the maximum number of filesin this rolling policy configuration.
+ * @param swup the size-win configuration object.
+ * @param max_num the maximum number of files in the list.
+ * @return zero if successful, non-zero otherwise.
+ */                                                         
+LOG4C_API int sizewin_udata_set_max_num_files(
+                              rollingpolicy_sizewin_udata_t * swup,
+	                      long max_num);
+
+/**
+ * Set the rolling file appender in this rolling policy configuration.
+ * @param swup the size-win configuration object.
+ * @param app the rolling file appender to set.
+ * @return zero if successful, non-zero otherwise.
+*/                                                            
+LOG4C_API int sizewin_udata_set_appender(
+                              rollingpolicy_sizewin_udata_t * swup,
+			      log4c_appender_t* app);
+
+__LOG4C_END_DECLS
+
+
+#endif

+ 40 - 0
scbc.tools/Log4C/log4c/sharedmemory.h

@@ -0,0 +1,40 @@
+/************** Begin of sharedmemory.h *******************************************/
+#if defined(linux)  && defined(HAVE_SHM)
+	/***************************************************************************
+	|sharedmemory.h|  -  sharedmemory类的头文件-声明sharedmemory类
+	-------------------
+	begin                : |03-6-20|
+	modify               : |03-6-20|
+	copyright            : (C) |YEAR| by |wenhm(温辉敏)|
+	email                : |EMAIL|
+	***************************************************************************/
+
+#ifndef SHAREDMEMORY_H
+#define SHAREDMEMORY_H
+
+#include <sys/types.h>
+
+	//创建或关键字为Key的含有大小为size的共享内存对象,并将共享内存对象id放于shmid中返回。
+	//若共享内存对象已存在则取得该对象
+	extern int create_sharedmemory(key_t key, int size);
+
+	//创建关键字Key为IPC_PRIVATE(即关键字由系统选定)的含有大小为size的共享内存对象,并将共享内存对象id放于shmid中返回。
+	//因使用IPC_PRIVATE创建的共享内存的key都一样,所以key就不要了。
+	extern int create_sharedmemory_private(int size);
+
+	//将共享内存attach到进程自己得空间内,函数返回指向映射内存的指针。
+	extern void *attach_sharedmemory(int shmid );
+
+	//将共享内存disattach,唯一的参数是共享内存映射的指针
+	//返回值: -1 on error: errno = EINVAL (Invalid attach address passed)
+	extern int disattach_sharedmemory(void* shm);
+
+	//获取共享内存对象shmid的大小
+	extern int getsize_sharedmemory(int shmid);
+
+	//删除共享内存对象
+	extern int del_sharedmemory(int shmid);
+#endif	/* SHAREDMEMORY_H */  
+
+#endif
+/************** Begin of sharedmemory.h *******************************************/

+ 57 - 0
scbc.tools/Log4C/log4c/version.h

@@ -0,0 +1,57 @@
+/* $Id$
+ *
+ * version.h
+ * 
+ * Copyright 2001-2003, Meiosys (www.meiosys.com). All rights reserved.
+ *
+ * See the COPYING file for the terms of usage and distribution.
+ */
+
+#ifndef log4c_version_h
+#define log4c_version_h
+
+/**
+ * @file version.h
+ *
+ * @brief log4c version information
+ **/
+
+#include <log4c/defs.h>
+
+__LOG4C_BEGIN_DECLS
+
+/**
+ * constant macro holding the major version of log4c
+ **/
+#define LOG4C_MAJOR_VERSION 1
+/**
+ * constant macro holding the minor version of log4c
+ **/
+#define LOG4C_MINOR_VERSION 2
+/**
+ * constant macro holding the micro version of log4c
+ **/
+#define LOG4C_MICRO_VERSION 1
+
+/**
+ * constant variable holding the major version of log4c
+ **/
+extern const int log4c_major_version;
+/**
+ * constant variable holding the minor version of log4c
+ **/
+extern const int log4c_minor_version;
+/**
+ * constant variable holding the micro version of log4c
+ **/
+extern const int log4c_micro_version;
+
+/**
+ * @return a string containing the full log4c version
+ **/
+extern const char* log4c_version(void);
+
+__LOG4C_END_DECLS
+
+#endif
+

+ 676 - 0
scbc.tools/Log4C/log4c/vos.h

@@ -0,0 +1,676 @@
+/************** Begin of vos.h *******************************************/
+/**********************************************************
+* 版权所有 (C)2002, 深圳市中兴通讯股份有限公司。
+*
+* 文件名称: vos.h
+* 文件标识:
+* 内容摘要: 操作系统封装层头文件(主要是所包含头文件、数据结构、接口等)
+* 其它说明: 无
+* 当前版本: V1.0
+* 作    者: 王泽民
+* 完成日期: 2003/08/10
+*
+* 修改记录1:
+*    修改日期:
+*    版 本 号:
+*    修 改 人:
+*    修改内容:
+**********************************************************/
+#ifndef _VOS_H_
+#define _VOS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "voscfg.h"
+	/**********************************************************
+	*                          宏定义                         *
+	**********************************************************/
+
+#define    VOS_NULL                      0x0
+
+#define    VOS_TRUE                      1
+#define    VOS_FALSE                     0
+
+#define    VOS_SUCCESS                   0     /* PSOS返回值                    */
+#define    VOS_PCBINDEXNO                0     /* 保存pcbindex的便条寄存器号    */
+#define    VOS_TASKPRINO                 1     /* 保存任务优先级的便条寄存器号  */
+#define    VOS_TICKNUM                   1     /* 中断的tick数                  */
+#define    TIMER_SCAN_EVENT              (WORD32)(1<<15)
+#define    MEMLEAK_SCAN_EVENT            (WORD32)(1<<16)
+#define    MAX_LENGTH_BUF                512
+
+#define    VOS_NO_WAIT                   0x0
+#define    VOS_WAIT_FOREVER              -1
+
+#define    VOS_SEM_DELETE_SAFE           0x04
+#define    VOS_SEM_INVERSION_SAFE        0x08
+
+#define    VOS_VM_STATE_MASK_VALID       0x03
+#define    VOS_VM_STATE_MASK_WRITABLE    0x0c
+#define    VOS_VM_STATE_MASK_CACHEABLE   0x30
+#define    VOS_VM_STATE_MASK_WBACK       0x40
+#define    VOS_VM_STATE_MASK_GLOBAL      0x80
+#define    VOS_VM_STATE_MASK_GUARDED     0x80
+
+#define    VOS_VM_STATE_VALID            0x01
+#define    VOS_VM_STATE_VALID_NOT        0x00
+#define    VOS_VM_STATE_WRITABLE         0x04
+#define    VOS_VM_STATE_WRITABLE_NOT     0x00
+#define    VOS_VM_STATE_CACHEABLE        0x10
+#define    VOS_VM_STATE_CACHEABLE_NOT    0x00
+#define    VOS_VM_STATE_WBACK			 0x40
+#define    VOS_VM_STATE_WBACK_NOT		 0x00
+#define    VOS_VM_STATE_GLOBAL			 0x80
+#define    VOS_VM_STATE_GLOBAL_NOT		 0x00
+#define    VOS_VM_STATE_GUARDED			 0x80
+#define    VOS_VM_STATE_GUARDED_NOT		 0x00
+
+#define    MAXCOUNTSEM                   10000
+#define    VOS_MAX_PATH_LEN              50
+#define    VOS_MAX_FILENAME_LEN          60
+#define    VOS_MAX_EXP_FILENAME_LEN      8
+
+#if OS_TYPE == OS_VXWORKS
+#define    NULL_TASKID               ERROR
+#define    NULL_SEMID                NULL
+#define    NULL_MSGQID               NULL
+#define    NULL_MSGGET               0
+#define    DIR_CODE                  0x2f    /* 定义符号 "/" */
+#define    DIR_CONCATE_CODE            "/"
+#endif
+
+#if OS_TYPE == OS_WINNT
+#define    NULL_TASKID               NULL
+#define    NULL_SEMID                NULL
+#define    NULL_MSGQID               NULL
+#define    NULL_MSGGET               0
+#define    DIR_CODE                  0x5c    /* 定义符号" \" */
+#define    DIR_CONCATE_CODE            "\\"
+#define    RDONLY                    0
+#define    WRONLY                    1
+#define    RDWR                      2
+#define    WINNT_ERROR               -1    
+#endif
+
+#if OS_TYPE == OS_PSOS
+#define    NULL_TASKID               0xffffffff
+#define    NULL_SEMID                0xffffffff
+#define    NULL_MSGQID               0xffffffff
+#define    NULL_MSGGET               0xffffffff
+#define    MSG_Q_FIFO                0x00
+#define    MSG_Q_PRIORITY            0x01
+#define    MSG_PRI_NORMAL            0x00
+#define    MSG_PRI_URGENT            0x01
+#define    RAM_BLOCKS                2*360  /* RAM disk块大小 */
+#define    RAM_PATH_LENGTH           80
+#define    MIN_EXPAN_BLOCKS          10
+#endif
+
+#if OS_TYPE == OS_LINUX
+#ifdef VXWORKS_TO_LINUX
+#define    NULL_TASKID               ERROR
+#define    NULL_SEMID                NULL
+#define    NULL_MSGQID               NULL
+#else
+#define    NULL_TASKID               0xffffffff
+#define    NULL_SEMID                0xffffffff
+#define    NULL_MSGQID               0xffffffff
+#endif
+#define    NULL_MSGGET               0
+#define    DIR_CODE                  0x2f  /* 定义符号 "/" */
+
+#endif
+
+#if OS_TYPE == OS_KLINUX
+#define    NULL_TASKID               ERROR
+#define    NULL_SEMID                 NULL
+#define    NULL_MSGQID              NULL
+#define    TRUE   1
+#define    FALSE 0
+#define    DIR_CONCATE_CODE        "/"
+#define    DIR_CODE                0x2f
+#define    VOS_ISDIR(mode)    ((mode & S_IFMT) == S_IFDIR)    /* 判断是否是目录 */
+	// #define    malloc(size) __vmalloc(size,GFP_KERNEL |__GFP_HIGHMEM, PAGE_KERNEL)
+	//#define    free(buf)      vfree(buf)
+#define    printf  printk
+#endif
+
+
+	/************** SOCKET & TCP ***************/
+#define NELEMENTS(array)  (sizeof (array) / sizeof ((array) [0]))
+
+#ifndef HASMAX
+#ifndef max
+#define max(a,b) ((a)>(b)?(a):(b))
+#endif
+#endif
+
+#ifndef HASMIN
+#ifndef min
+#define min(a,b) ((a)<(b)?(a):(b))
+#endif
+#endif 
+
+
+#if (OS_TYPE == OS_VXWORKS)
+#define SOCKET_ERROR     ERROR
+#define SOMAXCONN        5
+#define VOS_EWOULDBLOCK  EWOULDBLOCK
+#define VOS_ECONNRESET   ECONNRESET
+#endif
+
+#if (OS_TYPE == OS_WINNT)
+	/* 数组中元素个数 */
+	///(pclint检测注释掉该行)#define NELEMENTS(array)  (sizeof (array) / sizeof ((array) [0]))
+#define CloseSocket closesocket
+#define bcopy(src,dst,size) memcpy(dst,src,size)
+#define errnoGet         WSAGetLastError
+	typedef long int STATUS ;
+#define VOS_EWOULDBLOCK WSAEWOULDBLOCK
+#define VOS_ECONNRESET WSAECONNRESET
+#endif
+
+
+#if ((OS_TYPE == OS_LINUX) ||(OS_TYPE == OS_KLINUX))
+	typedef unsigned long ULONG;
+#define errnoGet() errno
+#define SOCKET_ERROR     ERROR
+#define SOMAXCONN	128
+#define VOS_EWOULDBLOCK  EWOULDBLOCK
+#define VOS_ECONNRESET ECONNRESET
+
+#endif
+
+#if ((OS_TYPE == OS_VXWORKS) || (OS_TYPE == OS_LINUX)||(OS_TYPE == OS_KLINUX))
+	typedef int SOCKET;
+#endif
+
+	/**************** VOS TIMER *******************/
+
+	/* 时钟中断精度10ms */
+#define  TIMER_RESOLUTION    10 
+
+
+#if (OS_TYPE == OS_WINNT)
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+#include <mmsystem.h>
+#define  VOS_TIMERCALLBACK     LPTIMECALLBACK  
+#define  VOS_TIMER_ID          WORD32 
+#define  INVALID_VOS_TIMERID   0
+#endif
+
+#if (OS_TYPE == OS_VXWORKS)
+#define  VOS_TIMERCALLBACK     FUNCPTR  
+#define  VOS_TIMER_ID          WDOG_ID 
+#define  INVALID_VOS_TIMERID   NULL
+
+#define  TIMER_ONESHOT         0
+#define  TIMER_PERIODIC        1
+#endif
+
+#if (OS_TYPE == OS_PSOS)
+#define  VOS_TIMERCALLBACK     LPVOID  
+#define  VOS_TIMER_ID          WORD32 
+#define  INVALID_VOS_TIMERID   0xffffffff
+#endif
+
+#if (OS_TYPE == OS_LINUX)
+	typedef  void(*VOS_TIMERCALLBACK)(int);
+#define  VOS_TIMER_ID          WORD32 
+#define  INVALID_VOS_TIMERID   0
+#endif
+
+#if (OS_TYPE == OS_KLINUX)
+#ifndef HZ
+#define HZ 100
+#endif     
+	extern unsigned long volatile jiffies;
+
+	typedef  void(*VOS_TIMERCALLBACK)(WORD32);
+	typedef  struct timer_list    *VOS_TIMER_ID;
+#define  INVALID_VOS_TIMERID   NULL    
+#endif
+
+	/**************** VOS VOLUME *******************/
+#define        VOLNAME_LENGTH            10
+
+
+	/**********************************************************
+	*                          类型定义                       *
+	**********************************************************/
+
+#if    OS_TYPE == OS_VXWORKS
+#define    VOS_ISDIR(mode)    ((mode & S_IFMT) == S_IFDIR)    /* 判断是否是目录 */
+#define    VOS_ISCHR(mode)    ((mode & S_IFMT) == S_IFCHR)    /* 是否 是特殊字符 */
+#define    VOS_ISBLK(mode)    ((mode & S_IFMT) == S_IFBLK)    /* 判断是否是特殊块 */
+#define    VOS_ISREG(mode)    ((mode & S_IFMT) == S_IFREG)    /* 判断是否正规块 */
+#define    VOS_ISFIFO(mode)   ((mode & S_IFMT) == S_IFIFO)    /* 判断是否fifo  */
+#elif OS_TYPE== OS_WINNT
+#define    VOS_ISDIR(mode)    ((mode & _S_IFMT) == _S_IFDIR)    /* 判断是否是目录 */
+#define    VOS_ISCHR(mode)    ((mode & _S_IFMT) == _S_IFCHR)    /* 是否 是特殊字符 */
+#define    VOS_ISBLK(mode)    ((mode & _S_IFMT) == _S_IFBLK)    /* 判断是否是特殊块 */
+#define    VOS_ISREG(mode)    ((mode & _S_IFMT) == _S_IFREG)      /* 判断是否正规块 */
+#define    VOS_ISFIFO(mode)   ((mode & _S_IFMT) == _S_IFIFO)    /* 判断是否fifo  */
+#endif
+
+
+	/* ID类型定义 */
+#if OS_TYPE == OS_VXWORKS
+	typedef SWORD32  TASK_ID;
+	typedef PART_ID  MEMPART_ID;
+	typedef FUNCPTR  VOS_FUNCPTR;
+	typedef WIND_TCB TASK_TCB;	
+#endif
+
+#if OS_TYPE == OS_PSOS
+	typedef WORD32  TASK_ID;
+	typedef VOS_VOIDFUNCPTR  VOS_FUNCPTR;
+	typedef WORD32  SEM_ID;
+	typedef WORD32  MSG_Q_ID;
+	typedef WORD32  MEMPART_ID;	
+#endif
+
+#if OS_TYPE == OS_WINNT
+	typedef HANDLE   TASK_ID;
+	typedef HANDLE   SEM_ID;
+	typedef HANDLE   MEMPART_ID;
+	typedef HANDLE   MSG_Q_ID;
+	typedef LPTHREAD_START_ROUTINE VOS_FUNCPTR;	
+#endif
+
+#if OS_TYPE == OS_LINUX
+	typedef void        VOID;
+	typedef pthread_t	TASK_ID;
+	typedef sem_t *		SEM_ID; 
+#ifndef PART_ID
+#define PART_ID int
+#endif /*wenhm,050826*/
+	typedef PART_ID     MEMPART_ID;
+	typedef void*       VOS_FUNCPTR; 
+	///typedef void (*AutoRunHandler)(void);
+	typedef WORD32      MSG_RECEIVE;/*yangyp*/    
+	typedef WORD32      MSG_Q_ID;
+
+	///typedef FUNCPTR     VOS_FUNCPTR; 
+	///typedef WIND_TCB    TASK_TCB;
+	///typedef WORD16      VOS_TIMER_ID;/*yangyp*/
+	///typedef WORD32		SEM_ID;
+	///typedef SWORD32     TASK_ID;
+#endif
+#if OS_TYPE == OS_KLINUX
+	typedef void        VOID;
+	typedef pthread_t	TASK_ID;
+	typedef sem_t*		SEM_ID; 
+	/*typedef PART_ID     MEMPART_ID;
+	typedef FUNCPTR     VOS_FUNCPTR;
+	typedef WIND_TCB    TASK_TCB;*/
+	typedef WORD32      MEMPART_ID;
+	typedef void*       VOS_FUNCPTR;
+	typedef WORD32      MSG_RECEIVE;/*yangyp*/
+	typedef WORD16      VOS_TIMER_ID;/*yangyp*/
+	typedef WORD32      MSG_Q_ID;
+#endif
+
+
+	/* VOS_STATUS: VOS层函数返回值 */
+	typedef enum
+	{
+		VOS_ERROR = -1,
+		VOS_OK = 0,
+	}VOS_STATUS;
+
+	/* VOS_SEM_STATE  二进制信号量初始状态 */
+	typedef enum
+	{
+		VOS_SEM_EMPTY,
+		VOS_SEM_FULL
+	}VOS_SEM_STATE;
+
+	/* 信号量队列类型:先进先出或优先级 */
+	typedef enum
+	{
+		VOS_SEM_Q_FIFO,
+		VOS_SEM_Q_PRIORITY
+	}VOS_SEM_QUEUE_TYPE;
+
+	/* 消息优先级 */
+	typedef enum
+	{
+		VOS_MSG_PRI_NORMAL,
+		VOS_MSG_PRI_URGENT
+	}VOS_MSG_TYPE;
+
+	/* 消息排队类型:先进先出或优先级 */
+	typedef enum
+	{
+		VOS_MSG_Q_FIFO,
+		VOS_MSG_Q_PRIORITY
+	}VOS_MSGQUE_TYPE;
+
+	/* 任务状态 */
+	typedef enum
+	{
+		VOS_TASK_STATUS_NULL,
+		VOS_TASK_STATUS_RUNNING,
+		VOS_TASK_STATUS_READY,
+		VOS_TASK_STATUS_PEND,
+		VOS_TASK_STATUS_SUSPEND,
+		VOS_TASK_STATUS_DEBUG,
+		VOS_TASK_STATUS_DEAD
+	}VOS_TASK_STATUS;
+
+	/* 参数和返回值为VOID的函数定义 */
+	typedef   VOID(*VOS_VOIDFUNCPTR)(VOID);
+
+	/**********************************************************
+	*                          数据结构定义                   *
+	**********************************************************/
+
+	/* 系统时钟 */
+	typedef struct tagSYS_CLOCK
+	{
+		WORD16             wSysYear;
+		WORD16             wSysMon;
+		WORD16             wSysDay;
+		WORD16             wSysHour;
+		WORD16             wSysMin;
+		WORD16             wSysSec;
+		WORD16             wSysWeek;
+		WORD16             wMilliSec;
+	}T_SYS_CLOCK;
+
+#undef st_atime
+#undef st_mtime
+#undef st_ctime
+	/* 文件状态描述 */
+	typedef struct tagFileStat
+	{
+		WORD32  st_dev;
+		WORD32  st_ino;
+		WORD16  st_mode;
+		SWORD16 st_nlink;
+		SWORD16 st_uid;
+		SWORD16 st_gid;
+		WORD32  st_rdev;
+		SWORD32 st_size;
+		SWORD32 st_atime;
+		SWORD32 st_mtime;
+		SWORD32 st_ctime;
+	}T_FileStat;
+
+
+	/* added by 温辉敏,文件的访问属性*/
+	enum Permissions {
+		/// File has world execute permission
+		WorldExecute = 1,   
+		/// File has world write permission
+		WorldWrite = 2,     
+		/// File has world read permission
+		WorldRead = 4,      
+		/// File has group execute permission
+		GroupExecute = 8,   
+		/// File has group write permission
+		GroupWrite = 16,    
+		/// File has group read permission
+		GroupRead = 32,     
+		/// File has owner execute permission
+		UserExecute = 64,   
+		/// File has owner write permission
+		UserWrite = 128,    
+		/// File has owner read permission
+		UserRead = 256,     
+		/// All possible permissions.
+		AllPermissions = 0x1ff,   
+		/// Owner read & write plus group and world read permissions.
+		DefaultPerms = UserRead|UserWrite|GroupRead|WorldRead,
+		/// Owner read & write & execute plus group and world read & exectute permissions.
+		DefaultDirPerms = DefaultPerms|UserExecute|GroupExecute|WorldExecute		
+	};
+
+#if OS_TYPE == OS_WINNT
+	/**
+	下面结构当和MINIAce一起使用时,
+	os_dirent.h中相应的结构产生的冲突,而os_dirent.h结构中采用了ACE_LACKS_STRUCT_DIR才会生效,
+	因此可以设定vos.h中不采用ACE_LACKS_STRUCT_DIR宏定义时它的结构dirent才生效. 
+	added by wenhm in 2007.05.16
+	*/
+#ifndef ACE_LACKS_STRUCT_DIR
+	/* 路径入口 */
+	struct  dirent
+	{
+		unsigned short d_ino;
+		unsigned short d_off;
+		unsigned short d_reclen;
+		CHAR     d_name [VOS_MAX_FILENAME_LEN + 1];
+	};
+#endif
+
+
+	/* 目录项的定义 */
+	typedef struct
+	{
+		SWORD32       dd_fd;        /* 打开目录的文件描述 */
+		SWORD32       dd_cookie;    /* 目录中的文件特定标示filesys-specific marker within dir */
+		struct dirent dd_dirent;    /* 路径入口 */
+	}DIR;
+
+
+#endif
+
+
+
+	/**********************************************************
+	*                          函数原型                       *
+	**********************************************************/
+
+	/******************  任务管理模块 ************************/
+	TASK_ID       VOS_CreateTask(CHAR *pTaskName, SWORD32 priority,
+		SWORD32 options, SWORD32 stackSize,
+		VOS_FUNCPTR pTaskEntry, SWORD32 arg1,
+		SWORD32 arg2, SWORD32 arg3, SWORD32 arg4,
+		SWORD32 arg5, SWORD32 arg6, SWORD32 arg7,
+		SWORD32 arg8, SWORD32 arg9, SWORD32 arg10);
+
+	VOS_STATUS    VOS_DeleteTask(TASK_ID taskId);
+	VOS_STATUS    VOS_SuspendTask(TASK_ID taskId);
+	VOS_STATUS    VOS_ResumeTask(TASK_ID  taskId);
+	VOS_STATUS    VOS_SetPriority(TASK_ID TaskId, SWORD32 newPriority);
+	SWORD32       VOS_GetPriority(TASK_ID TaskId);
+
+	VOS_STATUS    VOS_DelayTask(SWORD32 delayTime);
+	TASK_ID       VOS_GetSelfTaskID(VOID);
+	VOS_STATUS    VOS_SuspendSelf(VOID);
+
+	VOS_TASK_STATUS VOS_GetTaskStatus(TASK_ID taskId);
+	VOID          VOS_CheckStack(TASK_ID taskId);
+
+
+	/************** 二进制信号量与计数信号量 *****************/
+	SEM_ID        VOS_CreateBSem(SWORD32 options, VOS_SEM_STATE initialState);
+	SEM_ID        VOS_CreateCSem(SWORD32 options, SWORD32 initialState);
+	SEM_ID        VOS_CreateMSem(SWORD32 options);
+	VOS_STATUS    VOS_DeleteSem(SEM_ID semId);
+	VOS_STATUS    VOS_TakeSem(SEM_ID semId, SWORD32 timeout);
+	VOS_STATUS    VOS_GiveSem(SEM_ID semId);
+
+
+	/**************** 内存管理模块 ***************************/
+	MEMPART_ID    VOS_CreateMemPart(CHAR *pPool, WORD32 poolSize);
+	VOID         *VOS_AllocMemPart(MEMPART_ID memPartId, WORD32 size);
+	VOS_STATUS    VOS_FreeMemPart(MEMPART_ID memPartId, CHAR *pBlock);
+
+	CHAR         *VOS_GetPhysMemTop(VOID);
+	WORD32        VOS_GetRnFreeInfo(WORD32 dwRnId);
+
+	/********************* 中断处理 ******* ******************/
+	SWORD32       VOS_LockInt();
+	VOID          VOS_UnlockInt(SWORD32 dwLevel);
+
+
+	/********************* 消息队列 **************************/
+	MSG_Q_ID      VOS_CreateMsgQue(WORD32 dwMaxMsgNum,
+		WORD32 dwMaxMsgLength,
+		BYTE ucOptions);
+	VOS_STATUS    VOS_DeleteMsgQue(MSG_Q_ID wMsgId);
+	VOS_STATUS    VOS_SendMsg(MSG_Q_ID wMsgId,
+		CHAR *pcMsgData,
+		WORD32 dwlen,
+		SWORD32 dwtimeout,
+		BYTE ucPrior);
+	WORD32        VOS_ReceiveMsg(MSG_Q_ID wMsgId,
+		CHAR  *pcMsgDataBuffer,
+		WORD32 dwlen,
+		SWORD32 iTimeout);
+	WORD32        VOS_GetCurMsgs(MSG_Q_ID wMsgId);
+
+
+	/********************* 时钟模块 **************************/
+	VOS_STATUS    VOS_ConnectClk(VOS_VOIDFUNCPTR clkIntEntry);
+	SWORD32       VOS_GetSysClkRate(VOID);
+	WORD32        VOS_GetTick();
+	VOS_STATUS    VOS_IniSysClk(T_SYS_CLOCK *pSysSoftClk);
+	VOS_STATUS    VOS_SetSysClkRate(SWORD32 sdTicPerSend);
+
+	VOS_STATUS    VOS_TimeSet(T_SYS_CLOCK *pSysSoftClk);
+	VOS_STATUS    VOS_TimeGet(T_SYS_CLOCK *pSysSoftClk);
+
+	VOS_TIMER_ID VOS_RelTimer(
+		WORD32 dwTimeLength, 
+		VOS_TIMERCALLBACK lpTimeProc,
+		WORD32 dwUser,
+		WORD32 dwEvents			 
+		);
+
+	VOS_TIMER_ID VOS_AbsTimer(
+		T_SYS_CLOCK tRelTimerSet, 
+		VOS_TIMERCALLBACK lpTimeProc,
+		WORD32 dwUser,
+		WORD32 dwEvents			 
+		);
+
+	VOS_TIMER_ID VOS_PerTimer(
+		WORD32 dwTimeLength, 			 
+		VOS_TIMERCALLBACK lpTimeProc,
+		WORD32 dwUser,
+		WORD32 dwEvents			 
+		);
+
+	VOS_STATUS   VOS_TimerKill(VOS_TIMER_ID TimerId);
+
+
+	/********************* 错误异常 **************************/
+	SWORD32       VOS_GetErrno(VOID);
+	VOID          VOS_AddExcHook(VOS_FUNCPTR excHookEntry);
+
+	/********************* 初始化VOS *************************/
+	VOS_STATUS    VOS_InitVOS(VOID);
+
+
+	/****************** 当前进程PCB操作 **********************/
+	VOS_STATUS    VOS_SetCurPCBIndex(WORD16  wIndex);
+	WORD16        VOS_GetCurPCBIndex(VOID);
+	VOS_STATUS    VOS_FreeTlsData(VOID);
+
+	/******************      事件模块   **********************/
+	VOS_STATUS    VOS_SendEvent(TASK_ID taskId, WORD32 dwEvents);
+	VOS_STATUS    VOS_ReceiveEvent(WORD32 dwEvents, WORD32 dwTimeout,
+		WORD32 *ptEventsR);
+
+
+	/******************  调试打印函数  **********************/
+	VOID          VOS_Display(const CHAR *fmt, ... );
+
+
+	/********************文件系统模块**********************/
+	SWORD32       VOS_Create(CHAR *pcFileName);
+	VOS_STATUS    VOS_Delete(CHAR *pcFileName);
+	SWORD32       VOS_Open(CHAR *pcFileName,SWORD32 sdwFlag,SWORD32 sdwMode);
+	VOS_STATUS    VOS_Close(SWORD32 sdwFileHandle);
+	VOS_STATUS    VOS_Rename(CHAR *pcOldFileName,CHAR *pcNewFileName);
+	SWORD32       VOS_Read(SWORD32 sdFileHandle,VOID *pBuffer,SWORD32 sdCount);
+	SWORD32       VOS_Write(SWORD32 sdFileHandle,VOID *pBuffer,SWORD32 sdCount);
+	SWORD32       VOS_FileLength(CHAR *pcFileName);
+	SWORD32       VOS_Lseek(SWORD32 sdFileHandle,SWORD32 sdOffset,SWORD32 sdOrigin);
+	VOS_STATUS    VOS_CreateDir(CHAR *pcDirName);
+	VOS_STATUS    VOS_DeleteDir(CHAR *pcDirName);
+	VOS_STATUS    VOS_RenameDir(CHAR *pcOldDirName,CHAR *pcNewDirName);
+	DIR           *VOS_OpenDir(CHAR *pcDirName);
+	struct dirent *VOS_ReadDir(DIR *pDir);
+	VOS_STATUS    VOS_CloseDir(DIR *pDir);
+	VOS_STATUS    VOS_Stat(CHAR *pcFileName, T_FileStat *pStat);
+	VOS_STATUS    VOS_CreateMemDev(CHAR      *pcRamDiskName,
+		CHAR      *pcRamAddr,
+		SWORD32   sdwCHARsPerBlk,
+		SWORD32   sdwBlksPerTrack,
+		SWORD32   sdwNBlocks,
+		SWORD32   sdwBlkOffset);
+	VOS_STATUS    VOS_StartFtpServer(LPVOID   pLoginRtn,
+		SWORD32  sdwStackSize);
+
+	VOS_STATUS    VOS_StopFtpServer(VOID);
+
+#if OS_TYPE == OS_PSOS
+	VOS_STATUS    VOS_FileSystemInit(VOID);
+#endif
+
+	/****************** SOCKET **********************/
+	VOS_STATUS  VOS_InitSocketLib(VOID);
+	SOCKET      VOS_Socket(SWORD32 family, SWORD32 type,SWORD32 protocol );
+	VOS_STATUS  VOS_Bind(SWORD32 s, const struct sockaddr * name,  SWORD32 namelen);
+	VOS_STATUS  VOS_Accept(SOCKET s ,struct sockaddr * addr,SWORD32* addrlen );
+	VOS_STATUS  VOS_Listen(SOCKET s ,SWORD32 backlog );
+	SWORD32     VOS_Send(SOCKET s,const char * buffer,SWORD32 len, SWORD32 flags);
+	SWORD32     VOS_Recv(SOCKET s,const char * buffer,SWORD32 len,SWORD32 flags);
+	VOS_STATUS  VOS_CloseSocket(SOCKET s);
+	VOS_STATUS  VOS_CleanUp(void);
+	VOS_STATUS  VOS_ConnectWithTimeout(SOCKET s,  struct sockaddr * adrs,  int adrsLen,
+	struct timeval *  timeVal );
+	SWORD32     VOS_SendTo(SOCKET s,const char *buffer,SWORD32 len, SWORD32 flags,
+	struct sockaddr *to, int tolen );
+	SWORD32     VOS_SendSocketMsg(SOCKET s,  struct msghdr  *mp, SWORD32 flags);
+	SWORD32     VOS_RecvFrom(SOCKET s,const char *buffer,SWORD32 len, SWORD32 flags,
+	struct sockaddr *from, int  * pFromLen);
+	SWORD32     VOS_RecvSocketMsg(SOCKET s,  struct msghdr  *mp, SWORD32 flags);
+	VOS_STATUS  VOS_Shutdown(SOCKET s, int how);
+	VOS_STATUS  VOS_SetSockOpt (SOCKET s,  int level,  int  optname, char * optval, int optlen );
+	VOS_STATUS  VOS_GetSockOpt (SOCKET s,  int level,  int  optname, char * optval, int *optlen );
+	VOS_STATUS  VOS_GetSockName(SOCKET s,   struct sockaddr * name,   int * namelen);
+	VOS_STATUS  VOS_GetPeerName (SOCKET s, struct sockaddr * name, int * namelen);
+	SWORD32     VOS_Select(int width, fd_set  *pReadFds, fd_set  * pWriteFds,
+		fd_set * pExceptFds, struct timeval * pTimeOut);
+	SWORD32     VOS_Ioctl(int fd, int function,int arg);
+
+	/****************** Exec **********************/
+	VOS_STATUS VOS_Exec(
+		const CHAR * strFile,		///要执行的程序名称
+		const CHAR * strArgs		///要传入的命令行参数
+		);
+
+	VOS_STATUS VOS_ExecByFork(
+		const CHAR * strFile,	///要执行的程序名称
+		const CHAR * strArgs	///要传入的命令行参数
+		);
+
+	VOS_STATUS VOS_ForceDelete(CHAR *pcFileName);
+
+	SWORD32 VOS_Chmod(
+		const CHAR * pcFileName, ///文件名
+		int iPermissions         ///要进行设置的文件属性
+		);
+
+	VOS_STATUS VOS_SetRLimit(const int iCoreFileSize);
+
+	VOS_STATUS VOS_GetTimeOfDay(struct timeval *tv, struct timezone *tz);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
+/************** End of vos.h *******************************************/

+ 238 - 0
scbc.tools/Log4C/log4c/voscfg.h

@@ -0,0 +1,238 @@
+/************** Begin of voscfg.h *******************************************/
+/**********************************************************
+* 版权所有 (C)2002, 深圳市中兴通讯股份有限公司。
+*
+* 文件名称: voscfg.h
+* 文件标识:
+* 内容摘要: VOS的系统配置文件
+* 其它说明: 无
+* 当前版本: v1.0
+* 作    者: 谢鑫
+* 完成日期: 2004.02.27
+*
+* 修改记录1:
+*    修改日期:
+*    版 本 号:
+*    修 改 人:
+*    修改内容:
+**********************************************************/
+
+#ifndef _VOSCFG_H
+#define _VOSCFG_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+	/*******************************************************
+	*                       基本配置
+	*******************************************************/
+
+	/* CPU类型 */
+#define   CPU_X86             0x1
+#define   CPU_PPC             0x2
+#define   CPU_ARM             0x3
+#define   CPU_TYPE            CPU_X86
+
+#undef	OS_LINUX	
+#undef  OS_WINNT
+	/* 操作系统OS类型 */
+#define   OS_VXWORKS          0x1
+#define   OS_WINNT            0x2
+#define   OS_PSOS             0x3
+#define   OS_LINUX            0x4
+#define   OS_KLINUX           0x5
+
+	///added by wenhm in 2005.08.25
+#ifdef _WIN32
+#define   OS_TYPE             OS_WINNT
+#else #ifdef   linux
+#define   OS_TYPE			  OS_LINUX
+#endif
+
+
+	/* linux适配 */
+#define    VXWORKS_TO_LINUX
+#ifndef    VXWORKS_TO_LINUX
+#define    PSOS_TO_LINUX
+#endif
+#if ( OS_TYPE == OS_KLINUX)
+#define  _USE_TIMER_IRQ
+#endif
+
+	/*********************************************************
+	基本包含文件                        
+	**********************************************************/
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <assert.h>
+
+#if OS_TYPE == OS_PSOS
+#include <psos.h>
+#include <phile.h>
+#include <pna.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <time.h>
+#include <sys_conf.h>
+#include <types.h>
+#include <socket.h>
+#endif
+
+#if  OS_TYPE == OS_VXWORKS
+#include <vxWorks.h>
+#include <sysLib.h>
+#include <taskLib.h>    
+#include <msgQLib.h>
+#include <semLib.h>
+#include <vmLib.h>
+#include <dosfslib.h>
+#include <iolib.h>
+#include <dirent.h>
+#include <stat.h>
+#include <errnoLib.h>
+#include <types.h>
+#include <socket.h>
+#include <socklib.h>
+#include <logLib.h>
+#include <assert.h>
+#include <symlib.h>
+#include <sysSymTbl.h>
+#include <excLib.h>
+#include <esf.h>
+#include <memLib.h>
+#include <tickLib.h>
+#include <private\memPartLibP.h>
+#include <in.h>
+#include <ramDrv.h>
+#include <ftpdLib.h>
+#include <cachelib.h>
+#include <signal.h>
+#include <sigLib.h>
+#include <time.h>
+#include <wdLib.h>
+#include <intLib.h>
+#include <timers.h>
+#include "inetLib.h"
+#include "netinet\tcp.h"
+#include "fcntl.h"
+#include "netinet/in.h"
+#include "end.h"
+#include "zbufSockLib.h"
+#include <routeLib.h>
+#include <usrLib.h>
+#endif
+
+#if OS_TYPE == OS_WINNT
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+#include <process.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <memory.h>
+#include <tchar.h>
+#include <imagehlp.h>
+#include <io.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <direct.h>
+#include <Winsock.h>
+#include <time.h>
+	///#include <Winsock2.h>
+#pragma comment(lib, "imagehlp.lib")
+#pragma comment(lib,"Winmm.lib")
+#endif
+
+#if OS_TYPE == OS_LINUX
+#ifdef VXWORKS_TO_LINUX
+	///#include "vxw_hdrs.h"
+#else
+	///#include "psos_hdrs.h"
+#endif
+#include <time.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <asm/ioctls.h>
+#include <netinet/tcp.h>
+#include <sys/select.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <asm/errno.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <string.h> 
+#include <unistd.h>
+#include <netinet/in.h>    
+#include <signal.h>
+#include <stdio.h>
+#include <dirent.h>
+#include <semaphore.h>    
+#endif
+
+#if OS_TYPE == OS_KLINUX
+#include "kth.h"
+	/*	#include "ksocket.h"*/
+#include <stdio.h>
+#include "ktm.h"
+#include <netinet/tcp.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/ip.h>
+#include <netinet/in.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <arpa/inet.h>
+	/*	#include "kfile.h"*/
+	/*	#include <linux/vmalloc.h>*/
+#endif
+
+
+	/*********************************************************
+	基本数据类型                        
+	**********************************************************/
+#if OS_TYPE != OS_WINNT
+	typedef  unsigned char    BYTE;
+#endif
+
+	typedef  unsigned char    BOOLEAN;
+	typedef  char             CHAR;
+	typedef  void            *LPVOID;
+	typedef  unsigned short   WORD16;
+	typedef  unsigned long    WORD32;
+	typedef  signed short     SWORD16;
+	///typedef  signed long      SWORD32;
+
+#ifndef SWORD32
+#ifdef  WIN32
+	typedef long                SWORD32; 
+#else
+#define SWORD32            long
+#endif		
+#endif
+
+#define  INVALID_BYTE     (unsigned char)0xff
+#define  INVALID_WORD     (unsigned short)0xffff
+#define  INVALID_DWORD    (unsigned long)0xffffffff 
+
+	typedef  long             OSS_STATUS;
+#define  OSS_OK           0
+#define  OSS_ERROR        -1
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
+
+/************** End of voscfg.h *******************************************/

+ 19 - 0
scbc.tools/Log4C/sd/defs.h

@@ -0,0 +1,19 @@
+/* $Id$
+ *
+ * Copyright 2001-2003, Meiosys (www.meiosys.com). All rights reserved.
+ *
+ * See the COPYING file for the terms of usage and distribution.
+ */
+
+#ifndef __sd_defs_h
+#define __sd_defs_h
+
+#ifdef  __cplusplus
+# define __SD_BEGIN_DECLS  extern "C" {
+# define __SD_END_DECLS    }
+#else
+# define __SD_BEGIN_DECLS
+# define __SD_END_DECLS
+#endif
+
+#endif

+ 21 - 0
scbc.tools/Log4C/sd/domnode-xml-parser.h

@@ -0,0 +1,21 @@
+#ifndef BISON_DOMNODE_XML_PARSER_H
+# define BISON_DOMNODE_XML_PARSER_H
+
+#ifndef YYSTYPE
+typedef union { char *s; } yystype;
+# define YYSTYPE yystype
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+# define	ENDDEF	257
+# define	EQ	258
+# define	SLASH	259
+# define	CLOSE	260
+# define	END	261
+# define	NAME	262
+# define	VALUE	263
+# define	DATA	264
+# define	COMMENT	265
+# define	START	266
+
+
+#endif /* not BISON_DOMNODE_XML_PARSER_H */

+ 882 - 0
scbc.tools/Log4C/sd/domnode-xml-scanner.h

@@ -0,0 +1,882 @@
+#ifndef __sd_domnode_xml_HEADER_H
+#define __sd_domnode_xml_HEADER_H 1
+#define __sd_domnode_xml_IN_HEADER 1
+
+#define YY_REENTRANT 1
+#define YY_BISON_BRIDGE 1
+#ifndef YY_REENTRANT
+#define yytext __sd_domnode_xml_text
+#define yyleng __sd_domnode_xml_leng
+#define yyin __sd_domnode_xml_in
+#define yyout __sd_domnode_xml_out
+#define yy_flex_debug __sd_domnode_xml__flex_debug
+#endif
+#define yy_create_buffer __sd_domnode_xml__create_buffer
+#define yy_delete_buffer __sd_domnode_xml__delete_buffer
+#define yy_scan_buffer __sd_domnode_xml__scan_buffer
+#define yy_scan_string __sd_domnode_xml__scan_string
+#define yy_scan_bytes __sd_domnode_xml__scan_bytes
+#define yy_init_buffer __sd_domnode_xml__init_buffer
+#define yy_flush_buffer __sd_domnode_xml__flush_buffer
+#define yy_load_buffer_state __sd_domnode_xml__load_buffer_state
+#define yy_switch_to_buffer __sd_domnode_xml__switch_to_buffer
+#define yylex __sd_domnode_xml_lex
+#define yyrestart __sd_domnode_xml_restart
+#define yylex_init __sd_domnode_xml_lex_init
+#define yylex_destroy __sd_domnode_xml_lex_destroy
+#define yyget_debug __sd_domnode_xml_get_debug
+#define yyset_debug __sd_domnode_xml_set_debug
+#define yyget_extra __sd_domnode_xml_get_extra
+#define yyset_extra __sd_domnode_xml_set_extra
+#define yyget_in __sd_domnode_xml_get_in
+#define yyset_in __sd_domnode_xml_set_in
+#define yyget_out __sd_domnode_xml_get_out
+#define yyset_out __sd_domnode_xml_set_out
+#define yyget_leng __sd_domnode_xml_get_leng
+#define yyget_text __sd_domnode_xml_get_text
+#define yyget_lineno __sd_domnode_xml_get_lineno
+#define yyset_lineno __sd_domnode_xml_set_lineno
+#ifdef YY_BISON_BRIDGE
+#define yyget_lval __sd_domnode_xml_get_lval
+#define yyset_lval __sd_domnode_xml_set_lval
+#define yyget_lloc __sd_domnode_xml_get_lloc
+#define yyset_lloc __sd_domnode_xml_set_lloc
+#endif
+#define yyalloc __sd_domnode_xml_alloc
+#define yyrealloc __sd_domnode_xml_realloc
+#define yyfree __sd_domnode_xml_free
+
+#line 50 "domnode-xml-scanner.h"
+#define  YY_INT_ALIGNED short int
+
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 27
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+#include <sd/sd_xplatform.h>
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t; 
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN               (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN              (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN              (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX               (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX              (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX              (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX              (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX             (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX             (4294967295U)
+#endif
+
+
+#endif /* ! FLEXINT_H */
+
+
+
+#ifdef __cplusplus
+
+/* C++ compilers don't understand traditional function definitions. */
+#ifdef YY_TRADITIONAL_FUNC_DEFS
+#undef YY_TRADITIONAL_FUNC_DEFS
+#endif
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else	/* ! __cplusplus */
+
+/* We're not in a C++ compiler, so by default,
+   we generate C99 function defs, unless you explicitly ask
+   for traditional defs by defining YY_TRADITIONAL_FUNC_DEFS */
+
+#if __STDC__
+
+#define YY_USE_CONST
+
+#endif	/* __STDC__ */
+#endif	/* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* For compilers that can't handle prototypes.
+ * e.g.,
+ * The function prototype
+ *    int foo(int x, char* y);
+ *
+ * ...should be written as
+ *    int foo YY_PARAMS((int x, char* y));
+ *
+ * ...which could possibly generate
+ *    int foo ();
+ */
+#ifdef YY_NO_PROTOS
+#define YY_PARAMS(proto) ()
+#else
+#define YY_PARAMS(proto) proto
+#endif
+
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index.  If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+
+/* An opaque pointer. */
+#ifndef YY_TYPEDEF_YY_SCANNER_T
+#define YY_TYPEDEF_YY_SCANNER_T
+typedef void* yyscan_t;
+#endif
+
+/* For use wherever a Global is accessed or assigned. */
+#define YY_G(var) (((struct yyguts_t*)yyscanner)->var)
+
+/* For use in function prototypes to append the additional argument. */
+#define YY_PROTO_LAST_ARG , yyscan_t yyscanner
+#define YY_PROTO_ONLY_ARG    yyscan_t yyscanner
+
+/* For use in function definitions to append the additional argument. */
+#ifdef YY_TRADITIONAL_FUNC_DEFS
+#define YY_DEF_LAST_ARG , yyscanner
+#define YY_DEF_ONLY_ARG    yyscanner
+#else
+#define YY_DEF_LAST_ARG , yyscan_t yyscanner
+#define YY_DEF_ONLY_ARG   yyscan_t yyscanner
+#endif
+#define YY_DECL_LAST_ARG yyscan_t yyscanner;
+
+/* For use in function calls to pass the additional argument. */
+#define YY_CALL_LAST_ARG  , yyscanner
+#define YY_CALL_ONLY_ARG   yyscanner
+
+/* For convenience, these vars (plus the bison vars far below)
+   are macros in the reentrant scanner. */
+#define yyin YY_G(yyin_r)
+#define yyout YY_G(yyout_r)
+#define yyextra YY_G(yyextra_r)
+#define yyleng YY_G(yyleng_r)
+#define yytext YY_G(yytext_r)
+#define yylineno YY_G(yylineno_r)
+#define yy_flex_debug YY_G(yy_flex_debug_r)
+
+int yylex_init YY_PARAMS((yyscan_t* scanner));
+
+
+
+/* For compilers that need traditional function definitions.
+ * e.g.,
+ * The function prototype taking 2 arguments
+ *    int foo (int x, char* y)
+ *
+ * ...should be written as
+ *    int foo YYFARGS2(int,x, char*,y)
+ *
+ * ...which could possibly generate
+ *    int foo (x,y,yyscanner)
+ *        int x;
+ *        char * y;
+ *        yyscan_t yyscanner;
+ */
+#ifdef YY_TRADITIONAL_FUNC_DEFS
+/* Generate traditional function defs */
+#define YYFARGS0(v) (YY_DEF_ONLY_ARG) YY_DECL_LAST_ARG
+#define YYFARGS1(t1,n1) (n1 YY_DEF_LAST_ARG) t1 n1; YY_DECL_LAST_ARG
+#define YYFARGS2(t1,n1,t2,n2) (n1,n2 YY_DEF_LAST_ARG) t1 n1; t2 n2; YY_DECL_LAST_ARG
+#define YYFARGS3(t1,n1,t2,n2,t3,n3) (n1,n2,n3 YY_DEF_LAST_ARG) t1 n1; t2 n2; t3 n3; YY_DECL_LAST_ARG
+#else
+/* Generate C99 function defs. */
+#define YYFARGS0(v) (YY_DEF_ONLY_ARG)
+#define YYFARGS1(t1,n1) (t1 n1 YY_DEF_LAST_ARG)
+#define YYFARGS2(t1,n1,t2,n2) (t1 n1,t2 n2 YY_DEF_LAST_ARG)
+#define YYFARGS3(t1,n1,t2,n2,t3,n3) (t1 n1,t2 n2,t3 n3 YY_DEF_LAST_ARG)
+#endif
+
+/* Enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN YY_G(yy_start) = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((YY_G(yy_start) - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart( yyin YY_CALL_LAST_ARG )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#define YY_BUF_SIZE 16384
+#endif
+
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+#ifdef YY_USE_LINENO
+/* Note: We specifically omit the test for yy_rule_can_match_eol because it requires
+ *       access to the local variable yy_act. Since yyless() is a macro, it would break
+ *       existing scanners that call yyless() from OUTSIDE yylex. 
+ *       One obvious solution it to make yy_act a global. I tried that, and saw
+ *       a 5% performance hit in a non-yylineno scanner, because yy_act is
+ *       normally declared as a register variable-- so it's not worth it.
+ */
+#define  YY_LESS_LINENO(n) \
+        do { \
+			int yyl;\
+			for ( yyl = n; yyl < yyleng; ++yyl )\
+				if ( yytext[yyl] == '\n' )\
+					--yylineno;\
+        }while(0)
+#else
+#define YY_LESS_LINENO(n)
+#endif
+
+/* The funky do-while in the following #define is used to turn the definition
+ * int a single C statement (which needs a semi-colon terminator).  This
+ * avoids problems with code like:
+ *
+ * 	if ( condition_holds )
+ *		yyless( 5 );
+ *	else
+ *		do_something_else();
+ *
+ * Prior to using the do-while the compiler would get upset at the
+ * "else" because it interpreted the "if" statement as being all
+ * done when it reached the ';' after the yyless() call.
+ */
+
+/* Return all but the first 'n' matched characters back to the input stream. */
+
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		*yy_cp = YY_G(yy_hold_char); \
+		YY_RESTORE_YY_MORE_OFFSET \
+		YY_G(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+		} \
+	while ( 0 )
+
+#define unput(c) yyunput( c, YY_G(yytext_ptr) YY_CALL_LAST_ARG )
+
+/* The following is because we cannot portably get our hands on size_t
+ * (without autoconf's help, which isn't available because we want
+ * flex-generated scanners to compile on their own).
+ */
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef unsigned int yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+	{
+	FILE *yy_input_file;
+
+
+
+	char *yy_ch_buf;		/* input buffer */
+	char *yy_buf_pos;		/* current position in input buffer */
+
+	/* Size of input buffer in bytes, not including room for EOB
+	 * characters.
+	 */
+	yy_size_t yy_buf_size;
+
+	/* Number of characters read into yy_ch_buf, not including EOB
+	 * characters.
+	 */
+	int yy_n_chars;
+
+	/* Whether we "own" the buffer - i.e., we know we created it,
+	 * and can realloc() it to grow it, and should free() it to
+	 * delete it.
+	 */
+	int yy_is_our_buffer;
+
+	/* Whether this is an "interactive" input source; if so, and
+	 * if we're using stdio for input, then we want to use getc()
+	 * instead of fread(), to make sure we stop fetching input after
+	 * each newline.
+	 */
+	int yy_is_interactive;
+
+	/* Whether we're considered to be at the beginning of a line.
+	 * If so, '^' rules will be active on the next match, otherwise
+	 * not.
+	 */
+	int yy_at_bol;
+
+	/* Whether to try to fill the input buffer when we reach the
+	 * end of it.
+	 */
+	int yy_fill_buffer;
+
+	int yy_buffer_status;
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+	/* When an EOF's been seen but there's still some text to process
+	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+	 * shouldn't try reading from the input source any more.  We might
+	 * still have a bunch of tokens to match, though, because of
+	 * possible backing-up.
+	 *
+	 * When we actually see the EOF, we change the status to "new"
+	 * (via yyrestart()), so that the user can continue scanning by
+	 * just pointing yyin at a new input file.
+	 */
+#define YY_BUFFER_EOF_PENDING 2
+	};
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ */
+#define YY_CURRENT_BUFFER yy_current_buffer
+
+
+
+void yyrestart YY_PARAMS(( FILE *input_file YY_PROTO_LAST_ARG ));
+
+
+void yy_switch_to_buffer YY_PARAMS(( YY_BUFFER_STATE new_buffer YY_PROTO_LAST_ARG ));
+void yy_load_buffer_state YY_PARAMS(( YY_PROTO_ONLY_ARG ));
+YY_BUFFER_STATE yy_create_buffer YY_PARAMS(( FILE *file, int size YY_PROTO_LAST_ARG ));
+void yy_delete_buffer YY_PARAMS(( YY_BUFFER_STATE b YY_PROTO_LAST_ARG ));
+void yy_init_buffer YY_PARAMS(( YY_BUFFER_STATE b, FILE *file YY_PROTO_LAST_ARG ));
+void yy_flush_buffer YY_PARAMS(( YY_BUFFER_STATE b YY_PROTO_LAST_ARG ));
+
+#define YY_FLUSH_BUFFER yy_flush_buffer( YY_G(yy_current_buffer) YY_CALL_LAST_ARG)
+
+YY_BUFFER_STATE yy_scan_buffer YY_PARAMS(( char *base, yy_size_t size YY_PROTO_LAST_ARG ));
+YY_BUFFER_STATE yy_scan_string YY_PARAMS(( yyconst char *yy_str YY_PROTO_LAST_ARG ));
+YY_BUFFER_STATE yy_scan_bytes YY_PARAMS(( yyconst char *bytes, int len YY_PROTO_LAST_ARG ));
+
+
+void *yyalloc YY_PARAMS(( yy_size_t YY_PROTO_LAST_ARG ));
+void *yyrealloc YY_PARAMS(( void *, yy_size_t YY_PROTO_LAST_ARG ));
+void yyfree YY_PARAMS(( void * YY_PROTO_LAST_ARG ));
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+	{ \
+	if ( ! YY_G(yy_current_buffer) ) \
+		YY_G(yy_current_buffer) =    \
+            yy_create_buffer( yyin, YY_BUF_SIZE YY_CALL_LAST_ARG); \
+	YY_G(yy_current_buffer)->yy_is_interactive = is_interactive; \
+	}
+
+#define yy_set_bol(at_bol) \
+	{ \
+	if ( ! YY_G(yy_current_buffer) ) \
+		YY_G(yy_current_buffer) =    \
+            yy_create_buffer( yyin, YY_BUF_SIZE YY_CALL_LAST_ARG); \
+	YY_G(yy_current_buffer)->yy_at_bol = at_bol; \
+	}
+
+#define YY_AT_BOL() (YY_G(yy_current_buffer)->yy_at_bol)
+
+
+#define yywrap(n) 1
+#define YY_SKIP_YYWRAP
+#define yytext_ptr yytext_r
+
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+	YY_G(yytext_ptr) = yy_bp; \
+	yyleng = (size_t) (yy_cp - yy_bp); \
+	YY_G(yy_hold_char) = *yy_cp; \
+	*yy_cp = '\0'; \
+	YY_G(yy_c_buf_p) = yy_cp;
+
+
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#ifndef YY_NO_UNISTD_H
+#include <unistd.h>
+#endif /* !YY_NO_UNISTD_H */
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+
+
+
+
+
+/* Accessor methods to globals.
+   These are made visible to non-reentrant scanners for convenience. */
+
+#ifndef YY_NO_DESTROY
+int yylex_destroy YY_PARAMS(( YY_PROTO_ONLY_ARG ));
+#endif
+
+#ifndef YY_NO_GET_DEBUG
+int yyget_debug YY_PARAMS(( YY_PROTO_ONLY_ARG ));
+#endif
+
+#ifndef YY_NO_SET_DEBUG
+void yyset_debug YY_PARAMS(( int debug_flag YY_PROTO_LAST_ARG ));
+#endif
+
+#ifndef YY_NO_GET_EXTRA
+YY_EXTRA_TYPE yyget_extra YY_PARAMS(( YY_PROTO_ONLY_ARG ));
+#endif
+
+#ifndef YY_NO_SET_EXTRA
+void yyset_extra YY_PARAMS(( YY_EXTRA_TYPE user_defined YY_PROTO_LAST_ARG ));
+#endif
+
+#ifndef YY_NO_GET_IN
+FILE *yyget_in YY_PARAMS(( YY_PROTO_ONLY_ARG ));
+#endif
+
+#ifndef YY_NO_SET_IN
+void yyset_in  YY_PARAMS(( FILE * in_str YY_PROTO_LAST_ARG ));
+#endif
+
+#ifndef YY_NO_GET_OUT
+FILE *yyget_out YY_PARAMS(( YY_PROTO_ONLY_ARG ));
+#endif
+
+#ifndef YY_NO_SET_OUT
+void yyset_out  YY_PARAMS(( FILE * out_str YY_PROTO_LAST_ARG ));
+#endif
+
+#ifndef YY_NO_GET_LENG
+int yyget_leng YY_PARAMS(( YY_PROTO_ONLY_ARG ));
+#endif
+
+#ifndef YY_NO_GET_TEXT
+char *yyget_text YY_PARAMS(( YY_PROTO_ONLY_ARG ));
+#endif
+
+#ifndef YY_NO_GET_LINENO
+int yyget_lineno YY_PARAMS(( YY_PROTO_ONLY_ARG ));
+#endif
+
+#ifndef YY_NO_SET_LINENO
+void yyset_lineno YY_PARAMS(( int line_number YY_PROTO_LAST_ARG ));
+#endif
+
+#ifndef YY_NO_GET_LVAL
+YYSTYPE * yyget_lval YY_PARAMS(( YY_PROTO_ONLY_ARG ));
+#endif
+void yyset_lval YY_PARAMS(( YYSTYPE * yylvalp YY_PROTO_LAST_ARG ));
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+#ifndef YY_NO_GET_LLOC
+   YYLTYPE *yyget_lloc YY_PARAMS(( YY_PROTO_ONLY_ARG ));
+#endif
+#ifndef YY_NO_SET_LLOC
+    void yyset_lloc YY_PARAMS(( YYLTYPE * yyllocp YY_PROTO_LAST_ARG ));
+#endif
+#endif /* YYLTYPE */
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap YY_PARAMS(( YY_PROTO_ONLY_ARG ));
+#else
+extern int yywrap YY_PARAMS(( YY_PROTO_ONLY_ARG ));
+#endif
+#endif
+
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy YY_PARAMS(( char *, yyconst char *, int YY_PROTO_LAST_ARG));
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen YY_PARAMS(( yyconst char * YY_PROTO_LAST_ARG));
+#endif
+
+#ifndef YY_NO_INPUT
+#endif
+
+
+#if YY_STACK_USED
+
+#ifndef YY_NO_PUSH_STATE
+static void yy_push_state YY_PARAMS(( int new_state YY_PROTO_LAST_ARG));
+#endif
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state YY_PARAMS(( YY_PROTO_ONLY_ARG ));
+#endif
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state YY_PARAMS(( YY_PROTO_ONLY_ARG ));
+#endif
+
+#else
+#define YY_NO_PUSH_STATE 1
+#define YY_NO_POP_STATE 1
+#define YY_NO_TOP_STATE 1
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+	errno=0; \
+	while ( (result = read( fileno(yyin), (char *) buf, max_size )) < 0 ) \
+	{ \
+		if( errno != EINTR) \
+		{ \
+			YY_FATAL_ERROR( "input in flex scanner failed" ); \
+			break; \
+		} \
+		errno=0; \
+		clearerr(yyin); \
+	}
+\
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg YY_CALL_LAST_ARG)
+#endif
+
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+
+/* If the bison pure parser is used, then bison will provide
+   one or two additional arguments. */
+
+#  if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+#        define YY_LEX_PROTO YY_PARAMS((YYSTYPE * yylvalp, YYLTYPE * yyllocp YY_PROTO_LAST_ARG))
+#        define YY_LEX_DECLARATION YYFARGS2(YYSTYPE *,yylvalp, YYLTYPE *,yyllocp)
+#  else
+#        define YY_LEX_PROTO YY_PARAMS((YYSTYPE * yylvalp YY_PROTO_LAST_ARG))
+#        define YY_LEX_DECLARATION YYFARGS1(YYSTYPE *,yylvalp)
+#  endif
+
+
+
+extern int yylex YY_LEX_PROTO;
+
+#define YY_DECL int yylex YY_LEX_DECLARATION
+#endif
+
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+	YY_USER_ACTION
+
+
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ *	EOB_ACT_LAST_MATCH -
+ *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *	EOB_ACT_END_OF_FILE - end of file
+ */
+
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+#line 135 "../../../src/sd/domnode-xml-scanner.l"
+#line 719 "domnode-xml-scanner.h"
+#ifdef YY_HEADER_EXPORT_START_CONDITIONS
+/* Beware! Start conditions are not prefixed. */
+#undef INITIAL
+#define INITIAL 0
+#define CONTENT 1
+#endif /* YY_HEADER_EXPORT_START_CONDITIONS */
+
+#ifndef YY_HEADER_NO_UNDEFS
+/* Undefine all internal macros, etc., that do no belong in the header. */
+
+#undef BEGIN
+#undef ECHO
+#undef EOB_ACT_CONTINUE_SCAN
+#undef EOB_ACT_END_OF_FILE
+#undef EOB_ACT_LAST_MATCH
+#undef FLEX_SCANNER
+#undef FLEX_STD
+#undef REJECT
+#undef YYLMAX
+#undef YYSTATE
+#undef YY_AT_BOL
+#undef YY_BREAK
+#undef YY_BUFFER_EOF_PENDING
+#undef YY_BUFFER_NEW
+#undef YY_BUFFER_NORMAL
+#undef YY_BUF_SIZE
+#undef YY_CALL_LAST_ARG
+#undef YY_CALL_ONLY_ARG
+#undef YY_CURRENT_BUFFER
+#undef YY_DECL
+#undef YY_DECL_LAST_ARG
+#undef YY_DO_BEFORE_ACTION
+#undef YY_END_OF_BUFFER
+#undef YY_END_OF_BUFFER_CHAR
+#undef YY_EXIT_FAILURE
+#undef YY_EXTRA_TYPE
+#undef YY_FATAL_ERROR
+#undef YY_FLEX_DEFINED_ECHO
+#undef YY_FLEX_LEX_COMPAT
+#undef YY_FLEX_MAJOR_VERSION
+#undef YY_FLEX_MINOR_VERSION
+#undef YY_FLUSH_BUFFER
+#undef YY_G
+#undef YY_INPUT
+#undef YY_INT_ALIGNED
+#undef YY_INTERACTIVE
+#undef YY_LAST_ARG
+#undef YY_LEX_ARGS
+#undef YY_MAIN
+#undef YY_MORE_ADJ
+#undef YY_NEED_STRLEN
+#undef YY_NEW_FILE
+#undef YY_NO_FLEX_ALLOC
+#undef YY_NO_FLEX_REALLOC
+#undef YY_NO_FLEX_FREE
+#undef YY_NO_GET_DEBUG
+#undef YY_NO_GET_EXTRA
+#undef YY_NO_GET_IN
+#undef YY_NO_GET_LENG
+#undef YY_NO_GET_LINENO
+#undef YY_NO_GET_LLOC
+#undef YY_NO_GET_LVAL
+#undef YY_NO_GET_OUT
+#undef YY_NO_GET_TEXT
+#undef YY_NO_INPUT
+#undef YY_NO_POP_STATE
+#undef YY_NO_PUSH_STATE
+#undef YY_NO_SCAN_BUFFER
+#undef YY_NO_SCAN_BYTES
+#undef YY_NO_SCAN_STRING
+#undef YY_NO_SET_DEBUG
+#undef YY_NO_SET_EXTRA
+#undef YY_NO_SET_IN
+#undef YY_NO_SET_LINENO
+#undef YY_NO_SET_LLOC
+#undef YY_NO_SET_LVAL
+#undef YY_NO_SET_OUT
+#undef YY_NO_TOP_STATE
+#undef YY_NO_UNISTD_H
+#undef YY_NO_UNPUT
+#undef YY_NULL
+#undef YY_NUM_RULES
+#undef YY_ONLY_ARG
+#undef YY_PROTO
+#undef YY_READ_BUF_SIZE
+#undef YY_REENTRANT
+#undef YY_BISON_BRIDGE
+#undef YY_RESTORE_YY_MORE_OFFSET
+#undef YY_RULE_SETUP
+#undef YY_SC_TO_UI
+#undef YY_SKIP_YYWRAP
+#undef YY_STACK_USED
+#undef YY_START
+#undef YY_START_STACK_INCR
+#undef YY_STATE_EOF
+#undef YY_STDINIT
+#undef YY_TEXT_IS_ARRAY
+#undef YY_TRAILING_HEAD_MASK
+#undef YY_TRAILING_MASK
+#undef YY_USER_ACTION
+#undef YY_USES_REJECT
+#undef YY_USE_CONST
+#undef YY_USE_LINENO
+#undef YY_USE_PROTOS
+#undef unput
+#undef yy_create_buffer
+#undef yy_delete_buffer
+#undef yy_flex_debug
+#undef yy_flush_buffer
+#undef yy_init_buffer
+#undef yy_load_buffer_state
+#undef yy_new_buffer
+#undef yy_scan_buffer
+#undef yy_scan_bytes
+#undef yy_scan_string
+#undef yy_set_bol
+#undef yy_set_interactive
+#undef yy_switch_to_buffer
+#undef yyconst
+#undef yyextra
+#undef yyget_debug
+#undef yyset_debug
+#undef yyget_extra
+#undef yyget_in
+#undef yyget_leng
+#undef yyget_lineno
+#undef yyget_lloc
+#undef yyget_lval
+#undef yyget_out
+#undef yyget_text
+#undef yyin
+#undef yyleng
+#undef yyless
+#undef yylex
+#undef yylex_destroy
+#undef yylex_init
+#undef yylineno
+#undef yylloc
+#undef yylval
+#undef yymore
+#undef yyout
+#undef yyrestart
+#undef yyset_extra
+#undef yyset_in
+#undef yyset_lineno
+#undef yyset_lloc
+#undef yyset_lval
+#undef yyset_out
+#undef yyterminate
+#undef yytext
+#undef yytext_ptr
+#undef yywrap
+#undef yyalloc
+#undef yyrealloc
+#undef yyfree
+#undef YY_NEVER_INTERACTIVE
+#undef YY_NO_UNPUT
+#undef YY_TABLES_VERIFY
+#endif /* !YY_HEADER_NO_UNDEFS */
+
+#undef __sd_domnode_xml_IN_HEADER
+#endif /* __sd_domnode_xml_HEADER_H */

+ 33 - 0
scbc.tools/Log4C/sd/domnode-xml.h

@@ -0,0 +1,33 @@
+/* $Id$
+ *
+ * Copyright 2001-2003, Meiosys (www.meiosys.com). All rights reserved.
+ * See the COPYING file for the terms of usage and distribution.
+ */
+
+#ifndef __sd_domnode_xml_h
+#define __sd_domnode_xml_h
+
+/**
+ * @file domnode-xml.h @ingroup sd
+ *
+ * @brief Private API for XML parsing.
+ */
+
+#include "domnode.h"
+#include "stack.h"
+
+struct __sd_domnode_xml_maker {
+    void*		scanner;
+    sd_stack_t*		elements;
+    sd_domnode_t*	root;
+};
+
+extern int __sd_domnode_xml_fread(sd_domnode_t** a_node, FILE* a_stream);
+extern int __sd_domnode_xml_fwrite(const sd_domnode_t* a_node, FILE* a_stream);
+
+extern int __sd_domnode_xml_read(sd_domnode_t** a_node, const char* a_buffer,
+				 size_t a_size);
+extern int __sd_domnode_xml_write(const sd_domnode_t* a_node, char** a_buffer,
+				  size_t* a_size);
+
+#endif

+ 65 - 0
scbc.tools/Log4C/sd/domnode.h

@@ -0,0 +1,65 @@
+/* $Id$
+ *
+ * Copyright 2001-2003, Meiosys (www.meiosys.com). All rights reserved.
+ * See the COPYING file for the terms of usage and distribution.
+ */
+
+#ifndef __sd_domnode_h
+#define __sd_domnode_h
+
+/**
+ * @file domnode.h @ingroup sd
+ *
+ * @brief Generic DOM object.
+ */
+
+#include <stdio.h>
+#include <sd/list.h>
+
+__SD_BEGIN_DECLS
+
+typedef struct {
+    const char*	name;
+    const char*	value;
+    sd_list_t*	children;
+    sd_list_t*	attrs;
+} sd_domnode_t;
+
+extern sd_domnode_t*	sd_domnode_new(const char* a_name,
+				       const char* a_value);
+
+extern void		sd_domnode_delete(sd_domnode_t* ptrThis);
+
+extern int		sd_domnode_read(sd_domnode_t* ptrThis,
+					const char* a_buffer, size_t asize);
+extern int		sd_domnode_write(sd_domnode_t* ptrThis, char** a_buffer,
+					 size_t* asize);
+
+extern int		sd_domnode_fread(sd_domnode_t* ptrThis, FILE* a_stream);
+extern int		sd_domnode_fwrite(const sd_domnode_t* ptrThis,
+					  FILE* a_stream);
+
+extern int		sd_domnode_load(sd_domnode_t* ptrThis,
+					const char* a_filename);
+
+extern int		sd_domnode_store(const sd_domnode_t* ptrThis, 
+					 const char* a_filename);
+
+extern sd_domnode_t*	sd_domnode_search(const sd_domnode_t* ptrThis,
+					  const char* a_name);
+
+extern sd_domnode_t* 	sd_domnode_attrs_put(sd_domnode_t* ptrThis,
+					     sd_domnode_t* a_attr);
+extern sd_domnode_t*	sd_domnode_attrs_get(const sd_domnode_t* ptrThis,
+					     const char* a_name);
+extern sd_domnode_t*	sd_domnode_attrs_remove(sd_domnode_t* ptrThis,
+						const char* a_name);
+
+/** Creates a new node. */
+extern sd_domnode_t* __sd_domnode_new(const char* name, const char* a_value,
+				      int is_elem);
+
+__SD_END_DECLS
+
+#endif
+

+ 16 - 0
scbc.tools/Log4C/sd/error.h

@@ -0,0 +1,16 @@
+/* $Id$
+ *
+ * Copyright 2001-2003, Meiosys (www.meiosys.com). All rights reserved.
+ *
+ * See the COPYING file for the terms of usage and distribution.
+ */
+
+#ifndef __sd_error_h
+#define __sd_error_h
+
+#include <stdarg.h>
+
+extern int sd_debug(const char *fmt, ...);
+extern int sd_error(const char *fmt, ...);
+
+#endif /* __sd_error_h */

+ 1014 - 0
scbc.tools/Log4C/sd/expat.h

@@ -0,0 +1,1014 @@
+/* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
+   See the file COPYING for copying permission.
+*/
+
+#ifndef Expat_INCLUDED
+#define Expat_INCLUDED 1
+
+#ifdef __VMS
+/*      0        1         2         3      0        1         2         3
+        1234567890123456789012345678901     1234567890123456789012345678901 */
+#define XML_SetProcessingInstructionHandler XML_SetProcessingInstrHandler
+#define XML_SetUnparsedEntityDeclHandler    XML_SetUnparsedEntDeclHandler
+#define XML_SetStartNamespaceDeclHandler    XML_SetStartNamespcDeclHandler
+#define XML_SetExternalEntityRefHandlerArg  XML_SetExternalEntRefHandlerArg
+#endif
+
+#include <stdlib.h>
+#include "expat_external.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct XML_ParserStruct;
+typedef struct XML_ParserStruct *XML_Parser;
+
+/* Should this be defined using stdbool.h when C99 is available? */
+typedef unsigned char XML_Bool;
+#define XML_TRUE   ((XML_Bool) 1)
+#define XML_FALSE  ((XML_Bool) 0)
+
+/* The XML_Status enum gives the possible return values for several
+   API functions.  The preprocessor #defines are included so this
+   stanza can be added to code that still needs to support older
+   versions of Expat 1.95.x:
+
+   #ifndef XML_STATUS_OK
+   #define XML_STATUS_OK    1
+   #define XML_STATUS_ERROR 0
+   #endif
+
+   Otherwise, the #define hackery is quite ugly and would have been
+   dropped.
+*/
+enum XML_Status {
+  XML_STATUS_ERROR = 0,
+#define XML_STATUS_ERROR XML_STATUS_ERROR
+  XML_STATUS_OK = 1,
+#define XML_STATUS_OK XML_STATUS_OK
+  XML_STATUS_SUSPENDED = 2
+#define XML_STATUS_SUSPENDED XML_STATUS_SUSPENDED
+};
+
+enum XML_Error {
+  XML_ERROR_NONE,
+  XML_ERROR_NO_MEMORY,
+  XML_ERROR_SYNTAX,
+  XML_ERROR_NO_ELEMENTS,
+  XML_ERROR_INVALID_TOKEN,
+  XML_ERROR_UNCLOSED_TOKEN,
+  XML_ERROR_PARTIAL_CHAR,
+  XML_ERROR_TAG_MISMATCH,
+  XML_ERROR_DUPLICATE_ATTRIBUTE,
+  XML_ERROR_JUNK_AFTER_DOC_ELEMENT,
+  XML_ERROR_PARAM_ENTITY_REF,
+  XML_ERROR_UNDEFINED_ENTITY,
+  XML_ERROR_RECURSIVE_ENTITY_REF,
+  XML_ERROR_ASYNC_ENTITY,
+  XML_ERROR_BAD_CHAR_REF,
+  XML_ERROR_BINARY_ENTITY_REF,
+  XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF,
+  XML_ERROR_MISPLACED_XML_PI,
+  XML_ERROR_UNKNOWN_ENCODING,
+  XML_ERROR_INCORRECT_ENCODING,
+  XML_ERROR_UNCLOSED_CDATA_SECTION,
+  XML_ERROR_EXTERNAL_ENTITY_HANDLING,
+  XML_ERROR_NOT_STANDALONE,
+  XML_ERROR_UNEXPECTED_STATE,
+  XML_ERROR_ENTITY_DECLARED_IN_PE,
+  XML_ERROR_FEATURE_REQUIRES_XML_DTD,
+  XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING,
+  /* Added in 1.95.7. */
+  XML_ERROR_UNBOUND_PREFIX,
+  /* Added in 1.95.8. */
+  XML_ERROR_UNDECLARING_PREFIX,
+  XML_ERROR_INCOMPLETE_PE,
+  XML_ERROR_XML_DECL,
+  XML_ERROR_TEXT_DECL,
+  XML_ERROR_PUBLICID,
+  XML_ERROR_SUSPENDED,
+  XML_ERROR_NOT_SUSPENDED,
+  XML_ERROR_ABORTED,
+  XML_ERROR_FINISHED,
+  XML_ERROR_SUSPEND_PE,
+  /* Added in 2.0. */
+  XML_ERROR_RESERVED_PREFIX_XML,
+  XML_ERROR_RESERVED_PREFIX_XMLNS,
+  XML_ERROR_RESERVED_NAMESPACE_URI
+};
+
+enum XML_Content_Type {
+  XML_CTYPE_EMPTY = 1,
+  XML_CTYPE_ANY,
+  XML_CTYPE_MIXED,
+  XML_CTYPE_NAME,
+  XML_CTYPE_CHOICE,
+  XML_CTYPE_SEQ
+};
+
+enum XML_Content_Quant {
+  XML_CQUANT_NONE,
+  XML_CQUANT_OPT,
+  XML_CQUANT_REP,
+  XML_CQUANT_PLUS
+};
+
+/* If type == XML_CTYPE_EMPTY or XML_CTYPE_ANY, then quant will be
+   XML_CQUANT_NONE, and the other fields will be zero or NULL.
+   If type == XML_CTYPE_MIXED, then quant will be NONE or REP and
+   numchildren will contain number of elements that may be mixed in
+   and children point to an array of XML_Content cells that will be
+   all of XML_CTYPE_NAME type with no quantification.
+
+   If type == XML_CTYPE_NAME, then the name points to the name, and
+   the numchildren field will be zero and children will be NULL. The
+   quant fields indicates any quantifiers placed on the name.
+
+   CHOICE and SEQ will have name NULL, the number of children in
+   numchildren and children will point, recursively, to an array
+   of XML_Content cells.
+
+   The EMPTY, ANY, and MIXED types will only occur at top level.
+*/
+
+typedef struct XML_cp XML_Content;
+
+struct XML_cp {
+  enum XML_Content_Type         type;
+  enum XML_Content_Quant        quant;
+  XML_Char *                    name;
+  unsigned int                  numchildren;
+  XML_Content *                 children;
+};
+
+
+/* This is called for an element declaration. See above for
+   description of the model argument. It's the caller's responsibility
+   to free model when finished with it.
+*/
+typedef void (XMLCALL *XML_ElementDeclHandler) (void *userData,
+                                                const XML_Char *name,
+                                                XML_Content *model);
+
+XMLPARSEAPI(void)
+XML_SetElementDeclHandler(XML_Parser parser,
+                          XML_ElementDeclHandler eldecl);
+
+/* The Attlist declaration handler is called for *each* attribute. So
+   a single Attlist declaration with multiple attributes declared will
+   generate multiple calls to this handler. The "default" parameter
+   may be NULL in the case of the "#IMPLIED" or "#REQUIRED"
+   keyword. The "isrequired" parameter will be true and the default
+   value will be NULL in the case of "#REQUIRED". If "isrequired" is
+   true and default is non-NULL, then this is a "#FIXED" default.
+*/
+typedef void (XMLCALL *XML_AttlistDeclHandler) (
+                                    void            *userData,
+                                    const XML_Char  *elname,
+                                    const XML_Char  *attname,
+                                    const XML_Char  *att_type,
+                                    const XML_Char  *dflt,
+                                    int              isrequired);
+
+XMLPARSEAPI(void)
+XML_SetAttlistDeclHandler(XML_Parser parser,
+                          XML_AttlistDeclHandler attdecl);
+
+/* The XML declaration handler is called for *both* XML declarations
+   and text declarations. The way to distinguish is that the version
+   parameter will be NULL for text declarations. The encoding
+   parameter may be NULL for XML declarations. The standalone
+   parameter will be -1, 0, or 1 indicating respectively that there
+   was no standalone parameter in the declaration, that it was given
+   as no, or that it was given as yes.
+*/
+typedef void (XMLCALL *XML_XmlDeclHandler) (void           *userData,
+                                            const XML_Char *version,
+                                            const XML_Char *encoding,
+                                            int             standalone);
+
+XMLPARSEAPI(void)
+XML_SetXmlDeclHandler(XML_Parser parser,
+                      XML_XmlDeclHandler xmldecl);
+
+
+typedef struct {
+  void *(*malloc_fcn)(size_t size);
+  void *(*realloc_fcn)(void *ptr, size_t size);
+  void (*free_fcn)(void *ptr);
+} XML_Memory_Handling_Suite;
+
+/* Constructs a new parser; encoding is the encoding specified by the
+   external protocol or NULL if there is none specified.
+*/
+XMLPARSEAPI(XML_Parser)
+XML_ParserCreate(const XML_Char *encoding);
+
+/* Constructs a new parser and namespace processor.  Element type
+   names and attribute names that belong to a namespace will be
+   expanded; unprefixed attribute names are never expanded; unprefixed
+   element type names are expanded only if there is a default
+   namespace. The expanded name is the concatenation of the namespace
+   URI, the namespace separator character, and the local part of the
+   name.  If the namespace separator is '\0' then the namespace URI
+   and the local part will be concatenated without any separator.
+   It is a programming error to use the separator '\0' with namespace
+   triplets (see XML_SetReturnNSTriplet).
+*/
+XMLPARSEAPI(XML_Parser)
+XML_ParserCreateNS(const XML_Char *encoding, XML_Char namespaceSeparator);
+
+
+/* Constructs a new parser using the memory management suite referred to
+   by memsuite. If memsuite is NULL, then use the standard library memory
+   suite. If namespaceSeparator is non-NULL it creates a parser with
+   namespace processing as described above. The character pointed at
+   will serve as the namespace separator.
+
+   All further memory operations used for the created parser will come from
+   the given suite.
+*/
+XMLPARSEAPI(XML_Parser)
+XML_ParserCreate_MM(const XML_Char *encoding,
+                    const XML_Memory_Handling_Suite *memsuite,
+                    const XML_Char *namespaceSeparator);
+
+/* Prepare a parser object to be re-used.  This is particularly
+   valuable when memory allocation overhead is disproportionatly high,
+   such as when a large number of small documnents need to be parsed.
+   All handlers are cleared from the parser, except for the
+   unknownEncodingHandler. The parser's external state is re-initialized
+   except for the values of ns and ns_triplets.
+
+   Added in Expat 1.95.3.
+*/
+XMLPARSEAPI(XML_Bool)
+XML_ParserReset(XML_Parser parser, const XML_Char *encoding);
+
+/* atts is array of name/value pairs, terminated by 0;
+   names and values are 0 terminated.
+*/
+typedef void (XMLCALL *XML_StartElementHandler) (void *userData,
+                                                 const XML_Char *name,
+                                                 const XML_Char **atts);
+
+typedef void (XMLCALL *XML_EndElementHandler) (void *userData,
+                                               const XML_Char *name);
+
+
+/* s is not 0 terminated. */
+typedef void (XMLCALL *XML_CharacterDataHandler) (void *userData,
+                                                  const XML_Char *s,
+                                                  int len);
+
+/* target and data are 0 terminated */
+typedef void (XMLCALL *XML_ProcessingInstructionHandler) (
+                                                void *userData,
+                                                const XML_Char *target,
+                                                const XML_Char *data);
+
+/* data is 0 terminated */
+typedef void (XMLCALL *XML_CommentHandler) (void *userData,
+                                            const XML_Char *data);
+
+typedef void (XMLCALL *XML_StartCdataSectionHandler) (void *userData);
+typedef void (XMLCALL *XML_EndCdataSectionHandler) (void *userData);
+
+/* This is called for any characters in the XML document for which
+   there is no applicable handler.  This includes both characters that
+   are part of markup which is of a kind that is not reported
+   (comments, markup declarations), or characters that are part of a
+   construct which could be reported but for which no handler has been
+   supplied. The characters are passed exactly as they were in the XML
+   document except that they will be encoded in UTF-8 or UTF-16.
+   Line boundaries are not normalized. Note that a byte order mark
+   character is not passed to the default handler. There are no
+   guarantees about how characters are divided between calls to the
+   default handler: for example, a comment might be split between
+   multiple calls.
+*/
+typedef void (XMLCALL *XML_DefaultHandler) (void *userData,
+                                            const XML_Char *s,
+                                            int len);
+
+/* This is called for the start of the DOCTYPE declaration, before
+   any DTD or internal subset is parsed.
+*/
+typedef void (XMLCALL *XML_StartDoctypeDeclHandler) (
+                                            void *userData,
+                                            const XML_Char *doctypeName,
+                                            const XML_Char *sysid,
+                                            const XML_Char *pubid,
+                                            int has_internal_subset);
+
+/* This is called for the start of the DOCTYPE declaration when the
+   closing > is encountered, but after processing any external
+   subset.
+*/
+typedef void (XMLCALL *XML_EndDoctypeDeclHandler)(void *userData);
+
+/* This is called for entity declarations. The is_parameter_entity
+   argument will be non-zero if the entity is a parameter entity, zero
+   otherwise.
+
+   For internal entities (<!ENTITY foo "bar">), value will
+   be non-NULL and systemId, publicID, and notationName will be NULL.
+   The value string is NOT nul-terminated; the length is provided in
+   the value_length argument. Since it is legal to have zero-length
+   values, do not use this argument to test for internal entities.
+
+   For external entities, value will be NULL and systemId will be
+   non-NULL. The publicId argument will be NULL unless a public
+   identifier was provided. The notationName argument will have a
+   non-NULL value only for unparsed entity declarations.
+
+   Note that is_parameter_entity can't be changed to XML_Bool, since
+   that would break binary compatibility.
+*/
+typedef void (XMLCALL *XML_EntityDeclHandler) (
+                              void *userData,
+                              const XML_Char *entityName,
+                              int is_parameter_entity,
+                              const XML_Char *value,
+                              int value_length,
+                              const XML_Char *base,
+                              const XML_Char *systemId,
+                              const XML_Char *publicId,
+                              const XML_Char *notationName);
+
+XMLPARSEAPI(void)
+XML_SetEntityDeclHandler(XML_Parser parser,
+                         XML_EntityDeclHandler handler);
+
+/* OBSOLETE -- OBSOLETE -- OBSOLETE
+   This handler has been superceded by the EntityDeclHandler above.
+   It is provided here for backward compatibility.
+
+   This is called for a declaration of an unparsed (NDATA) entity.
+   The base argument is whatever was set by XML_SetBase. The
+   entityName, systemId and notationName arguments will never be
+   NULL. The other arguments may be.
+*/
+typedef void (XMLCALL *XML_UnparsedEntityDeclHandler) (
+                                    void *userData,
+                                    const XML_Char *entityName,
+                                    const XML_Char *base,
+                                    const XML_Char *systemId,
+                                    const XML_Char *publicId,
+                                    const XML_Char *notationName);
+
+/* This is called for a declaration of notation.  The base argument is
+   whatever was set by XML_SetBase. The notationName will never be
+   NULL.  The other arguments can be.
+*/
+typedef void (XMLCALL *XML_NotationDeclHandler) (
+                                    void *userData,
+                                    const XML_Char *notationName,
+                                    const XML_Char *base,
+                                    const XML_Char *systemId,
+                                    const XML_Char *publicId);
+
+/* When namespace processing is enabled, these are called once for
+   each namespace declaration. The call to the start and end element
+   handlers occur between the calls to the start and end namespace
+   declaration handlers. For an xmlns attribute, prefix will be
+   NULL.  For an xmlns="" attribute, uri will be NULL.
+*/
+typedef void (XMLCALL *XML_StartNamespaceDeclHandler) (
+                                    void *userData,
+                                    const XML_Char *prefix,
+                                    const XML_Char *uri);
+
+typedef void (XMLCALL *XML_EndNamespaceDeclHandler) (
+                                    void *userData,
+                                    const XML_Char *prefix);
+
+/* This is called if the document is not standalone, that is, it has an
+   external subset or a reference to a parameter entity, but does not
+   have standalone="yes". If this handler returns XML_STATUS_ERROR,
+   then processing will not continue, and the parser will return a
+   XML_ERROR_NOT_STANDALONE error.
+   If parameter entity parsing is enabled, then in addition to the
+   conditions above this handler will only be called if the referenced
+   entity was actually read.
+*/
+typedef int (XMLCALL *XML_NotStandaloneHandler) (void *userData);
+
+/* This is called for a reference to an external parsed general
+   entity.  The referenced entity is not automatically parsed.  The
+   application can parse it immediately or later using
+   XML_ExternalEntityParserCreate.
+
+   The parser argument is the parser parsing the entity containing the
+   reference; it can be passed as the parser argument to
+   XML_ExternalEntityParserCreate.  The systemId argument is the
+   system identifier as specified in the entity declaration; it will
+   not be NULL.
+
+   The base argument is the system identifier that should be used as
+   the base for resolving systemId if systemId was relative; this is
+   set by XML_SetBase; it may be NULL.
+
+   The publicId argument is the public identifier as specified in the
+   entity declaration, or NULL if none was specified; the whitespace
+   in the public identifier will have been normalized as required by
+   the XML spec.
+
+   The context argument specifies the parsing context in the format
+   expected by the context argument to XML_ExternalEntityParserCreate;
+   context is valid only until the handler returns, so if the
+   referenced entity is to be parsed later, it must be copied.
+   context is NULL only when the entity is a parameter entity.
+
+   The handler should return XML_STATUS_ERROR if processing should not
+   continue because of a fatal error in the handling of the external
+   entity.  In this case the calling parser will return an
+   XML_ERROR_EXTERNAL_ENTITY_HANDLING error.
+
+   Note that unlike other handlers the first argument is the parser,
+   not userData.
+*/
+typedef int (XMLCALL *XML_ExternalEntityRefHandler) (
+                                    XML_Parser parser,
+                                    const XML_Char *context,
+                                    const XML_Char *base,
+                                    const XML_Char *systemId,
+                                    const XML_Char *publicId);
+
+/* This is called in two situations:
+   1) An entity reference is encountered for which no declaration
+      has been read *and* this is not an error.
+   2) An internal entity reference is read, but not expanded, because
+      XML_SetDefaultHandler has been called.
+   Note: skipped parameter entities in declarations and skipped general
+         entities in attribute values cannot be reported, because
+         the event would be out of sync with the reporting of the
+         declarations or attribute values
+*/
+typedef void (XMLCALL *XML_SkippedEntityHandler) (
+                                    void *userData,
+                                    const XML_Char *entityName,
+                                    int is_parameter_entity);
+
+/* This structure is filled in by the XML_UnknownEncodingHandler to
+   provide information to the parser about encodings that are unknown
+   to the parser.
+
+   The map[b] member gives information about byte sequences whose
+   first byte is b.
+
+   If map[b] is c where c is >= 0, then b by itself encodes the
+   Unicode scalar value c.
+
+   If map[b] is -1, then the byte sequence is malformed.
+
+   If map[b] is -n, where n >= 2, then b is the first byte of an
+   n-byte sequence that encodes a single Unicode scalar value.
+
+   The data member will be passed as the first argument to the convert
+   function.
+
+   The convert function is used to convert multibyte sequences; s will
+   point to a n-byte sequence where map[(unsigned char)*s] == -n.  The
+   convert function must return the Unicode scalar value represented
+   by this byte sequence or -1 if the byte sequence is malformed.
+
+   The convert function may be NULL if the encoding is a single-byte
+   encoding, that is if map[b] >= -1 for all bytes b.
+
+   When the parser is finished with the encoding, then if release is
+   not NULL, it will call release passing it the data member; once
+   release has been called, the convert function will not be called
+   again.
+
+   Expat places certain restrictions on the encodings that are supported
+   using this mechanism.
+
+   1. Every ASCII character that can appear in a well-formed XML document,
+      other than the characters
+
+      $@\^`{}~
+
+      must be represented by a single byte, and that byte must be the
+      same byte that represents that character in ASCII.
+
+   2. No character may require more than 4 bytes to encode.
+
+   3. All characters encoded must have Unicode scalar values <=
+      0xFFFF, (i.e., characters that would be encoded by surrogates in
+      UTF-16 are  not allowed).  Note that this restriction doesn't
+      apply to the built-in support for UTF-8 and UTF-16.
+
+   4. No Unicode character may be encoded by more than one distinct
+      sequence of bytes.
+*/
+typedef struct {
+  int map[256];
+  void *data;
+  int (XMLCALL *convert)(void *data, const char *s);
+  void (XMLCALL *release)(void *data);
+} XML_Encoding;
+
+/* This is called for an encoding that is unknown to the parser.
+
+   The encodingHandlerData argument is that which was passed as the
+   second argument to XML_SetUnknownEncodingHandler.
+
+   The name argument gives the name of the encoding as specified in
+   the encoding declaration.
+
+   If the callback can provide information about the encoding, it must
+   fill in the XML_Encoding structure, and return XML_STATUS_OK.
+   Otherwise it must return XML_STATUS_ERROR.
+
+   If info does not describe a suitable encoding, then the parser will
+   return an XML_UNKNOWN_ENCODING error.
+*/
+typedef int (XMLCALL *XML_UnknownEncodingHandler) (
+                                    void *encodingHandlerData,
+                                    const XML_Char *name,
+                                    XML_Encoding *info);
+
+XMLPARSEAPI(void)
+XML_SetElementHandler(XML_Parser parser,
+                      XML_StartElementHandler start,
+                      XML_EndElementHandler end);
+
+XMLPARSEAPI(void)
+XML_SetStartElementHandler(XML_Parser parser,
+                           XML_StartElementHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetEndElementHandler(XML_Parser parser,
+                         XML_EndElementHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetCharacterDataHandler(XML_Parser parser,
+                            XML_CharacterDataHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetProcessingInstructionHandler(XML_Parser parser,
+                                    XML_ProcessingInstructionHandler handler);
+XMLPARSEAPI(void)
+XML_SetCommentHandler(XML_Parser parser,
+                      XML_CommentHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetCdataSectionHandler(XML_Parser parser,
+                           XML_StartCdataSectionHandler start,
+                           XML_EndCdataSectionHandler end);
+
+XMLPARSEAPI(void)
+XML_SetStartCdataSectionHandler(XML_Parser parser,
+                                XML_StartCdataSectionHandler start);
+
+XMLPARSEAPI(void)
+XML_SetEndCdataSectionHandler(XML_Parser parser,
+                              XML_EndCdataSectionHandler end);
+
+/* This sets the default handler and also inhibits expansion of
+   internal entities. These entity references will be passed to the
+   default handler, or to the skipped entity handler, if one is set.
+*/
+XMLPARSEAPI(void)
+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.
+*/
+XMLPARSEAPI(void)
+XML_SetDefaultHandlerExpand(XML_Parser parser,
+                            XML_DefaultHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetDoctypeDeclHandler(XML_Parser parser,
+                          XML_StartDoctypeDeclHandler start,
+                          XML_EndDoctypeDeclHandler end);
+
+XMLPARSEAPI(void)
+XML_SetStartDoctypeDeclHandler(XML_Parser parser,
+                               XML_StartDoctypeDeclHandler start);
+
+XMLPARSEAPI(void)
+XML_SetEndDoctypeDeclHandler(XML_Parser parser,
+                             XML_EndDoctypeDeclHandler end);
+
+XMLPARSEAPI(void)
+XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
+                                 XML_UnparsedEntityDeclHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetNotationDeclHandler(XML_Parser parser,
+                           XML_NotationDeclHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetNamespaceDeclHandler(XML_Parser parser,
+                            XML_StartNamespaceDeclHandler start,
+                            XML_EndNamespaceDeclHandler end);
+
+XMLPARSEAPI(void)
+XML_SetStartNamespaceDeclHandler(XML_Parser parser,
+                                 XML_StartNamespaceDeclHandler start);
+
+XMLPARSEAPI(void)
+XML_SetEndNamespaceDeclHandler(XML_Parser parser,
+                               XML_EndNamespaceDeclHandler end);
+
+XMLPARSEAPI(void)
+XML_SetNotStandaloneHandler(XML_Parser parser,
+                            XML_NotStandaloneHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetExternalEntityRefHandler(XML_Parser parser,
+                                XML_ExternalEntityRefHandler handler);
+
+/* If a non-NULL value for arg is specified here, then it will be
+   passed as the first argument to the external entity ref handler
+   instead of the parser object.
+*/
+XMLPARSEAPI(void)
+XML_SetExternalEntityRefHandlerArg(XML_Parser parser,
+                                   void *arg);
+
+XMLPARSEAPI(void)
+XML_SetSkippedEntityHandler(XML_Parser parser,
+                            XML_SkippedEntityHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetUnknownEncodingHandler(XML_Parser parser,
+                              XML_UnknownEncodingHandler handler,
+                              void *encodingHandlerData);
+
+/* This can be called within a handler for a start element, end
+   element, processing instruction or character data.  It causes the
+   corresponding markup to be passed to the default handler.
+*/
+XMLPARSEAPI(void)
+XML_DefaultCurrent(XML_Parser parser);
+
+/* If do_nst is non-zero, and namespace processing is in effect, and
+   a name has a prefix (i.e. an explicit namespace qualifier) then
+   that name is returned as a triplet in a single string separated by
+   the separator character specified when the parser was created: URI
+   + sep + local_name + sep + prefix.
+
+   If do_nst is zero, then namespace information is returned in the
+   default manner (URI + sep + local_name) whether or not the name
+   has a prefix.
+
+   Note: Calling XML_SetReturnNSTriplet after XML_Parse or
+     XML_ParseBuffer has no effect.
+*/
+
+XMLPARSEAPI(void)
+XML_SetReturnNSTriplet(XML_Parser parser, int do_nst);
+
+/* This value is passed as the userData argument to callbacks. */
+XMLPARSEAPI(void)
+XML_SetUserData(XML_Parser parser, void *userData);
+
+/* Returns the last value set by XML_SetUserData or NULL. */
+#define XML_GetUserData(parser) (*(void **)(parser))
+
+/* This is equivalent to supplying an encoding argument to
+   XML_ParserCreate. On success XML_SetEncoding returns non-zero,
+   zero otherwise.
+   Note: Calling XML_SetEncoding after XML_Parse or XML_ParseBuffer
+     has no effect and returns XML_STATUS_ERROR.
+*/
+XMLPARSEAPI(enum XML_Status)
+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.
+*/
+XMLPARSEAPI(void)
+XML_UseParserAsHandlerArg(XML_Parser parser);
+
+/* If useDTD == XML_TRUE is passed to this function, then the parser
+   will assume that there is an external subset, even if none is
+   specified in the document. In such a case the parser will call the
+   externalEntityRefHandler with a value of NULL for the systemId
+   argument (the publicId and context arguments will be NULL as well).
+   Note: For the purpose of checking WFC: Entity Declared, passing
+     useDTD == XML_TRUE will make the parser behave as if the document
+     had a DTD with an external subset.
+   Note: If this function is called, then this must be done before
+     the first call to XML_Parse or XML_ParseBuffer, since it will
+     have no effect after that.  Returns
+     XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING.
+   Note: If the document does not have a DOCTYPE declaration at all,
+     then startDoctypeDeclHandler and endDoctypeDeclHandler will not
+     be called, despite an external subset being parsed.
+   Note: If XML_DTD is not defined when Expat is compiled, returns
+     XML_ERROR_FEATURE_REQUIRES_XML_DTD.
+*/
+XMLPARSEAPI(enum XML_Error)
+XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD);
+
+
+/* Sets the base to be used for resolving relative URIs in system
+   identifiers in declarations.  Resolving relative identifiers is
+   left to the application: this value will be passed through as the
+   base argument to the XML_ExternalEntityRefHandler,
+   XML_NotationDeclHandler and XML_UnparsedEntityDeclHandler. The base
+   argument will be copied.  Returns XML_STATUS_ERROR if out of memory,
+   XML_STATUS_OK otherwise.
+*/
+XMLPARSEAPI(enum XML_Status)
+XML_SetBase(XML_Parser parser, const XML_Char *base);
+
+XMLPARSEAPI(const XML_Char *)
+XML_GetBase(XML_Parser parser);
+
+/* Returns the number of the attribute/value pairs passed in last call
+   to the XML_StartElementHandler that were specified in the start-tag
+   rather than defaulted. Each attribute/value pair counts as 2; thus
+   this correspondds to an index into the atts array passed to the
+   XML_StartElementHandler.
+*/
+XMLPARSEAPI(int)
+XML_GetSpecifiedAttributeCount(XML_Parser parser);
+
+/* Returns the index of the ID attribute passed in the last call to
+   XML_StartElementHandler, or -1 if there is no ID attribute.  Each
+   attribute/value pair counts as 2; thus this correspondds to an
+   index into the atts array passed to the XML_StartElementHandler.
+*/
+XMLPARSEAPI(int)
+XML_GetIdAttributeIndex(XML_Parser parser);
+
+/* Parses some input. Returns XML_STATUS_ERROR 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).
+
+   Though the return values for these functions has always been
+   described as a Boolean value, the implementation, at least for the
+   1.95.x series, has always returned exactly one of the XML_Status
+   values.
+*/
+XMLPARSEAPI(enum XML_Status)
+XML_Parse(XML_Parser parser, const char *s, int len, int isFinal);
+
+XMLPARSEAPI(void *)
+XML_GetBuffer(XML_Parser parser, int len);
+
+XMLPARSEAPI(enum XML_Status)
+XML_ParseBuffer(XML_Parser parser, int len, int isFinal);
+
+/* Stops parsing, causing XML_Parse() or XML_ParseBuffer() to return.
+   Must be called from within a call-back handler, except when aborting
+   (resumable = 0) an already suspended parser. Some call-backs may
+   still follow because they would otherwise get lost. Examples:
+   - endElementHandler() for empty elements when stopped in
+     startElementHandler(), 
+   - endNameSpaceDeclHandler() when stopped in endElementHandler(), 
+   and possibly others.
+
+   Can be called from most handlers, including DTD related call-backs,
+   except when parsing an external parameter entity and resumable != 0.
+   Returns XML_STATUS_OK when successful, XML_STATUS_ERROR otherwise.
+   Possible error codes: 
+   - XML_ERROR_SUSPENDED: when suspending an already suspended parser.
+   - XML_ERROR_FINISHED: when the parser has already finished.
+   - XML_ERROR_SUSPEND_PE: when suspending while parsing an external PE.
+
+   When resumable != 0 (true) then parsing is suspended, that is, 
+   XML_Parse() and XML_ParseBuffer() return XML_STATUS_SUSPENDED. 
+   Otherwise, parsing is aborted, that is, XML_Parse() and XML_ParseBuffer()
+   return XML_STATUS_ERROR with error code XML_ERROR_ABORTED.
+
+   *Note*:
+   This will be applied to the current parser instance only, that is, if
+   there is a parent parser then it will continue parsing when the
+   externalEntityRefHandler() returns. It is up to the implementation of
+   the externalEntityRefHandler() to call XML_StopParser() on the parent
+   parser (recursively), if one wants to stop parsing altogether.
+
+   When suspended, parsing can be resumed by calling XML_ResumeParser(). 
+*/
+XMLPARSEAPI(enum XML_Status)
+XML_StopParser(XML_Parser parser, XML_Bool resumable);
+
+/* Resumes parsing after it has been suspended with XML_StopParser().
+   Must not be called from within a handler call-back. Returns same
+   status codes as XML_Parse() or XML_ParseBuffer().
+   Additional error code XML_ERROR_NOT_SUSPENDED possible.   
+
+   *Note*:
+   This must be called on the most deeply nested child parser instance
+   first, and on its parent parser only after the child parser has finished,
+   to be applied recursively until the document entity's parser is restarted.
+   That is, the parent parser will not resume by itself and it is up to the
+   application to call XML_ResumeParser() on it at the appropriate moment.
+*/
+XMLPARSEAPI(enum XML_Status)
+XML_ResumeParser(XML_Parser parser);
+
+enum XML_Parsing {
+  XML_INITIALIZED,
+  XML_PARSING,
+  XML_FINISHED,
+  XML_SUSPENDED
+};
+
+typedef struct {
+  enum XML_Parsing parsing;
+  XML_Bool finalBuffer;
+} XML_ParsingStatus;
+
+/* Returns status of parser with respect to being initialized, parsing,
+   finished, or suspended and processing the final buffer.
+   XXX XML_Parse() and XML_ParseBuffer() should return XML_ParsingStatus,
+   XXX with XML_FINISHED_OK or XML_FINISHED_ERROR replacing XML_FINISHED
+*/
+XMLPARSEAPI(void)
+XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status);
+
+/* Creates an XML_Parser object that can parse an external general
+   entity; context is a '\0'-terminated string specifying the parse
+   context; encoding is a '\0'-terminated string giving the name of
+   the externally specified encoding, or NULL if there is no
+   externally specified encoding.  The context string consists of a
+   sequence of tokens separated by formfeeds (\f); a token consisting
+   of a name specifies that the general entity of the name is open; a
+   token of the form prefix=uri specifies the namespace for a
+   particular prefix; a token of the form =uri specifies the default
+   namespace.  This can be called at any point after the first call to
+   an ExternalEntityRefHandler so longer as the parser has not yet
+   been freed.  The new parser is completely independent and may
+   safely be used in a separate thread.  The handlers and userData are
+   initialized from the parser argument.  Returns NULL if out of memory.
+   Otherwise returns a new XML_Parser object.
+*/
+XMLPARSEAPI(XML_Parser)
+XML_ExternalEntityParserCreate(XML_Parser parser,
+                               const XML_Char *context,
+                               const XML_Char *encoding);
+
+enum XML_ParamEntityParsing {
+  XML_PARAM_ENTITY_PARSING_NEVER,
+  XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE,
+  XML_PARAM_ENTITY_PARSING_ALWAYS
+};
+
+/* Controls parsing of parameter entities (including the external DTD
+   subset). If parsing of parameter entities is enabled, then
+   references to external parameter entities (including the external
+   DTD subset) will be passed to the handler set with
+   XML_SetExternalEntityRefHandler.  The context passed will be 0.
+
+   Unlike external general entities, external parameter entities can
+   only be parsed synchronously.  If the external parameter entity is
+   to be parsed, it must be parsed during the call to the external
+   entity ref handler: the complete sequence of
+   XML_ExternalEntityParserCreate, XML_Parse/XML_ParseBuffer and
+   XML_ParserFree calls must be made during this call.  After
+   XML_ExternalEntityParserCreate has been called to create the parser
+   for the external parameter entity (context must be 0 for this
+   call), it is illegal to make any calls on the old parser until
+   XML_ParserFree has been called on the newly created parser.
+   If the library has been compiled without support for parameter
+   entity parsing (ie without XML_DTD being defined), then
+   XML_SetParamEntityParsing will return 0 if parsing of parameter
+   entities is requested; otherwise it will return non-zero.
+   Note: If XML_SetParamEntityParsing is called after XML_Parse or
+      XML_ParseBuffer, then it has no effect and will always return 0.
+*/
+XMLPARSEAPI(int)
+XML_SetParamEntityParsing(XML_Parser parser,
+                          enum XML_ParamEntityParsing parsing);
+
+/* If XML_Parse or XML_ParseBuffer have returned XML_STATUS_ERROR, then
+   XML_GetErrorCode returns information about the error.
+*/
+XMLPARSEAPI(enum XML_Error)
+XML_GetErrorCode(XML_Parser parser);
+
+/* These functions return information about the current parse
+   location.  They may be called from any callback called to report
+   some parse event; in this case the location is the location of the
+   first of the sequence of characters that generated the event.  When
+   called from callbacks generated by declarations in the document
+   prologue, the location identified isn't as neatly defined, but will
+   be within the relevant markup.  When called outside of the callback
+   functions, the position indicated will be just past the last parse
+   event (regardless of whether there was an associated callback).
+   
+   They may also be called after returning from a call to XML_Parse
+   or XML_ParseBuffer.  If the return value is XML_STATUS_ERROR then
+   the location is the location of the character at which the error
+   was detected; otherwise the location is the location of the last
+   parse event, as described above.
+*/
+XMLPARSEAPI(XML_Size) XML_GetCurrentLineNumber(XML_Parser parser);
+XMLPARSEAPI(XML_Size) XML_GetCurrentColumnNumber(XML_Parser parser);
+XMLPARSEAPI(XML_Index) XML_GetCurrentByteIndex(XML_Parser parser);
+
+/* Return the number of bytes in the current event.
+   Returns 0 if the event is in an internal entity.
+*/
+XMLPARSEAPI(int)
+XML_GetCurrentByteCount(XML_Parser parser);
+
+/* If XML_CONTEXT_BYTES is defined, returns the input buffer, sets
+   the integer pointed to by offset to the offset within this buffer
+   of the current parse position, and sets the integer pointed to by size
+   to the size of this buffer (the number of input bytes). Otherwise
+   returns a NULL pointer. Also returns a NULL pointer if a parse isn't
+   active.
+
+   NOTE: The character pointer returned should not be used outside
+   the handler that makes the call.
+*/
+XMLPARSEAPI(const char *)
+XML_GetInputContext(XML_Parser parser,
+                    int *offset,
+                    int *size);
+
+/* For backwards compatibility with previous versions. */
+#define XML_GetErrorLineNumber   XML_GetCurrentLineNumber
+#define XML_GetErrorColumnNumber XML_GetCurrentColumnNumber
+#define XML_GetErrorByteIndex    XML_GetCurrentByteIndex
+
+/* Frees the content model passed to the element declaration handler */
+XMLPARSEAPI(void)
+XML_FreeContentModel(XML_Parser parser, XML_Content *model);
+
+/* Exposing the memory handling functions used in Expat */
+XMLPARSEAPI(void *)
+XML_MemMalloc(XML_Parser parser, size_t size);
+
+XMLPARSEAPI(void *)
+XML_MemRealloc(XML_Parser parser, void *ptr, size_t size);
+
+XMLPARSEAPI(void)
+XML_MemFree(XML_Parser parser, void *ptr);
+
+/* Frees memory used by the parser. */
+XMLPARSEAPI(void)
+XML_ParserFree(XML_Parser parser);
+
+/* Returns a string describing the error. */
+XMLPARSEAPI(const XML_LChar *)
+XML_ErrorString(enum XML_Error code);
+
+/* Return a string containing the version number of this expat */
+XMLPARSEAPI(const XML_LChar *)
+XML_ExpatVersion(void);
+
+typedef struct {
+  int major;
+  int minor;
+  int micro;
+} XML_Expat_Version;
+
+/* Return an XML_Expat_Version structure containing numeric version
+   number information for this version of expat.
+*/
+XMLPARSEAPI(XML_Expat_Version)
+XML_ExpatVersionInfo(void);
+
+/* Added in Expat 1.95.5. */
+enum XML_FeatureEnum {
+  XML_FEATURE_END = 0,
+  XML_FEATURE_UNICODE,
+  XML_FEATURE_UNICODE_WCHAR_T,
+  XML_FEATURE_DTD,
+  XML_FEATURE_CONTEXT_BYTES,
+  XML_FEATURE_MIN_SIZE,
+  XML_FEATURE_SIZEOF_XML_CHAR,
+  XML_FEATURE_SIZEOF_XML_LCHAR,
+  XML_FEATURE_NS,
+  XML_FEATURE_LARGE_SIZE
+  /* Additional features must be added to the end of this enum. */
+};
+
+typedef struct {
+  enum XML_FeatureEnum  feature;
+  const XML_LChar       *name;
+  long int              value;
+} XML_Feature;
+
+XMLPARSEAPI(const XML_Feature *)
+XML_GetFeatureList(void);
+
+
+/* Expat follows the GNU/Linux convention of odd number minor version for
+   beta/development releases and even number minor version for stable
+   releases. Micro is bumped with each release, and set to 0 with each
+   change to major or minor version.
+*/
+#define XML_MAJOR_VERSION 2
+#define XML_MINOR_VERSION 0
+#define XML_MICRO_VERSION 1
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* not Expat_INCLUDED */

+ 115 - 0
scbc.tools/Log4C/sd/expat_external.h

@@ -0,0 +1,115 @@
+/* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
+   See the file COPYING for copying permission.
+*/
+
+#ifndef Expat_External_INCLUDED
+#define Expat_External_INCLUDED 1
+
+/* External API definitions */
+
+#if defined(_MSC_EXTENSIONS) && !defined(__BEOS__) && !defined(__CYGWIN__)
+#define XML_USE_MSC_EXTENSIONS 1
+#endif
+
+/* Expat tries very hard to make the API boundary very specifically
+   defined.  There are two macros defined to control this boundary;
+   each of these can be defined before including this header to
+   achieve some different behavior, but doing so it not recommended or
+   tested frequently.
+
+   XMLCALL    - The calling convention to use for all calls across the
+                "library boundary."  This will default to cdecl, and
+                try really hard to tell the compiler that's what we
+                want.
+
+   XMLIMPORT  - Whatever magic is needed to note that a function is
+                to be imported from a dynamically loaded library
+                (.dll, .so, or .sl, depending on your platform).
+
+   The XMLCALL macro was added in Expat 1.95.7.  The only one which is
+   expected to be directly useful in client code is XMLCALL.
+
+   Note that on at least some Unix versions, the Expat library must be
+   compiled with the cdecl calling convention as the default since
+   system headers may assume the cdecl convention.
+*/
+#ifndef XMLCALL
+#if defined(_MSC_VER)
+#define XMLCALL __cdecl
+#elif defined(__GNUC__) && defined(__i386) && !defined(__INTEL_COMPILER)
+#define XMLCALL __attribute__((cdecl))
+#else
+/* For any platform which uses this definition and supports more than
+   one calling convention, we need to extend this definition to
+   declare the convention used on that platform, if it's possible to
+   do so.
+
+   If this is the case for your platform, please file a bug report
+   with information on how to identify your platform via the C
+   pre-processor and how to specify the same calling convention as the
+   platform's malloc() implementation.
+*/
+#define XMLCALL
+#endif
+#endif  /* not defined XMLCALL */
+
+
+#if !defined(XML_STATIC) && !defined(XMLIMPORT)
+#ifndef XML_BUILDING_EXPAT
+/* using Expat from an application */
+
+#ifdef XML_USE_MSC_EXTENSIONS
+#define XMLIMPORT __declspec(dllimport)
+#endif
+
+#endif
+#endif  /* not defined XML_STATIC */
+
+
+/* If we didn't define it above, define it away: */
+#ifndef XMLIMPORT
+#define XMLIMPORT
+#endif
+
+
+#define XMLPARSEAPI(type) XMLIMPORT type XMLCALL
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef XML_UNICODE_WCHAR_T
+#define XML_UNICODE
+#endif
+
+#ifdef XML_UNICODE     /* Information is UTF-16 encoded. */
+#ifdef XML_UNICODE_WCHAR_T
+typedef wchar_t XML_Char;
+typedef wchar_t XML_LChar;
+#else
+typedef unsigned short XML_Char;
+typedef char XML_LChar;
+#endif /* XML_UNICODE_WCHAR_T */
+#else                  /* Information is UTF-8 encoded. */
+typedef char XML_Char;
+typedef char XML_LChar;
+#endif /* XML_UNICODE */
+
+#ifdef XML_LARGE_SIZE  /* Use large integers for file/stream positions. */
+#if defined(XML_USE_MSC_EXTENSIONS) && _MSC_VER < 1400
+typedef __int64 XML_Index; 
+typedef unsigned __int64 XML_Size;
+#else
+typedef long long XML_Index;
+typedef unsigned long long XML_Size;
+#endif
+#else
+typedef long XML_Index;
+typedef unsigned long XML_Size;
+#endif /* XML_LARGE_SIZE */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* not Expat_External_INCLUDED */

+ 43 - 0
scbc.tools/Log4C/sd/factory.h

@@ -0,0 +1,43 @@
+/* $Id$
+ *
+ * factory.h
+ * 
+ * Copyright 2001-2003, Meiosys (www.meiosys.com). All rights reserved.
+ * See the COPYING file for the terms of usage and distribution.
+ */
+
+#ifndef __sd_factory_h
+#define __sd_factory_h
+
+/**
+ * @file factory.h
+ */
+
+#include <stdio.h>
+#include <sd/defs.h>
+
+__SD_BEGIN_DECLS
+
+struct __sd_factory;
+typedef struct __sd_factory sd_factory_t;
+
+struct __sd_factory_ops
+{
+    void* (*fac_new)	(const char*);
+    void  (*fac_delete)	(void*);
+    void  (*fac_print)	(void*, FILE*);
+};
+typedef struct __sd_factory_ops sd_factory_ops_t;
+
+extern sd_factory_t* sd_factory_new(const char* a_name, 
+				    const sd_factory_ops_t* a_ops);
+extern void	sd_factory_delete(sd_factory_t* a_this);
+extern void*	sd_factory_get(sd_factory_t* a_this, const char* a_name);
+extern void	sd_factory_destroy(sd_factory_t* a_this, void* a_pr);
+extern void	sd_factory_print(const sd_factory_t* a_this, FILE* a_stream);
+extern int	sd_factory_list(const sd_factory_t* a_this, void** a_items,
+				int a_nitems);
+
+__SD_END_DECLS
+
+#endif

+ 166 - 0
scbc.tools/Log4C/sd/hash.h

@@ -0,0 +1,166 @@
+/* $Id$
+ *
+ * Copyright 2001-2003, Meiosys (www.meiosys.com). All rights reserved.
+ * Author: Marc Vertes <mvertes@meiosys.com>
+ * See the COPYING file for the terms of usage and distribution.
+ */
+
+#ifndef __sd_hash_h
+#define __sd_hash_h
+
+/**
+ * @file hash.h
+ *
+ * @brief Generic hash table. It is implemented as an array of doubly-linked
+ * lists of iterators. The index within the array is computed by a efficient
+ * hash function.
+ */
+
+#include <stddef.h>
+#include <sd/defs.h>
+
+__SD_BEGIN_DECLS
+
+struct __sd_hash_ops {
+    unsigned int	(*hash)		(const void*);
+    int			(*compare)	(const void*, const void*);
+    void*		(*key_dup)	(const void*);
+    void		(*key_free)	(void*);
+    void*		(*data_dup)	(const void*);
+    void		(*data_free)	(void*);
+};
+
+/**
+ * This structure holds hash table operations.
+ */
+typedef struct __sd_hash_ops sd_hash_ops_t;
+
+/**
+ * This is the hash table.
+ */
+typedef struct __sd_hash sd_hash_t;
+
+struct __sd_hash_iter {
+    void*			key;
+    void*			data;
+    struct __sd_hash*		hash;
+    unsigned int		__hkey;
+    struct __sd_hash_iter*	__next;
+    struct __sd_hash_iter*	__prev;
+    int				__foreach;
+};
+
+/**
+ * This is the elementary container for storing data into the hash table.
+ */
+typedef struct __sd_hash_iter sd_hash_iter_t;
+
+/**
+ * Signature of a "foreach" function.
+ */
+typedef unsigned int (*sd_hash_func_t)(void* a_key, void* a_data,
+				       void* a_userdata);
+
+/**
+ * Creates a new hash table. One can customize the memory (de)allocation
+ * policy for keys and data stored in the hash table.
+ * @param a_size the initial size of the array.
+ * @param a_ops the hash operations. If NULL, then string keys are assumed and
+ * no memory (de)allocation is performed for keys and data.
+ * @return a dynamicaly allocated hash table.
+ */
+extern sd_hash_t* sd_hash_new(size_t a_size, const sd_hash_ops_t* a_ops);
+
+/**
+ * Destroys the hash table.
+ */
+extern void sd_hash_delete(sd_hash_t* a_this);
+
+/**
+ * clears the hash table.
+ */
+extern void sd_hash_clear(sd_hash_t* a_this);
+
+/**
+ * Looks for the iterator associated to the given key in the hash table.
+ * @param a_key the key associated to the iterator.
+ * @return a pointer to the found iterator or NULL.
+ */
+extern sd_hash_iter_t* sd_hash_lookup(sd_hash_t* a_this, const void* a_key);
+
+/**
+ * Looks for the iterator associated to the given key in the hash table and
+ * creates it if doesn't exist.
+ * @param a_key the key associated to the iterator.
+ * @return a pointer to the found iterator or NULL.
+ */
+extern sd_hash_iter_t* sd_hash_lookadd(sd_hash_t* a_this, const void* a_key);
+
+/**
+ * Adds data associated with the given key into the hash table. If the
+ * key already exists, the old iterator is freed according to the memory
+ * management operations passed to sd_hash_new().
+ * @param a_key the key associated to the iterator.
+ * @return a pointer to the created or found iterator.
+ */
+extern sd_hash_iter_t* sd_hash_add(sd_hash_t* a_this, const void* a_key,
+				 void* a_data);
+
+/**
+ * Removes an iterator from the hash table.
+ * @param a_key the key associated to the iterator.
+ */
+extern void sd_hash_del(sd_hash_t* a_this, const void* a_key);
+
+/**
+ * Calls \a a_func for each element of the hash table, as long as \a a_func
+ * returns 0.
+ * @param a_func the "foreach" function.
+ * @param a_data the user data passed to \a a_func.
+ */
+extern void sd_hash_foreach(sd_hash_t* a_this, sd_hash_func_t a_func,
+			    void* a_data);
+
+/**
+ * Gets the number of iterators.
+ */
+extern unsigned int sd_hash_get_nelem(sd_hash_t* a_this);
+
+/**
+ * Gets the size of the array.
+ */
+extern unsigned int sd_hash_get_size(sd_hash_t* a_this);
+
+/**
+ * Gets the first iterator.
+ */
+extern sd_hash_iter_t* sd_hash_begin(sd_hash_t* a_this);
+
+/**
+ * Gets the last iterator.
+ */
+extern sd_hash_iter_t* sd_hash_end(sd_hash_t* a_this);
+
+/**
+ * Gets a pointer to the next iterator.
+ */
+extern sd_hash_iter_t* sd_hash_iter_next(sd_hash_iter_t* a_this);
+
+/**
+ * Gets a pointer to the previous iterator.
+ */
+extern sd_hash_iter_t* sd_hash_iter_prev(sd_hash_iter_t* a_this);
+
+/**
+ * Gets a pointer to the previous iterator.
+ */
+extern void sd_hash_iter_del(sd_hash_iter_t* a_this);
+
+/**
+ * Hashes strings.
+ */
+extern unsigned int sd_hash_hash_string(const char* a_string);
+
+__SD_END_DECLS
+
+#endif

+ 190 - 0
scbc.tools/Log4C/sd/list.h

@@ -0,0 +1,190 @@
+/* $Id$
+ *
+ * Copyright 2001-2003, Meiosys (www.meiosys.com). All rights reserved.
+ * 
+ * See the COPYING file for the terms of usage and distribution.
+ */
+
+#ifndef __sd_list_h
+#define __sd_list_h
+
+/**
+ * @file list.h @ingroup sd
+ *
+ * @brief Generic list object. It is implemented as an array of doubly-linked
+ * lists of iterators. The index within the array is computed by a efficient
+ * list function.
+ */
+
+#include <stddef.h>
+#include <sd/defs.h>
+
+__SD_BEGIN_DECLS
+
+/**
+ * This is the list object.
+ */
+typedef struct __sd_list sd_list_t;
+
+struct __sd_list_iter {
+    void*			data;
+    struct __sd_list*		list;
+    struct __sd_list_iter*	__next;
+    struct __sd_list_iter*	__prev;
+    int				__foreach;
+};
+
+/**
+ * This is the elementary container for storing data into the list object.
+ */
+typedef struct __sd_list_iter sd_list_iter_t;
+
+/**
+ * Signature of a "foreach" function.
+ */
+typedef unsigned int (*sd_list_func_t)(void* a_data, void* a_userdata);
+
+/**
+ * Creates a list.
+ * @param a_capacity initial number of preallocated iterators
+ * @return the list object.
+ */
+extern sd_list_t* sd_list_new(size_t a_capacity);
+
+/**
+ * Destroys the list object.
+ * @todo need a function parameter to destroy list elements.
+ */
+extern void sd_list_delete(sd_list_t* a_this);
+
+/**
+ * Adds the given_data at the head of the list.
+ */
+extern sd_list_iter_t* sd_list_prepend(sd_list_t* a_this, void* a_data);
+
+/**
+ * Adds the given data at the tail of the list.
+ */
+extern sd_list_iter_t* sd_list_append(sd_list_t* a_this, void* a_data);
+
+/**
+ * Looks for the iterator associated to the given data in the list object.
+ * @param a_data the data to find
+ * @return a pointer to the found iterator or NULL.
+ */
+extern sd_list_iter_t* sd_list_lookup(sd_list_t* a_this, void* a_data);
+
+/**
+ * Looks for the iterator associated to the given data in the list object and
+ * creates it if doesn't exist, using @c sd_list_add().
+ * @param a_data the data to find/add
+ * @return a pointer to the found iterator or NULL.
+ */
+extern sd_list_iter_t* sd_list_lookadd(sd_list_t* a_this, void* a_data);
+
+/**
+ * Adds the given data into the list object. If the data already exists,
+ * the associated iterator is returned.
+ * @warning the element is added at the begining of the list.
+ * @param a_data the data to add
+ * @return a pointer to the created or found iterator.
+ */
+extern sd_list_iter_t* sd_list_add(sd_list_t* a_this, void* a_data);
+
+/**
+ * Applies the given function to all list elements, starting from the
+ * first one. As soon as the function returns a non-null value, the
+ * given data is inserted in the list (before the element).
+ * @param a_func the "sort" function.
+ * @param a_data the data to add
+ * @return a pointer to the created iterator.
+ */
+extern sd_list_iter_t* sd_list_sortadd(sd_list_t* a_this,
+				       sd_list_func_t a_func,
+				       void* a_data);
+
+/**
+ * Removes an iterator from the list object.
+ * @param a_data the data associated to the iterator.
+ */
+extern int sd_list_del(sd_list_t* a_this, void* a_data);
+
+/**
+ * clears the list object.
+ */
+extern void sd_list_clear(sd_list_t* a_this);
+
+/**
+ * Calls \a a_func for each element of the list object, as long as \a a_func
+ * returns 0.
+ * @param a_func the "foreach" function.
+ * @param a_data the user data passed to \a a_func.
+ */
+extern void sd_list_foreach(sd_list_t* a_this, sd_list_func_t a_func,
+			    void* a_userdata);
+
+/**
+ * Calls \a a_func for each element of the list object, as long as \a a_func
+ * returns 0.
+ * Same as sd_list_foreach but from tail to head of list.
+ * @param a_func the "foreach" function.
+ * @param a_data the user data passed to \a a_func.
+ */
+extern void sd_list_rforeach(sd_list_t* a_this, sd_list_func_t a_func,
+			     void* a_userdata);
+
+/**
+ * Gets the number of iterators.
+ */
+extern size_t sd_list_get_nelem(sd_list_t* a_this);
+
+/**
+ * Gets the iterator pointing to the first element of the list.
+ */
+extern sd_list_iter_t* sd_list_begin(sd_list_t* a_this);
+
+/**
+ * Gets the past-the-last-element iterator of the list.
+ */
+extern sd_list_iter_t* sd_list_end(sd_list_t* a_this);
+
+/**
+ * Gets the iterator pointing to the last element of the list.
+ */
+extern sd_list_iter_t* sd_list_rbegin(sd_list_t* a_this);
+
+/**
+ * Gets the before-the-first-element iterator of the list.
+ */
+extern sd_list_iter_t* sd_list_rend(sd_list_t* a_this);
+
+/**
+ * Gets a pointer to the next iterator.
+ */
+extern sd_list_iter_t* sd_list_iter_next(sd_list_iter_t* a_this);
+
+/**
+ * Gets a pointer to the previous iterator.
+ */
+extern sd_list_iter_t* sd_list_iter_prev(sd_list_iter_t* a_this);
+
+/**
+ * Deletes the iterator from the list.
+ */
+extern void sd_list_iter_del(sd_list_iter_t* a_this);
+
+/**
+ * Deletes the iterator from the list.
+ */
+extern void sd_list_iter_del(sd_list_iter_t* a_this);
+
+/**
+ * Creates a new iterator and inserts it before @a a_this.
+ * @param a_data the data associated to the iterator.
+ */
+extern sd_list_iter_t* sd_list_iter_insert(sd_list_iter_t* a_this,
+					   void* a_data);
+
+__SD_END_DECLS
+
+#endif

+ 43 - 0
scbc.tools/Log4C/sd/malloc.h

@@ -0,0 +1,43 @@
+/* $Id$
+ *
+ * Copyright 2001-2003, Meiosys (www.meiosys.com). All rights reserved.
+ *
+ * See the COPYING file for the terms of usage and distribution.
+ */
+
+#ifndef __sd_malloc_h
+#define __sd_malloc_h
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <sd/defs.h>
+
+/**
+ * @file malloc.h
+ */
+
+__SD_BEGIN_DECLS
+
+typedef void (*sd_malloc_handler_t)();
+
+extern sd_malloc_handler_t sd_malloc_set_handler(void (*a_handler)());
+
+#ifndef __SD_DEBUG__
+
+extern void *sd_malloc(size_t n);
+extern void *sd_calloc(size_t n, size_t s);
+extern void *sd_realloc(void *p, size_t n);
+extern char *sd_strdup (const char *__str);
+
+#else
+
+#define sd_malloc	malloc
+#define sd_calloc	calloc
+#define sd_realloc	realloc
+#define sd_strdup	strdup
+
+#endif
+
+__SD_END_DECLS
+
+#endif

+ 137 - 0
scbc.tools/Log4C/sd/sd_xplatform.h

@@ -0,0 +1,137 @@
+/* $Id$
+ *
+ * sd_xplatform.h
+ * 
+ * See the COPYING file for the terms of usage and distribution.
+ */
+
+#ifndef __sd_xplatform_h
+#define __sd_xplatform_h
+
+#ifndef _WIN32
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#else
+#include <time.h>
+#include <io.h> /* needed for _access  */
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#include <winsock2.h>
+#include <process.h>
+#endif
+
+
+#ifdef HAVE_STDINT_H
+#       include <stdint.h>
+#define  XP_UINT64 uint64_t
+#define  XP_INT64 int64_t
+#else
+#ifndef _WIN32
+#define  XP_UINT64 unsigned long long
+#define  XP_INT64 long long
+#else
+#define  XP_UINT64 DWORD64
+#define  XP_INT64 __int64
+#endif
+#endif
+
+#include <log4c/defs.h>
+#include <sd/defs.h>
+
+
+/*extern int sd_optind; */
+LOG4C_DATA int sd_optind; 
+
+extern void getopt_reset(void); 
+
+extern int sd_getopt(int argc, char *const *argv, const char *opts);
+
+#ifdef _WIN32
+#define SD_GETOPT(a,b,c) sd_getopt(a,b,c)
+#define SD_OPTIND sd_optind
+#else
+#define SD_GETOPT(a,b,c) getopt(a,b,c)
+#define SD_OPTIND optind
+#endif
+
+
+#ifdef _WIN32
+#define SD_GETTIMEOFDAY(a,b) sd_gettimeofday(a,b)
+extern int sd_gettimeofday(LPFILETIME lpft, void* tzp);
+#else
+#define SD_GETTIMEOFDAY(a,b) gettimeofday(a,b)
+extern int sd_gettimeofday(struct timeval* tp, void* tzp);
+#endif
+
+#ifdef _WIN32
+#define FILE_SEP "\\"
+#else
+#define FILE_SEP "/"
+#endif
+
+#ifdef _WIN32
+#define SD_ACCESS_READ(a) _access(a,04)
+#else
+#define SD_ACCESS_READ(a) access(a,R_OK)
+#endif
+
+int sd_stat_ctime(const char* path, time_t* time);
+#define SD_STAT_CTIME(path, time) sd_stat_ctime(path, time)
+
+#ifndef _WIN32
+#define DIFF_CMD  "/usr/bin/diff -q"
+#else
+#define DIFF_CMD  "comp.exe"
+#endif
+
+#ifdef _WIN32
+#define snprintf _snprintf
+#define vsnprintf _vsnprintf
+#define alloca _alloca
+#define strncasecmp _strnicmp
+#define strcasecmp _stricmp
+#define YY_NO_UNISTD_H
+#define sleep(x) Sleep(x*1000)
+#endif
+
+
+/* Maybe should be using this for to mean
+* MS compiler #if defined(_MSC_VER) 
+*/
+#ifdef _WIN32
+#define pthread_t HANDLE
+#define pthread_mutex_t HANDLE
+#define pthread_attr_t DWORD
+#define THREAD_FUNCTION DWORD (WINAPI *)(void *)
+
+/*
+* This one not obvious: you would have naturally thought of mapping to
+* CreateThread()--turns out that to be safe using CRT functions
+* you need to use _begintheadex().  
+* cf. http://msdn2.microsoft.com/en-us/library/7t9ha0zh.aspx
+*  http://groups.google.com/group/comp.os.ms-windows.programmer.win32/browse_thread/thread/86d8624e7ee38c5d/f947ac76cd10f397?lnk=st&q=when+to+use+_beginthreadex&rnum=1#f947ac76cd10f397
+* 
+*/
+#define pthread_create(thhandle,attr,thfunc,tharg) \
+  (int)((*thhandle=(HANDLE)_beginthreadex(NULL,0,(THREAD_FUNCTION)thfunc,tharg,0,NULL))==NULL)
+#define pthread_join(thread, result) \
+  ((WaitForSingleObject((thread),INFINITE)!=WAIT_OBJECT_0) || !CloseHandle(thread))
+#define pthread_exit() _endthreadex(0)
+#define pthread_cancel(thread) TerminateThread(thread,0)
+
+#define pthread_mutex_init(pobject,pattr) (*pobject=CreateMutex(NULL,FALSE,NULL))
+#define pthread_mutex_lock(pobject) WaitForSingleObject(*pobject,INFINITE)
+#define pthread_mutex_unlock(pobject) ReleaseMutex(*pobject)
+
+#define pthread_mutex_destroy(pobject) CloseHandle(*pobject)
+
+#endif
+
+
+#ifdef __HP_cc
+#define inline __inline
+#endif 
+
+#endif

+ 59 - 0
scbc.tools/Log4C/sd/sprintf.h

@@ -0,0 +1,59 @@
+/* $Id$
+ *
+ * Copyright 2001-2003, Meiosys (www.meiosys.com). All rights reserved.
+ *
+ * See the COPYING file for the terms of usage and distribution.
+ */
+
+#ifndef __sd_sprintf_h
+#define __sd_sprintf_h
+
+/**
+ * @file sprintf.h
+ *
+ * @brief Formatted output conversion
+ *
+ * These functions write the output under the control of a format
+ * string that specifies how subsequent arguments (or arguments
+ * accessed via the variable-length argument facilities of stdarg(2))
+ * are converted for output.
+ *
+ * They do not write more than \a size bytes, including the trailing
+ * \c '\0'.
+ *
+ * These functions return the number of characters printed (not
+ * including the trailing \c `\0' used to end output to strings). They
+ * return -1 if the output was truncated due to the @a size limit.
+ *
+ */
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <sd/defs.h>
+
+__SD_BEGIN_DECLS
+
+/**
+ * Same as fprintf(3) with auto-allocation of the resulting buffer,
+ * and output directly in a file, not a stream.
+ */
+extern int sd_fprintf(int fd, const char *fmt, ...);
+
+/**
+ * Same as sprintf(3) with auto-allocation of the resulting buffer.
+ */
+extern char* sd_sprintf(const char* a_fmt, ...);
+
+/**
+ * Same as vsprintf(3) with auto-allocation of the resulting buffer.
+ */
+extern char* sd_vsprintf(const char* a_fmt, va_list a_arg);
+
+#if defined(__osf__)
+extern int snprintf(char* str, size_t size, const char* fmt, ...);
+extern int vsnprintf(char* str, size_t size, const char* fmt, va_list arg);
+#endif
+
+__SD_END_DECLS
+
+#endif

+ 41 - 0
scbc.tools/Log4C/sd/stack.h

@@ -0,0 +1,41 @@
+/* $Id$
+ *
+ * Copyright 2001-2003, Meiosys (www.meiosys.com). All rights reserved.
+ *
+ * See the COPYING file for the terms of usage and distribution.
+ */
+
+#ifndef __sd_stack_h
+#define __sd_stack_h
+
+/**
+ * @file stack.h @ingroup sd
+ *
+ * @brief Generic stack object.
+ *
+ * @todo documentation
+ * @todo API homogeneity with sd_list and sd_hash
+ */
+
+#include <stddef.h>
+#include <sd/defs.h>
+
+__SD_BEGIN_DECLS
+
+typedef struct __sd_stack sd_stack_t;
+
+extern sd_stack_t* sd_stack_new(size_t max);
+extern void	sd_stack_delete(sd_stack_t* astack, void (*free_data_fn)(void *));
+extern size_t	sd_stack_get_nelem(const sd_stack_t* astack);
+
+extern void	sd_stack_clear(sd_stack_t* astack, void (*free_data_fn)(void *));
+extern int	sd_stack_push(sd_stack_t* astack, void *data);
+extern void*	sd_stack_pop(sd_stack_t* astack);
+extern void*	sd_stack_begin(sd_stack_t* astack);
+extern void*	sd_stack_next(sd_stack_t* astack);
+extern void*	sd_stack_end(sd_stack_t* astack);
+extern void*	sd_stack_peek(sd_stack_t* astack);
+
+__SD_END_DECLS
+
+#endif

+ 132 - 0
scbc.tools/cJson/JsonUtils.cpp

@@ -0,0 +1,132 @@
+#include "JsonUtils.h"
+
+
+namespace JsonUtil {
+
+	cJSON * obj2json(const JsonType &obj) {
+
+		// 创建json根节点;
+		cJSON * pJsonRoot = NULL;
+		JsonList jsonList;
+		JsonMap jsonMap;
+		JsonVector jsonvec;
+
+		switch (obj.type()) {
+		case JsonType::VoidType:
+			pJsonRoot = cJSON_CreateNull();
+			break;
+		case JsonType::NumberType:
+			pJsonRoot = cJSON_CreateNumber(obj.toNumber());
+			break;
+		case JsonType::BooleanType:
+			pJsonRoot = cJSON_CreateBool(obj.toBoolean());
+			break;
+		case JsonType::StringType:
+			pJsonRoot = cJSON_CreateString(obj.toString().c_str());
+			break;
+		case JsonType::ListType:
+			jsonList.clear();
+			jsonList = obj.toList();
+			pJsonRoot = cJSON_CreateArray();
+			for (JsonList::const_iterator iter = jsonList.begin();
+				iter != jsonList.end(); ++iter) {
+				cJSON_AddItemToArray(pJsonRoot, obj2json(*iter));
+			}
+			break;
+		case JsonType::MapType:
+			jsonMap.clear();
+			jsonMap = obj.toMap();
+			pJsonRoot = cJSON_CreateObject();
+			for (JsonMap::const_iterator iter = jsonMap.begin();
+				iter != jsonMap.end(); ++iter) {
+				cJSON_AddItemToObject(pJsonRoot, iter->first.toString().c_str(), obj2json(iter->second));
+			}
+			break;
+		case JsonType::VectorType:
+			jsonvec.clear();
+			jsonvec = obj.toVector();
+			pJsonRoot = cJSON_CreateArray();
+			for (JsonVector::const_iterator it = jsonvec.begin(); it != jsonvec.end(); ++it) {
+				cJSON_AddItemToArray(pJsonRoot, obj2json(*it));
+			}
+			break;
+		default:
+			break;
+		}
+		return pJsonRoot;
+	}
+
+	JsonType json2obj(const cJSON *pJsonRoot) {
+
+		// 创建json根节点;
+		cJSON *pChild = NULL;
+		JsonList jsonList;
+		JsonMap jsonMap;
+
+		// 解析类型;
+		if (pJsonRoot) {
+			switch (pJsonRoot->type) {
+			case cJSON_NULL:
+				return JsonType();
+				break;
+			case cJSON_False:
+				return JsonType(false);
+				break;
+			case cJSON_True:
+				return JsonType(true);
+				break;
+			case cJSON_Number:
+				return JsonType(pJsonRoot->valuedouble);
+				break;
+			case cJSON_String:
+				return JsonType(pJsonRoot->valuestring);
+				break;
+			case cJSON_Array:
+				jsonList.clear();
+				pChild = pJsonRoot->child;
+				while (pChild) {
+					jsonList.push_back(json2obj(pChild));
+					pChild = pChild->next;
+				}
+				return JsonType(jsonList);
+				break;
+			case cJSON_Object:
+				jsonMap.clear();
+				pChild = pJsonRoot->child;
+				while (pChild) {
+					jsonMap.insert(JsonMap::value_type(JsonType(pChild->string), json2obj(pChild)));
+					pChild = pChild->next;
+				}
+				return JsonType(jsonMap);
+				break;
+			default:
+				break;
+			}
+		}
+		return JsonType();
+	}
+
+	string objectToString(const JsonType &obj) {
+		cJSON *pJson = obj2json(obj);
+		string str;
+		if (pJson) {
+			const char *pCh = cJSON_PrintUnformatted(pJson);
+			if (pCh) {
+				str = pCh;
+				free((void*)pCh);
+			}
+			cJSON_Delete(pJson);
+		}
+		return str;
+	}
+
+	JsonType stringToObject(const string &json) {
+		cJSON *pJson = cJSON_Parse(json.c_str());
+		JsonType obj = json2obj(pJson);
+		if (pJson) {
+			cJSON_Delete(pJson);
+		}
+		return obj;
+	}
+
+}

+ 15 - 0
scbc.tools/cJson/JsonUtils.h

@@ -0,0 +1,15 @@
+#ifndef JSONUTIL_H
+#define JSONUTIL_H
+
+#include "cJSON.h"
+#include "json_type.h"
+
+namespace JsonUtil {
+
+    string objectToString(const JsonType &obj);
+
+    JsonType stringToObject(const string &json);
+
+}
+
+#endif // JSONUTIL_H

+ 132 - 0
scbc.tools/cJson/Json_Type.h

@@ -0,0 +1,132 @@
+#ifndef JSONTYPE_H
+#define JSONTYPE_H
+
+#include <string>
+#include <list>
+#include <map>
+#include <vector>
+
+using std::string;
+using std::list;
+using std::vector;
+using std::map;
+
+class JsonType;
+
+typedef list<JsonType> JsonList;
+typedef vector<JsonType> JsonVector;
+typedef map<JsonType, JsonType> JsonMap;
+
+class JsonType {
+public:
+	JsonType() : m_type(JsonType::VoidType) {}
+
+	JsonType(int num) : m_type(JsonType::NumberType), num_vale(num) {}
+
+	JsonType(double fvalue) : m_type(JsonType::FloatType), float_value(fvalue) {}
+
+	JsonType(bool bl) : m_type(JsonType::BooleanType), bl_value(bl) {}
+
+	JsonType(const char *str) : m_type(JsonType::StringType), str_value(str) {}
+
+	JsonType(const char *str, int len) : m_type(JsonType::StringType), str_value(str, len) {}
+
+	JsonType(const string &str) : m_type(JsonType::StringType), str_value(str) {}
+
+	JsonType(const JsonList &list) : m_type(JsonType::ListType), json_list(list) {}
+
+	JsonType(const JsonVector &vec) : m_type(JsonType::VectorType), json_vec(vec) {}
+
+	JsonType(const JsonMap &map) : m_type(JsonType::MapType), json_map(map) {}
+
+	virtual ~JsonType() {}
+
+	bool operator<(const JsonType &val) const {
+		if (this->type() < val.type()) {
+			return true;
+		}
+		else if (this->type() == val.type()) {
+			switch (this->type()) {
+			case JsonType::VoidType:
+				return false;
+				break;
+			case JsonType::NumberType:
+				return this->toNumber() < val.toNumber();
+				break;
+			case JsonType::FloatType:
+				return this->toFloat() < val.toFloat();
+				break;
+			case JsonType::BooleanType:
+				return this->toBoolean() < val.toBoolean();
+				break;
+			case JsonType::StringType:
+				return this->toString() < val.toString();
+				break;
+			case JsonType::ListType:
+				return this->toList() < val.toList();
+				break;
+			case JsonType::VectorType:
+				return this->toVector() < val.toVector();
+				break;
+			case JsonType::MapType:
+				return this->toMap() < val.toMap();
+				break;
+			default:
+				break;
+			}
+		}
+		return false;
+	}
+
+public:
+	enum Type {
+		VoidType, NumberType, FloatType, BooleanType, StringType, ListType, VectorType, MapType
+	};
+
+private:
+	Type m_type;
+
+	int		 num_vale;
+	double   float_value;
+	bool     bl_value;
+	string   str_value;
+	JsonList json_list;
+	JsonVector json_vec;
+	JsonMap  json_map;
+
+public:
+	Type type() const {
+		return m_type;
+	}
+
+	int toNumber() const {
+		return num_vale;
+	}
+
+	double toFloat() const {
+		return float_value;
+	}
+
+	bool toBoolean() const {
+		return bl_value;
+	}
+
+	string toString() const {
+		return str_value;
+	}
+
+	JsonList toList() const {
+		return json_list;
+	}
+
+	JsonMap toMap() const {
+		return json_map;
+	}
+
+	JsonVector toVector() const {
+		return json_vec;
+	}
+};
+
+
+#endif // JSONTYPE_H

+ 2973 - 0
scbc.tools/cJson/cJSON.c

@@ -0,0 +1,2973 @@
+/*
+  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
+
+  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.
+*/
+
+/* cJSON */
+/* JSON parser in C. */
+
+/* disable warnings about old C89 functions in MSVC */
+#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER)
+#define _CRT_SECURE_NO_DEPRECATE
+#endif
+
+#ifdef __GNUC__
+#pragma GCC visibility push(default)
+#endif
+#if defined(_MSC_VER)
+#pragma warning (push)
+/* disable warning about single line comments in system headers */
+#pragma warning (disable : 4001)
+#endif
+
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <ctype.h>
+
+#ifdef ENABLE_LOCALES
+#include <locale.h>
+#endif
+
+#if defined(_MSC_VER)
+#pragma warning (pop)
+#endif
+#ifdef __GNUC__
+#pragma GCC visibility pop
+#endif
+
+#include "cJSON.h"
+
+/* define our own boolean type */
+#ifdef true
+#undef true
+#endif
+#define true ((cJSON_bool)1)
+
+#ifdef false
+#undef false
+#endif
+#define false ((cJSON_bool)0)
+
+typedef struct {
+    const unsigned char *json;
+    size_t position;
+} error;
+static error global_error = { NULL, 0 };
+
+CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
+{
+    return (const char*) (global_error.json + global_error.position);
+}
+
+CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item) {
+    if (!cJSON_IsString(item)) {
+        return NULL;
+    }
+
+    return item->valuestring;
+}
+
+/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */
+#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 12)
+    #error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
+#endif
+
+CJSON_PUBLIC(const char*) cJSON_Version(void)
+{
+    static char version[15];
+    sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH);
+
+    return version;
+}
+
+/* Case insensitive string comparison, doesn't consider two NULL pointers equal though */
+static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2)
+{
+    if ((string1 == NULL) || (string2 == NULL))
+    {
+        return 1;
+    }
+
+    if (string1 == string2)
+    {
+        return 0;
+    }
+
+    for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++)
+    {
+        if (*string1 == '\0')
+        {
+            return 0;
+        }
+    }
+
+    return tolower(*string1) - tolower(*string2);
+}
+
+typedef struct internal_hooks
+{
+    void *(CJSON_CDECL *allocate)(size_t size);
+    void (CJSON_CDECL *deallocate)(void *pointer);
+    void *(CJSON_CDECL *reallocate)(void *pointer, size_t size);
+} internal_hooks;
+
+#if defined(_MSC_VER)
+/* work around MSVC error C2322: '...' address of dillimport '...' is not static */
+static void * CJSON_CDECL internal_malloc(size_t size)
+{
+    return malloc(size);
+}
+static void CJSON_CDECL internal_free(void *pointer)
+{
+    free(pointer);
+}
+static void * CJSON_CDECL internal_realloc(void *pointer, size_t size)
+{
+    return realloc(pointer, size);
+}
+#else
+#define internal_malloc malloc
+#define internal_free free
+#define internal_realloc realloc
+#endif
+
+/* strlen of character literals resolved at compile time */
+#define static_strlen(string_literal) (sizeof(string_literal) - sizeof(""))
+
+static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc };
+
+static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks)
+{
+    size_t length = 0;
+    unsigned char *copy = NULL;
+
+    if (string == NULL)
+    {
+        return NULL;
+    }
+
+    length = strlen((const char*)string) + sizeof("");
+    copy = (unsigned char*)hooks->allocate(length);
+    if (copy == NULL)
+    {
+        return NULL;
+    }
+    memcpy(copy, string, length);
+
+    return copy;
+}
+
+CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks)
+{
+    if (hooks == NULL)
+    {
+        /* Reset hooks */
+        global_hooks.allocate = malloc;
+        global_hooks.deallocate = free;
+        global_hooks.reallocate = realloc;
+        return;
+    }
+
+    global_hooks.allocate = malloc;
+    if (hooks->malloc_fn != NULL)
+    {
+        global_hooks.allocate = hooks->malloc_fn;
+    }
+
+    global_hooks.deallocate = free;
+    if (hooks->free_fn != NULL)
+    {
+        global_hooks.deallocate = hooks->free_fn;
+    }
+
+    /* use realloc only if both free and malloc are used */
+    global_hooks.reallocate = NULL;
+    if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free))
+    {
+        global_hooks.reallocate = realloc;
+    }
+}
+
+/* Internal constructor. */
+static cJSON *cJSON_New_Item(const internal_hooks * const hooks)
+{
+    cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON));
+    if (node)
+    {
+        memset(node, '\0', sizeof(cJSON));
+    }
+
+    return node;
+}
+
+/* Delete a cJSON structure. */
+CJSON_PUBLIC(void) cJSON_Delete(cJSON *item)
+{
+    cJSON *next = NULL;
+    while (item != NULL)
+    {
+        next = item->next;
+        if (!(item->type & cJSON_IsReference) && (item->child != NULL))
+        {
+            cJSON_Delete(item->child);
+        }
+        if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL))
+        {
+            global_hooks.deallocate(item->valuestring);
+        }
+        if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
+        {
+            global_hooks.deallocate(item->string);
+        }
+        global_hooks.deallocate(item);
+        item = next;
+    }
+}
+
+/* get the decimal point character of the current locale */
+static unsigned char get_decimal_point(void)
+{
+#ifdef ENABLE_LOCALES
+    struct lconv *lconv = localeconv();
+    return (unsigned char) lconv->decimal_point[0];
+#else
+    return '.';
+#endif
+}
+
+typedef struct
+{
+    const unsigned char *content;
+    size_t length;
+    size_t offset;
+    size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */
+    internal_hooks hooks;
+} parse_buffer;
+
+/* check if the given size is left to read in a given parse buffer (starting with 1) */
+#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
+/* check if the buffer can be accessed at the given index (starting with 0) */
+#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
+#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
+/* get a pointer to the buffer at the position */
+#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
+
+/* Parse the input text to generate a number, and populate the result into item. */
+static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer)
+{
+    double number = 0;
+    unsigned char *after_end = NULL;
+    unsigned char number_c_string[64];
+    unsigned char decimal_point = get_decimal_point();
+    size_t i = 0;
+
+    if ((input_buffer == NULL) || (input_buffer->content == NULL))
+    {
+        return false;
+    }
+
+    /* copy the number into a temporary buffer and replace '.' with the decimal point
+     * of the current locale (for strtod)
+     * This also takes care of '\0' not necessarily being available for marking the end of the input */
+    for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++)
+    {
+        switch (buffer_at_offset(input_buffer)[i])
+        {
+            case '0':
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+            case '+':
+            case '-':
+            case 'e':
+            case 'E':
+                number_c_string[i] = buffer_at_offset(input_buffer)[i];
+                break;
+
+            case '.':
+                number_c_string[i] = decimal_point;
+                break;
+
+            default:
+                goto loop_end;
+        }
+    }
+loop_end:
+    number_c_string[i] = '\0';
+
+    number = strtod((const char*)number_c_string, (char**)&after_end);
+    if (number_c_string == after_end)
+    {
+        return false; /* parse_error */
+    }
+
+    item->valuedouble = number;
+
+    /* use saturation in case of overflow */
+    if (number >= INT_MAX)
+    {
+        item->valueint = INT_MAX;
+    }
+    else if (number <= (double)INT_MIN)
+    {
+        item->valueint = INT_MIN;
+    }
+    else
+    {
+        item->valueint = (int)number;
+    }
+
+    item->type = cJSON_Number;
+
+    input_buffer->offset += (size_t)(after_end - number_c_string);
+    return true;
+}
+
+/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */
+CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
+{
+    if (number >= INT_MAX)
+    {
+        object->valueint = INT_MAX;
+    }
+    else if (number <= (double)INT_MIN)
+    {
+        object->valueint = INT_MIN;
+    }
+    else
+    {
+        object->valueint = (int)number;
+    }
+
+    return object->valuedouble = number;
+}
+
+typedef struct
+{
+    unsigned char *buffer;
+    size_t length;
+    size_t offset;
+    size_t depth; /* current nesting depth (for formatted printing) */
+    cJSON_bool noalloc;
+    cJSON_bool format; /* is this print a formatted print */
+    internal_hooks hooks;
+} printbuffer;
+
+/* realloc printbuffer if necessary to have at least "needed" bytes more */
+static unsigned char* ensure(printbuffer * const p, size_t needed)
+{
+    unsigned char *newbuffer = NULL;
+    size_t newsize = 0;
+
+    if ((p == NULL) || (p->buffer == NULL))
+    {
+        return NULL;
+    }
+
+    if ((p->length > 0) && (p->offset >= p->length))
+    {
+        /* make sure that offset is valid */
+        return NULL;
+    }
+
+    if (needed > INT_MAX)
+    {
+        /* sizes bigger than INT_MAX are currently not supported */
+        return NULL;
+    }
+
+    needed += p->offset + 1;
+    if (needed <= p->length)
+    {
+        return p->buffer + p->offset;
+    }
+
+    if (p->noalloc) {
+        return NULL;
+    }
+
+    /* calculate new buffer size */
+    if (needed > (INT_MAX / 2))
+    {
+        /* overflow of int, use INT_MAX if possible */
+        if (needed <= INT_MAX)
+        {
+            newsize = INT_MAX;
+        }
+        else
+        {
+            return NULL;
+        }
+    }
+    else
+    {
+        newsize = needed * 2;
+    }
+
+    if (p->hooks.reallocate != NULL)
+    {
+        /* reallocate with realloc if available */
+        newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize);
+        if (newbuffer == NULL)
+        {
+            p->hooks.deallocate(p->buffer);
+            p->length = 0;
+            p->buffer = NULL;
+
+            return NULL;
+        }
+    }
+    else
+    {
+        /* otherwise reallocate manually */
+        newbuffer = (unsigned char*)p->hooks.allocate(newsize);
+        if (!newbuffer)
+        {
+            p->hooks.deallocate(p->buffer);
+            p->length = 0;
+            p->buffer = NULL;
+
+            return NULL;
+        }
+        if (newbuffer)
+        {
+            memcpy(newbuffer, p->buffer, p->offset + 1);
+        }
+        p->hooks.deallocate(p->buffer);
+    }
+    p->length = newsize;
+    p->buffer = newbuffer;
+
+    return newbuffer + p->offset;
+}
+
+/* calculate the new length of the string in a printbuffer and update the offset */
+static void update_offset(printbuffer * const buffer)
+{
+    const unsigned char *buffer_pointer = NULL;
+    if ((buffer == NULL) || (buffer->buffer == NULL))
+    {
+        return;
+    }
+    buffer_pointer = buffer->buffer + buffer->offset;
+
+    buffer->offset += strlen((const char*)buffer_pointer);
+}
+
+/* Render the number nicely from the given item into a string. */
+static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer)
+{
+    unsigned char *output_pointer = NULL;
+    double d = item->valuedouble;
+    int length = 0;
+    size_t i = 0;
+    unsigned char number_buffer[26]; /* temporary buffer to print the number into */
+    unsigned char decimal_point = get_decimal_point();
+    double test;
+
+    if (output_buffer == NULL)
+    {
+        return false;
+    }
+
+    /* This checks for NaN and Infinity */
+    if ((d * 0) != 0)
+    {
+        length = sprintf((char*)number_buffer, "null");
+    }
+    else
+    {
+        /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
+        length = sprintf((char*)number_buffer, "%1.15g", d);
+
+        /* Check whether the original double can be recovered */
+        if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || ((double)test != d))
+        {
+            /* If not, print with 17 decimal places of precision */
+            length = sprintf((char*)number_buffer, "%1.17g", d);
+        }
+    }
+
+    /* sprintf failed or buffer overrun occurred */
+    if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1)))
+    {
+        return false;
+    }
+
+    /* reserve appropriate space in the output */
+    output_pointer = ensure(output_buffer, (size_t)length + sizeof(""));
+    if (output_pointer == NULL)
+    {
+        return false;
+    }
+
+    /* copy the printed number to the output and replace locale
+     * dependent decimal point with '.' */
+    for (i = 0; i < ((size_t)length); i++)
+    {
+        if (number_buffer[i] == decimal_point)
+        {
+            output_pointer[i] = '.';
+            continue;
+        }
+
+        output_pointer[i] = number_buffer[i];
+    }
+    output_pointer[i] = '\0';
+
+    output_buffer->offset += (size_t)length;
+
+    return true;
+}
+
+/* parse 4 digit hexadecimal number */
+static unsigned parse_hex4(const unsigned char * const input)
+{
+    unsigned int h = 0;
+    size_t i = 0;
+
+    for (i = 0; i < 4; i++)
+    {
+        /* parse digit */
+        if ((input[i] >= '0') && (input[i] <= '9'))
+        {
+            h += (unsigned int) input[i] - '0';
+        }
+        else if ((input[i] >= 'A') && (input[i] <= 'F'))
+        {
+            h += (unsigned int) 10 + input[i] - 'A';
+        }
+        else if ((input[i] >= 'a') && (input[i] <= 'f'))
+        {
+            h += (unsigned int) 10 + input[i] - 'a';
+        }
+        else /* invalid */
+        {
+            return 0;
+        }
+
+        if (i < 3)
+        {
+            /* shift left to make place for the next nibble */
+            h = h << 4;
+        }
+    }
+
+    return h;
+}
+
+/* converts a UTF-16 literal to UTF-8
+ * A literal can be one or two sequences of the form \uXXXX */
+static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer)
+{
+    long unsigned int codepoint = 0;
+    unsigned int first_code = 0;
+    const unsigned char *first_sequence = input_pointer;
+    unsigned char utf8_length = 0;
+    unsigned char utf8_position = 0;
+    unsigned char sequence_length = 0;
+    unsigned char first_byte_mark = 0;
+
+    if ((input_end - first_sequence) < 6)
+    {
+        /* input ends unexpectedly */
+        goto fail;
+    }
+
+    /* get the first utf16 sequence */
+    first_code = parse_hex4(first_sequence + 2);
+
+    /* check that the code is valid */
+    if (((first_code >= 0xDC00) && (first_code <= 0xDFFF)))
+    {
+        goto fail;
+    }
+
+    /* UTF16 surrogate pair */
+    if ((first_code >= 0xD800) && (first_code <= 0xDBFF))
+    {
+        const unsigned char *second_sequence = first_sequence + 6;
+        unsigned int second_code = 0;
+        sequence_length = 12; /* \uXXXX\uXXXX */
+
+        if ((input_end - second_sequence) < 6)
+        {
+            /* input ends unexpectedly */
+            goto fail;
+        }
+
+        if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u'))
+        {
+            /* missing second half of the surrogate pair */
+            goto fail;
+        }
+
+        /* get the second utf16 sequence */
+        second_code = parse_hex4(second_sequence + 2);
+        /* check that the code is valid */
+        if ((second_code < 0xDC00) || (second_code > 0xDFFF))
+        {
+            /* invalid second half of the surrogate pair */
+            goto fail;
+        }
+
+
+        /* calculate the unicode codepoint from the surrogate pair */
+        codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF));
+    }
+    else
+    {
+        sequence_length = 6; /* \uXXXX */
+        codepoint = first_code;
+    }
+
+    /* encode as UTF-8
+     * takes at maximum 4 bytes to encode:
+     * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
+    if (codepoint < 0x80)
+    {
+        /* normal ascii, encoding 0xxxxxxx */
+        utf8_length = 1;
+    }
+    else if (codepoint < 0x800)
+    {
+        /* two bytes, encoding 110xxxxx 10xxxxxx */
+        utf8_length = 2;
+        first_byte_mark = 0xC0; /* 11000000 */
+    }
+    else if (codepoint < 0x10000)
+    {
+        /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
+        utf8_length = 3;
+        first_byte_mark = 0xE0; /* 11100000 */
+    }
+    else if (codepoint <= 0x10FFFF)
+    {
+        /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */
+        utf8_length = 4;
+        first_byte_mark = 0xF0; /* 11110000 */
+    }
+    else
+    {
+        /* invalid unicode codepoint */
+        goto fail;
+    }
+
+    /* encode as utf8 */
+    for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--)
+    {
+        /* 10xxxxxx */
+        (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF);
+        codepoint >>= 6;
+    }
+    /* encode first byte */
+    if (utf8_length > 1)
+    {
+        (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF);
+    }
+    else
+    {
+        (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F);
+    }
+
+    *output_pointer += utf8_length;
+
+    return sequence_length;
+
+fail:
+    return 0;
+}
+
+/* Parse the input text into an unescaped cinput, and populate item. */
+static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer)
+{
+    const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
+    const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
+    unsigned char *output_pointer = NULL;
+    unsigned char *output = NULL;
+
+    /* not a string */
+    if (buffer_at_offset(input_buffer)[0] != '\"')
+    {
+        goto fail;
+    }
+
+    {
+        /* calculate approximate size of the output (overestimate) */
+        size_t allocation_length = 0;
+        size_t skipped_bytes = 0;
+        while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"'))
+        {
+            /* is escape sequence */
+            if (input_end[0] == '\\')
+            {
+                if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length)
+                {
+                    /* prevent buffer overflow when last input character is a backslash */
+                    goto fail;
+                }
+                skipped_bytes++;
+                input_end++;
+            }
+            input_end++;
+        }
+        if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"'))
+        {
+            goto fail; /* string ended unexpectedly */
+        }
+
+        /* This is at most how much we need for the output */
+        allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes;
+        output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof(""));
+        if (output == NULL)
+        {
+            goto fail; /* allocation failure */
+        }
+    }
+
+    output_pointer = output;
+    /* loop through the string literal */
+    while (input_pointer < input_end)
+    {
+        if (*input_pointer != '\\')
+        {
+            *output_pointer++ = *input_pointer++;
+        }
+        /* escape sequence */
+        else
+        {
+            unsigned char sequence_length = 2;
+            if ((input_end - input_pointer) < 1)
+            {
+                goto fail;
+            }
+
+            switch (input_pointer[1])
+            {
+                case 'b':
+                    *output_pointer++ = '\b';
+                    break;
+                case 'f':
+                    *output_pointer++ = '\f';
+                    break;
+                case 'n':
+                    *output_pointer++ = '\n';
+                    break;
+                case 'r':
+                    *output_pointer++ = '\r';
+                    break;
+                case 't':
+                    *output_pointer++ = '\t';
+                    break;
+                case '\"':
+                case '\\':
+                case '/':
+                    *output_pointer++ = input_pointer[1];
+                    break;
+
+                /* UTF-16 literal */
+                case 'u':
+                    sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
+                    if (sequence_length == 0)
+                    {
+                        /* failed to convert UTF16-literal to UTF-8 */
+                        goto fail;
+                    }
+                    break;
+
+                default:
+                    goto fail;
+            }
+            input_pointer += sequence_length;
+        }
+    }
+
+    /* zero terminate the output */
+    *output_pointer = '\0';
+
+    item->type = cJSON_String;
+    item->valuestring = (char*)output;
+
+    input_buffer->offset = (size_t) (input_end - input_buffer->content);
+    input_buffer->offset++;
+
+    return true;
+
+fail:
+    if (output != NULL)
+    {
+        input_buffer->hooks.deallocate(output);
+    }
+
+    if (input_pointer != NULL)
+    {
+        input_buffer->offset = (size_t)(input_pointer - input_buffer->content);
+    }
+
+    return false;
+}
+
+/* Render the cstring provided to an escaped version that can be printed. */
+static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer)
+{
+    const unsigned char *input_pointer = NULL;
+    unsigned char *output = NULL;
+    unsigned char *output_pointer = NULL;
+    size_t output_length = 0;
+    /* numbers of additional characters needed for escaping */
+    size_t escape_characters = 0;
+
+    if (output_buffer == NULL)
+    {
+        return false;
+    }
+
+    /* empty string */
+    if (input == NULL)
+    {
+        output = ensure(output_buffer, sizeof("\"\""));
+        if (output == NULL)
+        {
+            return false;
+        }
+        strcpy((char*)output, "\"\"");
+
+        return true;
+    }
+
+    /* set "flag" to 1 if something needs to be escaped */
+    for (input_pointer = input; *input_pointer; input_pointer++)
+    {
+        switch (*input_pointer)
+        {
+            case '\"':
+            case '\\':
+            case '\b':
+            case '\f':
+            case '\n':
+            case '\r':
+            case '\t':
+                /* one character escape sequence */
+                escape_characters++;
+                break;
+            default:
+                if (*input_pointer < 32)
+                {
+                    /* UTF-16 escape sequence uXXXX */
+                    escape_characters += 5;
+                }
+                break;
+        }
+    }
+    output_length = (size_t)(input_pointer - input) + escape_characters;
+
+    output = ensure(output_buffer, output_length + sizeof("\"\""));
+    if (output == NULL)
+    {
+        return false;
+    }
+
+    /* no characters have to be escaped */
+    if (escape_characters == 0)
+    {
+        output[0] = '\"';
+        memcpy(output + 1, input, output_length);
+        output[output_length + 1] = '\"';
+        output[output_length + 2] = '\0';
+
+        return true;
+    }
+
+    output[0] = '\"';
+    output_pointer = output + 1;
+    /* copy the string */
+    for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++)
+    {
+        if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\'))
+        {
+            /* normal character, copy */
+            *output_pointer = *input_pointer;
+        }
+        else
+        {
+            /* character needs to be escaped */
+            *output_pointer++ = '\\';
+            switch (*input_pointer)
+            {
+                case '\\':
+                    *output_pointer = '\\';
+                    break;
+                case '\"':
+                    *output_pointer = '\"';
+                    break;
+                case '\b':
+                    *output_pointer = 'b';
+                    break;
+                case '\f':
+                    *output_pointer = 'f';
+                    break;
+                case '\n':
+                    *output_pointer = 'n';
+                    break;
+                case '\r':
+                    *output_pointer = 'r';
+                    break;
+                case '\t':
+                    *output_pointer = 't';
+                    break;
+                default:
+                    /* escape and print as unicode codepoint */
+                    sprintf((char*)output_pointer, "u%04x", *input_pointer);
+                    output_pointer += 4;
+                    break;
+            }
+        }
+    }
+    output[output_length + 1] = '\"';
+    output[output_length + 2] = '\0';
+
+    return true;
+}
+
+/* Invoke print_string_ptr (which is useful) on an item. */
+static cJSON_bool print_string(const cJSON * const item, printbuffer * const p)
+{
+    return print_string_ptr((unsigned char*)item->valuestring, p);
+}
+
+/* Predeclare these prototypes. */
+static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer);
+static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer);
+static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer);
+static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer);
+static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer);
+static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer);
+
+/* Utility to jump whitespace and cr/lf */
+static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer)
+{
+    if ((buffer == NULL) || (buffer->content == NULL))
+    {
+        return NULL;
+    }
+
+    while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32))
+    {
+       buffer->offset++;
+    }
+
+    if (buffer->offset == buffer->length)
+    {
+        buffer->offset--;
+    }
+
+    return buffer;
+}
+
+/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */
+static parse_buffer *skip_utf8_bom(parse_buffer * const buffer)
+{
+    if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0))
+    {
+        return NULL;
+    }
+
+    if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0))
+    {
+        buffer->offset += 3;
+    }
+
+    return buffer;
+}
+
+/* Parse an object - create a new root, and populate. */
+CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)
+{
+    parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
+    cJSON *item = NULL;
+
+    /* reset error position */
+    global_error.json = NULL;
+    global_error.position = 0;
+
+    if (value == NULL)
+    {
+        goto fail;
+    }
+
+    buffer.content = (const unsigned char*)value;
+    buffer.length = strlen((const char*)value) + sizeof("");
+    buffer.offset = 0;
+    buffer.hooks = global_hooks;
+
+    item = cJSON_New_Item(&global_hooks);
+    if (item == NULL) /* memory fail */
+    {
+        goto fail;
+    }
+
+    if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer))))
+    {
+        /* parse failure. ep is set. */
+        goto fail;
+    }
+
+    /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
+    if (require_null_terminated)
+    {
+        buffer_skip_whitespace(&buffer);
+        if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0')
+        {
+            goto fail;
+        }
+    }
+    if (return_parse_end)
+    {
+        *return_parse_end = (const char*)buffer_at_offset(&buffer);
+    }
+
+    return item;
+
+fail:
+    if (item != NULL)
+    {
+        cJSON_Delete(item);
+    }
+
+    if (value != NULL)
+    {
+        error local_error;
+        local_error.json = (const unsigned char*)value;
+        local_error.position = 0;
+
+        if (buffer.offset < buffer.length)
+        {
+            local_error.position = buffer.offset;
+        }
+        else if (buffer.length > 0)
+        {
+            local_error.position = buffer.length - 1;
+        }
+
+        if (return_parse_end != NULL)
+        {
+            *return_parse_end = (const char*)local_error.json + local_error.position;
+        }
+
+        global_error = local_error;
+    }
+
+    return NULL;
+}
+
+/* Default options for cJSON_Parse */
+CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value)
+{
+    return cJSON_ParseWithOpts(value, 0, 0);
+}
+
+#define cjson_min(a, b) ((a < b) ? a : b)
+
+static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks)
+{
+    static const size_t default_buffer_size = 256;
+    printbuffer buffer[1];
+    unsigned char *printed = NULL;
+
+    memset(buffer, 0, sizeof(buffer));
+
+    /* create buffer */
+    buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size);
+    buffer->length = default_buffer_size;
+    buffer->format = format;
+    buffer->hooks = *hooks;
+    if (buffer->buffer == NULL)
+    {
+        goto fail;
+    }
+
+    /* print the value */
+    if (!print_value(item, buffer))
+    {
+        goto fail;
+    }
+    update_offset(buffer);
+
+    /* check if reallocate is available */
+    if (hooks->reallocate != NULL)
+    {
+        printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1);
+        if (printed == NULL) {
+            goto fail;
+        }
+        buffer->buffer = NULL;
+    }
+    else /* otherwise copy the JSON over to a new buffer */
+    {
+        printed = (unsigned char*) hooks->allocate(buffer->offset + 1);
+        if (printed == NULL)
+        {
+            goto fail;
+        }
+        memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1));
+        printed[buffer->offset] = '\0'; /* just to be sure */
+
+        /* free the buffer */
+        hooks->deallocate(buffer->buffer);
+    }
+
+    return printed;
+
+fail:
+    if (buffer->buffer != NULL)
+    {
+        hooks->deallocate(buffer->buffer);
+    }
+
+    if (printed != NULL)
+    {
+        hooks->deallocate(printed);
+    }
+
+    return NULL;
+}
+
+/* Render a cJSON item/entity/structure to text. */
+CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item)
+{
+    return (char*)print(item, true, &global_hooks);
+}
+
+CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item)
+{
+    return (char*)print(item, false, &global_hooks);
+}
+
+CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)
+{
+    printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
+
+    if (prebuffer < 0)
+    {
+        return NULL;
+    }
+
+    p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer);
+    if (!p.buffer)
+    {
+        return NULL;
+    }
+
+    p.length = (size_t)prebuffer;
+    p.offset = 0;
+    p.noalloc = false;
+    p.format = fmt;
+    p.hooks = global_hooks;
+
+    if (!print_value(item, &p))
+    {
+        global_hooks.deallocate(p.buffer);
+        return NULL;
+    }
+
+    return (char*)p.buffer;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buf, const int len, const cJSON_bool fmt)
+{
+    printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
+
+    if ((len < 0) || (buf == NULL))
+    {
+        return false;
+    }
+
+    p.buffer = (unsigned char*)buf;
+    p.length = (size_t)len;
+    p.offset = 0;
+    p.noalloc = true;
+    p.format = fmt;
+    p.hooks = global_hooks;
+
+    return print_value(item, &p);
+}
+
+/* Parser core - when encountering text, process appropriately. */
+static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer)
+{
+    if ((input_buffer == NULL) || (input_buffer->content == NULL))
+    {
+        return false; /* no input */
+    }
+
+    /* parse the different types of values */
+    /* null */
+    if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0))
+    {
+        item->type = cJSON_NULL;
+        input_buffer->offset += 4;
+        return true;
+    }
+    /* false */
+    if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0))
+    {
+        item->type = cJSON_False;
+        input_buffer->offset += 5;
+        return true;
+    }
+    /* true */
+    if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0))
+    {
+        item->type = cJSON_True;
+        item->valueint = 1;
+        input_buffer->offset += 4;
+        return true;
+    }
+    /* string */
+    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"'))
+    {
+        return parse_string(item, input_buffer);
+    }
+    /* number */
+    if (can_access_at_index(input_buffer, 0) && ((buffer_at_offset(input_buffer)[0] == '-') || ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9'))))
+    {
+        return parse_number(item, input_buffer);
+    }
+    /* array */
+    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '['))
+    {
+        return parse_array(item, input_buffer);
+    }
+    /* object */
+    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{'))
+    {
+        return parse_object(item, input_buffer);
+    }
+
+    return false;
+}
+
+/* Render a value to text. */
+static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer)
+{
+    unsigned char *output = NULL;
+
+    if ((item == NULL) || (output_buffer == NULL))
+    {
+        return false;
+    }
+
+    switch ((item->type) & 0xFF)
+    {
+        case cJSON_NULL:
+            output = ensure(output_buffer, 5);
+            if (output == NULL)
+            {
+                return false;
+            }
+            strcpy((char*)output, "null");
+            return true;
+
+        case cJSON_False:
+            output = ensure(output_buffer, 6);
+            if (output == NULL)
+            {
+                return false;
+            }
+            strcpy((char*)output, "false");
+            return true;
+
+        case cJSON_True:
+            output = ensure(output_buffer, 5);
+            if (output == NULL)
+            {
+                return false;
+            }
+            strcpy((char*)output, "true");
+            return true;
+
+        case cJSON_Number:
+            return print_number(item, output_buffer);
+
+        case cJSON_Raw:
+        {
+            size_t raw_length = 0;
+            if (item->valuestring == NULL)
+            {
+                return false;
+            }
+
+            raw_length = strlen(item->valuestring) + sizeof("");
+            output = ensure(output_buffer, raw_length);
+            if (output == NULL)
+            {
+                return false;
+            }
+            memcpy(output, item->valuestring, raw_length);
+            return true;
+        }
+
+        case cJSON_String:
+            return print_string(item, output_buffer);
+
+        case cJSON_Array:
+            return print_array(item, output_buffer);
+
+        case cJSON_Object:
+            return print_object(item, output_buffer);
+
+        default:
+            return false;
+    }
+}
+
+/* Build an array from input text. */
+static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer)
+{
+    cJSON *head = NULL; /* head of the linked list */
+    cJSON *current_item = NULL;
+
+    if (input_buffer->depth >= CJSON_NESTING_LIMIT)
+    {
+        return false; /* to deeply nested */
+    }
+    input_buffer->depth++;
+
+    if (buffer_at_offset(input_buffer)[0] != '[')
+    {
+        /* not an array */
+        goto fail;
+    }
+
+    input_buffer->offset++;
+    buffer_skip_whitespace(input_buffer);
+    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']'))
+    {
+        /* empty array */
+        goto success;
+    }
+
+    /* check if we skipped to the end of the buffer */
+    if (cannot_access_at_index(input_buffer, 0))
+    {
+        input_buffer->offset--;
+        goto fail;
+    }
+
+    /* step back to character in front of the first element */
+    input_buffer->offset--;
+    /* loop through the comma separated array elements */
+    do
+    {
+        /* allocate next item */
+        cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
+        if (new_item == NULL)
+        {
+            goto fail; /* allocation failure */
+        }
+
+        /* attach next item to list */
+        if (head == NULL)
+        {
+            /* start the linked list */
+            current_item = head = new_item;
+        }
+        else
+        {
+            /* add to the end and advance */
+            current_item->next = new_item;
+            new_item->prev = current_item;
+            current_item = new_item;
+        }
+
+        /* parse next value */
+        input_buffer->offset++;
+        buffer_skip_whitespace(input_buffer);
+        if (!parse_value(current_item, input_buffer))
+        {
+            goto fail; /* failed to parse value */
+        }
+        buffer_skip_whitespace(input_buffer);
+    }
+    while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
+
+    if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']')
+    {
+        goto fail; /* expected end of array */
+    }
+
+success:
+    input_buffer->depth--;
+
+    item->type = cJSON_Array;
+    item->child = head;
+
+    input_buffer->offset++;
+
+    return true;
+
+fail:
+    if (head != NULL)
+    {
+        cJSON_Delete(head);
+    }
+
+    return false;
+}
+
+/* Render an array to text */
+static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer)
+{
+    unsigned char *output_pointer = NULL;
+    size_t length = 0;
+    cJSON *current_element = item->child;
+
+    if (output_buffer == NULL)
+    {
+        return false;
+    }
+
+    /* Compose the output array. */
+    /* opening square bracket */
+    output_pointer = ensure(output_buffer, 1);
+    if (output_pointer == NULL)
+    {
+        return false;
+    }
+
+    *output_pointer = '[';
+    output_buffer->offset++;
+    output_buffer->depth++;
+
+    while (current_element != NULL)
+    {
+        if (!print_value(current_element, output_buffer))
+        {
+            return false;
+        }
+        update_offset(output_buffer);
+        if (current_element->next)
+        {
+            length = (size_t) (output_buffer->format ? 2 : 1);
+            output_pointer = ensure(output_buffer, length + 1);
+            if (output_pointer == NULL)
+            {
+                return false;
+            }
+            *output_pointer++ = ',';
+            if(output_buffer->format)
+            {
+                *output_pointer++ = ' ';
+            }
+            *output_pointer = '\0';
+            output_buffer->offset += length;
+        }
+        current_element = current_element->next;
+    }
+
+    output_pointer = ensure(output_buffer, 2);
+    if (output_pointer == NULL)
+    {
+        return false;
+    }
+    *output_pointer++ = ']';
+    *output_pointer = '\0';
+    output_buffer->depth--;
+
+    return true;
+}
+
+/* Build an object from the text. */
+static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer)
+{
+    cJSON *head = NULL; /* linked list head */
+    cJSON *current_item = NULL;
+
+    if (input_buffer->depth >= CJSON_NESTING_LIMIT)
+    {
+        return false; /* to deeply nested */
+    }
+    input_buffer->depth++;
+
+    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{'))
+    {
+        goto fail; /* not an object */
+    }
+
+    input_buffer->offset++;
+    buffer_skip_whitespace(input_buffer);
+    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}'))
+    {
+        goto success; /* empty object */
+    }
+
+    /* check if we skipped to the end of the buffer */
+    if (cannot_access_at_index(input_buffer, 0))
+    {
+        input_buffer->offset--;
+        goto fail;
+    }
+
+    /* step back to character in front of the first element */
+    input_buffer->offset--;
+    /* loop through the comma separated array elements */
+    do
+    {
+        /* allocate next item */
+        cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
+        if (new_item == NULL)
+        {
+            goto fail; /* allocation failure */
+        }
+
+        /* attach next item to list */
+        if (head == NULL)
+        {
+            /* start the linked list */
+            current_item = head = new_item;
+        }
+        else
+        {
+            /* add to the end and advance */
+            current_item->next = new_item;
+            new_item->prev = current_item;
+            current_item = new_item;
+        }
+
+        /* parse the name of the child */
+        input_buffer->offset++;
+        buffer_skip_whitespace(input_buffer);
+        if (!parse_string(current_item, input_buffer))
+        {
+            goto fail; /* failed to parse name */
+        }
+        buffer_skip_whitespace(input_buffer);
+
+        /* swap valuestring and string, because we parsed the name */
+        current_item->string = current_item->valuestring;
+        current_item->valuestring = NULL;
+
+        if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':'))
+        {
+            goto fail; /* invalid object */
+        }
+
+        /* parse the value */
+        input_buffer->offset++;
+        buffer_skip_whitespace(input_buffer);
+        if (!parse_value(current_item, input_buffer))
+        {
+            goto fail; /* failed to parse value */
+        }
+        buffer_skip_whitespace(input_buffer);
+    }
+    while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
+
+    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}'))
+    {
+        goto fail; /* expected end of object */
+    }
+
+success:
+    input_buffer->depth--;
+
+    item->type = cJSON_Object;
+    item->child = head;
+
+    input_buffer->offset++;
+    return true;
+
+fail:
+    if (head != NULL)
+    {
+        cJSON_Delete(head);
+    }
+
+    return false;
+}
+
+/* Render an object to text. */
+static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer)
+{
+    unsigned char *output_pointer = NULL;
+    size_t length = 0;
+    cJSON *current_item = item->child;
+
+    if (output_buffer == NULL)
+    {
+        return false;
+    }
+
+    /* Compose the output: */
+    length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */
+    output_pointer = ensure(output_buffer, length + 1);
+    if (output_pointer == NULL)
+    {
+        return false;
+    }
+
+    *output_pointer++ = '{';
+    output_buffer->depth++;
+    if (output_buffer->format)
+    {
+        *output_pointer++ = '\n';
+    }
+    output_buffer->offset += length;
+
+    while (current_item)
+    {
+        if (output_buffer->format)
+        {
+            size_t i;
+            output_pointer = ensure(output_buffer, output_buffer->depth);
+            if (output_pointer == NULL)
+            {
+                return false;
+            }
+            for (i = 0; i < output_buffer->depth; i++)
+            {
+                *output_pointer++ = '\t';
+            }
+            output_buffer->offset += output_buffer->depth;
+        }
+
+        /* print key */
+        if (!print_string_ptr((unsigned char*)current_item->string, output_buffer))
+        {
+            return false;
+        }
+        update_offset(output_buffer);
+
+        length = (size_t) (output_buffer->format ? 2 : 1);
+        output_pointer = ensure(output_buffer, length);
+        if (output_pointer == NULL)
+        {
+            return false;
+        }
+        *output_pointer++ = ':';
+        if (output_buffer->format)
+        {
+            *output_pointer++ = '\t';
+        }
+        output_buffer->offset += length;
+
+        /* print value */
+        if (!print_value(current_item, output_buffer))
+        {
+            return false;
+        }
+        update_offset(output_buffer);
+
+        /* print comma if not last */
+        length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0));
+        output_pointer = ensure(output_buffer, length + 1);
+        if (output_pointer == NULL)
+        {
+            return false;
+        }
+        if (current_item->next)
+        {
+            *output_pointer++ = ',';
+        }
+
+        if (output_buffer->format)
+        {
+            *output_pointer++ = '\n';
+        }
+        *output_pointer = '\0';
+        output_buffer->offset += length;
+
+        current_item = current_item->next;
+    }
+
+    output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2);
+    if (output_pointer == NULL)
+    {
+        return false;
+    }
+    if (output_buffer->format)
+    {
+        size_t i;
+        for (i = 0; i < (output_buffer->depth - 1); i++)
+        {
+            *output_pointer++ = '\t';
+        }
+    }
+    *output_pointer++ = '}';
+    *output_pointer = '\0';
+    output_buffer->depth--;
+
+    return true;
+}
+
+/* Get Array size/item / object item. */
+CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array)
+{
+    cJSON *child = NULL;
+    size_t size = 0;
+
+    if (array == NULL)
+    {
+        return 0;
+    }
+
+    child = array->child;
+
+    while(child != NULL)
+    {
+        size++;
+        child = child->next;
+    }
+
+    /* FIXME: Can overflow here. Cannot be fixed without breaking the API */
+
+    return (int)size;
+}
+
+static cJSON* get_array_item(const cJSON *array, size_t index)
+{
+    cJSON *current_child = NULL;
+
+    if (array == NULL)
+    {
+        return NULL;
+    }
+
+    current_child = array->child;
+    while ((current_child != NULL) && (index > 0))
+    {
+        index--;
+        current_child = current_child->next;
+    }
+
+    return current_child;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index)
+{
+    if (index < 0)
+    {
+        return NULL;
+    }
+
+    return get_array_item(array, (size_t)index);
+}
+
+static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive)
+{
+    cJSON *current_element = NULL;
+
+    if ((object == NULL) || (name == NULL))
+    {
+        return NULL;
+    }
+
+    current_element = object->child;
+    if (case_sensitive)
+    {
+        while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0))
+        {
+            current_element = current_element->next;
+        }
+    }
+    else
+    {
+        while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0))
+        {
+            current_element = current_element->next;
+        }
+    }
+
+    if ((current_element == NULL) || (current_element->string == NULL)) {
+        return NULL;
+    }
+
+    return current_element;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string)
+{
+    return get_object_item(object, string, false);
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string)
+{
+    return get_object_item(object, string, true);
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string)
+{
+    return cJSON_GetObjectItem(object, string) ? 1 : 0;
+}
+
+/* Utility for array list handling. */
+static void suffix_object(cJSON *prev, cJSON *item)
+{
+    prev->next = item;
+    item->prev = prev;
+}
+
+/* Utility for handling references. */
+static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks)
+{
+    cJSON *reference = NULL;
+    if (item == NULL)
+    {
+        return NULL;
+    }
+
+    reference = cJSON_New_Item(hooks);
+    if (reference == NULL)
+    {
+        return NULL;
+    }
+
+    memcpy(reference, item, sizeof(cJSON));
+    reference->string = NULL;
+    reference->type |= cJSON_IsReference;
+    reference->next = reference->prev = NULL;
+    return reference;
+}
+
+static cJSON_bool add_item_to_array(cJSON *array, cJSON *item)
+{
+    cJSON *child = NULL;
+
+    if ((item == NULL) || (array == NULL))
+    {
+        return false;
+    }
+
+    child = array->child;
+
+    if (child == NULL)
+    {
+        /* list is empty, start new one */
+        array->child = item;
+    }
+    else
+    {
+        /* append to the end */
+        while (child->next)
+        {
+            child = child->next;
+        }
+        suffix_object(child, item);
+    }
+
+    return true;
+}
+
+/* Add item to array/object. */
+CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item)
+{
+    add_item_to_array(array, item);
+}
+
+#if defined(__clang__) || (defined(__GNUC__)  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
+    #pragma GCC diagnostic push
+#endif
+#ifdef __GNUC__
+#pragma GCC diagnostic ignored "-Wcast-qual"
+#endif
+/* helper function to cast away const */
+static void* cast_away_const(const void* string)
+{
+    return (void*)string;
+}
+#if defined(__clang__) || (defined(__GNUC__)  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
+    #pragma GCC diagnostic pop
+#endif
+
+
+static cJSON_bool add_item_to_object(cJSON * const object, const char * const string, cJSON * const item, const internal_hooks * const hooks, const cJSON_bool constant_key)
+{
+    char *new_key = NULL;
+    int new_type = cJSON_Invalid;
+
+    if ((object == NULL) || (string == NULL) || (item == NULL))
+    {
+        return false;
+    }
+
+    if (constant_key)
+    {
+        new_key = (char*)cast_away_const(string);
+        new_type = item->type | cJSON_StringIsConst;
+    }
+    else
+    {
+        new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks);
+        if (new_key == NULL)
+        {
+            return false;
+        }
+
+        new_type = item->type & ~cJSON_StringIsConst;
+    }
+
+    if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
+    {
+        hooks->deallocate(item->string);
+    }
+
+    item->string = new_key;
+    item->type = new_type;
+
+    return add_item_to_array(object, item);
+}
+
+CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
+{
+    add_item_to_object(object, string, item, &global_hooks, false);
+}
+
+/* Add an item to an object with constant string as key */
+CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
+{
+    add_item_to_object(object, string, item, &global_hooks, true);
+}
+
+CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
+{
+    if (array == NULL)
+    {
+        return;
+    }
+
+    add_item_to_array(array, create_reference(item, &global_hooks));
+}
+
+CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
+{
+    if ((object == NULL) || (string == NULL))
+    {
+        return;
+    }
+
+    add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false);
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name)
+{
+    cJSON *null = cJSON_CreateNull();
+    if (add_item_to_object(object, name, null, &global_hooks, false))
+    {
+        return null;
+    }
+
+    cJSON_Delete(null);
+    return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name)
+{
+    cJSON *true_item = cJSON_CreateTrue();
+    if (add_item_to_object(object, name, true_item, &global_hooks, false))
+    {
+        return true_item;
+    }
+
+    cJSON_Delete(true_item);
+    return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name)
+{
+    cJSON *false_item = cJSON_CreateFalse();
+    if (add_item_to_object(object, name, false_item, &global_hooks, false))
+    {
+        return false_item;
+    }
+
+    cJSON_Delete(false_item);
+    return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean)
+{
+    cJSON *bool_item = cJSON_CreateBool(boolean);
+    if (add_item_to_object(object, name, bool_item, &global_hooks, false))
+    {
+        return bool_item;
+    }
+
+    cJSON_Delete(bool_item);
+    return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number)
+{
+    cJSON *number_item = cJSON_CreateNumber(number);
+    if (add_item_to_object(object, name, number_item, &global_hooks, false))
+    {
+        return number_item;
+    }
+
+    cJSON_Delete(number_item);
+    return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string)
+{
+    cJSON *string_item = cJSON_CreateString(string);
+    if (add_item_to_object(object, name, string_item, &global_hooks, false))
+    {
+        return string_item;
+    }
+
+    cJSON_Delete(string_item);
+    return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw)
+{
+    cJSON *raw_item = cJSON_CreateRaw(raw);
+    if (add_item_to_object(object, name, raw_item, &global_hooks, false))
+    {
+        return raw_item;
+    }
+
+    cJSON_Delete(raw_item);
+    return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name)
+{
+    cJSON *object_item = cJSON_CreateObject();
+    if (add_item_to_object(object, name, object_item, &global_hooks, false))
+    {
+        return object_item;
+    }
+
+    cJSON_Delete(object_item);
+    return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name)
+{
+    cJSON *array = cJSON_CreateArray();
+    if (add_item_to_object(object, name, array, &global_hooks, false))
+    {
+        return array;
+    }
+
+    cJSON_Delete(array);
+    return NULL;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item)
+{
+    if ((parent == NULL) || (item == NULL))
+    {
+        return NULL;
+    }
+
+    if (item->prev != NULL)
+    {
+        /* not the first element */
+        item->prev->next = item->next;
+    }
+    if (item->next != NULL)
+    {
+        /* not the last element */
+        item->next->prev = item->prev;
+    }
+
+    if (item == parent->child)
+    {
+        /* first element */
+        parent->child = item->next;
+    }
+    /* make sure the detached item doesn't point anywhere anymore */
+    item->prev = NULL;
+    item->next = NULL;
+
+    return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which)
+{
+    if (which < 0)
+    {
+        return NULL;
+    }
+
+    return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which));
+}
+
+CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)
+{
+    cJSON_Delete(cJSON_DetachItemFromArray(array, which));
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string)
+{
+    cJSON *to_detach = cJSON_GetObjectItem(object, string);
+
+    return cJSON_DetachItemViaPointer(object, to_detach);
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string)
+{
+    cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string);
+
+    return cJSON_DetachItemViaPointer(object, to_detach);
+}
+
+CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)
+{
+    cJSON_Delete(cJSON_DetachItemFromObject(object, string));
+}
+
+CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string)
+{
+    cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string));
+}
+
+/* Replace array/object items with new ones. */
+CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
+{
+    cJSON *after_inserted = NULL;
+
+    if (which < 0)
+    {
+        return;
+    }
+
+    after_inserted = get_array_item(array, (size_t)which);
+    if (after_inserted == NULL)
+    {
+        add_item_to_array(array, newitem);
+        return;
+    }
+
+    newitem->next = after_inserted;
+    newitem->prev = after_inserted->prev;
+    after_inserted->prev = newitem;
+    if (after_inserted == array->child)
+    {
+        array->child = newitem;
+    }
+    else
+    {
+        newitem->prev->next = newitem;
+    }
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement)
+{
+    if ((parent == NULL) || (replacement == NULL) || (item == NULL))
+    {
+        return false;
+    }
+
+    if (replacement == item)
+    {
+        return true;
+    }
+
+    replacement->next = item->next;
+    replacement->prev = item->prev;
+
+    if (replacement->next != NULL)
+    {
+        replacement->next->prev = replacement;
+    }
+    if (replacement->prev != NULL)
+    {
+        replacement->prev->next = replacement;
+    }
+    if (parent->child == item)
+    {
+        parent->child = replacement;
+    }
+
+    item->next = NULL;
+    item->prev = NULL;
+    cJSON_Delete(item);
+
+    return true;
+}
+
+CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
+{
+    if (which < 0)
+    {
+        return;
+    }
+
+    cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem);
+}
+
+static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive)
+{
+    if ((replacement == NULL) || (string == NULL))
+    {
+        return false;
+    }
+
+    /* replace the name in the replacement */
+    if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL))
+    {
+        cJSON_free(replacement->string);
+    }
+    replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
+    replacement->type &= ~cJSON_StringIsConst;
+
+    cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement);
+
+    return true;
+}
+
+CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
+{
+    replace_item_in_object(object, string, newitem, false);
+}
+
+CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem)
+{
+    replace_item_in_object(object, string, newitem, true);
+}
+
+/* Create basic types: */
+CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void)
+{
+    cJSON *item = cJSON_New_Item(&global_hooks);
+    if(item)
+    {
+        item->type = cJSON_NULL;
+    }
+
+    return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void)
+{
+    cJSON *item = cJSON_New_Item(&global_hooks);
+    if(item)
+    {
+        item->type = cJSON_True;
+    }
+
+    return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
+{
+    cJSON *item = cJSON_New_Item(&global_hooks);
+    if(item)
+    {
+        item->type = cJSON_False;
+    }
+
+    return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool b)
+{
+    cJSON *item = cJSON_New_Item(&global_hooks);
+    if(item)
+    {
+        item->type = b ? cJSON_True : cJSON_False;
+    }
+
+    return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
+{
+    cJSON *item = cJSON_New_Item(&global_hooks);
+    if(item)
+    {
+        item->type = cJSON_Number;
+        item->valuedouble = num;
+
+        /* use saturation in case of overflow */
+        if (num >= INT_MAX)
+        {
+            item->valueint = INT_MAX;
+        }
+        else if (num <= (double)INT_MIN)
+        {
+            item->valueint = INT_MIN;
+        }
+        else
+        {
+            item->valueint = (int)num;
+        }
+    }
+
+    return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
+{
+    cJSON *item = cJSON_New_Item(&global_hooks);
+    if(item)
+    {
+        item->type = cJSON_String;
+        item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
+        if(!item->valuestring)
+        {
+            cJSON_Delete(item);
+            return NULL;
+        }
+    }
+
+    return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string)
+{
+    cJSON *item = cJSON_New_Item(&global_hooks);
+    if (item != NULL)
+    {
+        item->type = cJSON_String | cJSON_IsReference;
+        item->valuestring = (char*)cast_away_const(string);
+    }
+
+    return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child)
+{
+    cJSON *item = cJSON_New_Item(&global_hooks);
+    if (item != NULL) {
+        item->type = cJSON_Object | cJSON_IsReference;
+        item->child = (cJSON*)cast_away_const(child);
+    }
+
+    return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) {
+    cJSON *item = cJSON_New_Item(&global_hooks);
+    if (item != NULL) {
+        item->type = cJSON_Array | cJSON_IsReference;
+        item->child = (cJSON*)cast_away_const(child);
+    }
+
+    return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)
+{
+    cJSON *item = cJSON_New_Item(&global_hooks);
+    if(item)
+    {
+        item->type = cJSON_Raw;
+        item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks);
+        if(!item->valuestring)
+        {
+            cJSON_Delete(item);
+            return NULL;
+        }
+    }
+
+    return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void)
+{
+    cJSON *item = cJSON_New_Item(&global_hooks);
+    if(item)
+    {
+        item->type=cJSON_Array;
+    }
+
+    return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void)
+{
+    cJSON *item = cJSON_New_Item(&global_hooks);
+    if (item)
+    {
+        item->type = cJSON_Object;
+    }
+
+    return item;
+}
+
+/* Create Arrays: */
+CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
+{
+    size_t i = 0;
+    cJSON *n = NULL;
+    cJSON *p = NULL;
+    cJSON *a = NULL;
+
+    if ((count < 0) || (numbers == NULL))
+    {
+        return NULL;
+    }
+
+    a = cJSON_CreateArray();
+    for(i = 0; a && (i < (size_t)count); i++)
+    {
+        n = cJSON_CreateNumber(numbers[i]);
+        if (!n)
+        {
+            cJSON_Delete(a);
+            return NULL;
+        }
+        if(!i)
+        {
+            a->child = n;
+        }
+        else
+        {
+            suffix_object(p, n);
+        }
+        p = n;
+    }
+
+    return a;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)
+{
+    size_t i = 0;
+    cJSON *n = NULL;
+    cJSON *p = NULL;
+    cJSON *a = NULL;
+
+    if ((count < 0) || (numbers == NULL))
+    {
+        return NULL;
+    }
+
+    a = cJSON_CreateArray();
+
+    for(i = 0; a && (i < (size_t)count); i++)
+    {
+        n = cJSON_CreateNumber((double)numbers[i]);
+        if(!n)
+        {
+            cJSON_Delete(a);
+            return NULL;
+        }
+        if(!i)
+        {
+            a->child = n;
+        }
+        else
+        {
+            suffix_object(p, n);
+        }
+        p = n;
+    }
+
+    return a;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
+{
+    size_t i = 0;
+    cJSON *n = NULL;
+    cJSON *p = NULL;
+    cJSON *a = NULL;
+
+    if ((count < 0) || (numbers == NULL))
+    {
+        return NULL;
+    }
+
+    a = cJSON_CreateArray();
+
+    for(i = 0;a && (i < (size_t)count); i++)
+    {
+        n = cJSON_CreateNumber(numbers[i]);
+        if(!n)
+        {
+            cJSON_Delete(a);
+            return NULL;
+        }
+        if(!i)
+        {
+            a->child = n;
+        }
+        else
+        {
+            suffix_object(p, n);
+        }
+        p = n;
+    }
+
+    return a;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count)
+{
+    size_t i = 0;
+    cJSON *n = NULL;
+    cJSON *p = NULL;
+    cJSON *a = NULL;
+
+    if ((count < 0) || (strings == NULL))
+    {
+        return NULL;
+    }
+
+    a = cJSON_CreateArray();
+
+    for (i = 0; a && (i < (size_t)count); i++)
+    {
+        n = cJSON_CreateString(strings[i]);
+        if(!n)
+        {
+            cJSON_Delete(a);
+            return NULL;
+        }
+        if(!i)
+        {
+            a->child = n;
+        }
+        else
+        {
+            suffix_object(p,n);
+        }
+        p = n;
+    }
+
+    return a;
+}
+
+/* Duplication */
+CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
+{
+    cJSON *newitem = NULL;
+    cJSON *child = NULL;
+    cJSON *next = NULL;
+    cJSON *newchild = NULL;
+
+    /* Bail on bad ptr */
+    if (!item)
+    {
+        goto fail;
+    }
+    /* Create new item */
+    newitem = cJSON_New_Item(&global_hooks);
+    if (!newitem)
+    {
+        goto fail;
+    }
+    /* Copy over all vars */
+    newitem->type = item->type & (~cJSON_IsReference);
+    newitem->valueint = item->valueint;
+    newitem->valuedouble = item->valuedouble;
+    if (item->valuestring)
+    {
+        newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks);
+        if (!newitem->valuestring)
+        {
+            goto fail;
+        }
+    }
+    if (item->string)
+    {
+        newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks);
+        if (!newitem->string)
+        {
+            goto fail;
+        }
+    }
+    /* If non-recursive, then we're done! */
+    if (!recurse)
+    {
+        return newitem;
+    }
+    /* Walk the ->next chain for the child. */
+    child = item->child;
+    while (child != NULL)
+    {
+        newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */
+        if (!newchild)
+        {
+            goto fail;
+        }
+        if (next != NULL)
+        {
+            /* If newitem->child already set, then crosswire ->prev and ->next and move on */
+            next->next = newchild;
+            newchild->prev = next;
+            next = newchild;
+        }
+        else
+        {
+            /* Set newitem->child and move to it */
+            newitem->child = newchild;
+            next = newchild;
+        }
+        child = child->next;
+    }
+
+    return newitem;
+
+fail:
+    if (newitem != NULL)
+    {
+        cJSON_Delete(newitem);
+    }
+
+    return NULL;
+}
+
+static void skip_oneline_comment(char **input)
+{
+    *input += static_strlen("//");
+
+    for (; (*input)[0] != '\0'; ++(*input))
+    {
+        if ((*input)[0] == '\n') {
+            *input += static_strlen("\n");
+            return;
+        }
+    }
+}
+
+static void skip_multiline_comment(char **input)
+{
+    *input += static_strlen("/*");
+
+    for (; (*input)[0] != '\0'; ++(*input))
+    {
+        if (((*input)[0] == '*') && ((*input)[1] == '/'))
+        {
+            *input += static_strlen("*/");
+            return;
+        }
+    }
+}
+
+static void minify_string(char **input, char **output) {
+    (*output)[0] = (*input)[0];
+    *input += static_strlen("\"");
+    *output += static_strlen("\"");
+
+
+    for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) {
+        (*output)[0] = (*input)[0];
+
+        if ((*input)[0] == '\"') {
+            (*output)[0] = '\"';
+            *input += static_strlen("\"");
+            *output += static_strlen("\"");
+            return;
+        } else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) {
+            (*output)[1] = (*input)[1];
+            *input += static_strlen("\"");
+            *output += static_strlen("\"");
+        }
+    }
+}
+
+CJSON_PUBLIC(void) cJSON_Minify(char *json)
+{
+    char *into = json;
+
+    if (json == NULL)
+    {
+        return;
+    }
+
+    while (json[0] != '\0')
+    {
+        switch (json[0])
+        {
+            case ' ':
+            case '\t':
+            case '\r':
+            case '\n':
+                json++;
+                break;
+
+            case '/':
+                if (json[1] == '/')
+                {
+                    skip_oneline_comment(&json);
+                }
+                else if (json[1] == '*')
+                {
+                    skip_multiline_comment(&json);
+                } else {
+                    json++;
+                }
+                break;
+
+            case '\"':
+                minify_string(&json, (char**)&into);
+                break;
+
+            default:
+                into[0] = json[0];
+                json++;
+                into++;
+        }
+    }
+
+    /* and null-terminate. */
+    *into = '\0';
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item)
+{
+    if (item == NULL)
+    {
+        return false;
+    }
+
+    return (item->type & 0xFF) == cJSON_Invalid;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item)
+{
+    if (item == NULL)
+    {
+        return false;
+    }
+
+    return (item->type & 0xFF) == cJSON_False;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item)
+{
+    if (item == NULL)
+    {
+        return false;
+    }
+
+    return (item->type & 0xff) == cJSON_True;
+}
+
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item)
+{
+    if (item == NULL)
+    {
+        return false;
+    }
+
+    return (item->type & (cJSON_True | cJSON_False)) != 0;
+}
+CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item)
+{
+    if (item == NULL)
+    {
+        return false;
+    }
+
+    return (item->type & 0xFF) == cJSON_NULL;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item)
+{
+    if (item == NULL)
+    {
+        return false;
+    }
+
+    return (item->type & 0xFF) == cJSON_Number;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item)
+{
+    if (item == NULL)
+    {
+        return false;
+    }
+
+    return (item->type & 0xFF) == cJSON_String;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item)
+{
+    if (item == NULL)
+    {
+        return false;
+    }
+
+    return (item->type & 0xFF) == cJSON_Array;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item)
+{
+    if (item == NULL)
+    {
+        return false;
+    }
+
+    return (item->type & 0xFF) == cJSON_Object;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item)
+{
+    if (item == NULL)
+    {
+        return false;
+    }
+
+    return (item->type & 0xFF) == cJSON_Raw;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive)
+{
+    if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)) || cJSON_IsInvalid(a))
+    {
+        return false;
+    }
+
+    /* check if type is valid */
+    switch (a->type & 0xFF)
+    {
+        case cJSON_False:
+        case cJSON_True:
+        case cJSON_NULL:
+        case cJSON_Number:
+        case cJSON_String:
+        case cJSON_Raw:
+        case cJSON_Array:
+        case cJSON_Object:
+            break;
+
+        default:
+            return false;
+    }
+
+    /* identical objects are equal */
+    if (a == b)
+    {
+        return true;
+    }
+
+    switch (a->type & 0xFF)
+    {
+        /* in these cases and equal type is enough */
+        case cJSON_False:
+        case cJSON_True:
+        case cJSON_NULL:
+            return true;
+
+        case cJSON_Number:
+            if (a->valuedouble == b->valuedouble)
+            {
+                return true;
+            }
+            return false;
+
+        case cJSON_String:
+        case cJSON_Raw:
+            if ((a->valuestring == NULL) || (b->valuestring == NULL))
+            {
+                return false;
+            }
+            if (strcmp(a->valuestring, b->valuestring) == 0)
+            {
+                return true;
+            }
+
+            return false;
+
+        case cJSON_Array:
+        {
+            cJSON *a_element = a->child;
+            cJSON *b_element = b->child;
+
+            for (; (a_element != NULL) && (b_element != NULL);)
+            {
+                if (!cJSON_Compare(a_element, b_element, case_sensitive))
+                {
+                    return false;
+                }
+
+                a_element = a_element->next;
+                b_element = b_element->next;
+            }
+
+            /* one of the arrays is longer than the other */
+            if (a_element != b_element) {
+                return false;
+            }
+
+            return true;
+        }
+
+        case cJSON_Object:
+        {
+            cJSON *a_element = NULL;
+            cJSON *b_element = NULL;
+            cJSON_ArrayForEach(a_element, a)
+            {
+                /* TODO This has O(n^2) runtime, which is horrible! */
+                b_element = get_object_item(b, a_element->string, case_sensitive);
+                if (b_element == NULL)
+                {
+                    return false;
+                }
+
+                if (!cJSON_Compare(a_element, b_element, case_sensitive))
+                {
+                    return false;
+                }
+            }
+
+            /* doing this twice, once on a and b to prevent true comparison if a subset of b
+             * TODO: Do this the proper way, this is just a fix for now */
+            cJSON_ArrayForEach(b_element, b)
+            {
+                a_element = get_object_item(a, b_element->string, case_sensitive);
+                if (a_element == NULL)
+                {
+                    return false;
+                }
+
+                if (!cJSON_Compare(b_element, a_element, case_sensitive))
+                {
+                    return false;
+                }
+            }
+
+            return true;
+        }
+
+        default:
+            return false;
+    }
+}
+
+CJSON_PUBLIC(void *) cJSON_malloc(size_t size)
+{
+    return global_hooks.allocate(size);
+}
+
+CJSON_PUBLIC(void) cJSON_free(void *object)
+{
+    global_hooks.deallocate(object);
+}

+ 285 - 0
scbc.tools/cJson/cJSON.h

@@ -0,0 +1,285 @@
+/*
+  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
+
+  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.
+*/
+
+#ifndef cJSON__h
+#define cJSON__h
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
+#define __WINDOWS__
+#endif
+
+#ifdef __WINDOWS__
+
+/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention.  For windows you have 3 define options:
+
+CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols
+CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default)
+CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
+
+For *nix builds that support visibility attribute, you can define similar behavior by
+
+setting default visibility to hidden by adding
+-fvisibility=hidden (for gcc)
+or
+-xldscope=hidden (for sun cc)
+to CFLAGS
+
+then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does
+
+*/
+
+#define CJSON_CDECL __cdecl
+#define CJSON_STDCALL __stdcall
+
+/* export symbols by default, this is necessary for copy pasting the C and header file */
+#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)
+#define CJSON_EXPORT_SYMBOLS
+#endif
+
+#if defined(CJSON_HIDE_SYMBOLS)
+#define CJSON_PUBLIC(type)   type CJSON_STDCALL
+#elif defined(CJSON_EXPORT_SYMBOLS)
+#define CJSON_PUBLIC(type)   __declspec(dllexport) type CJSON_STDCALL
+#elif defined(CJSON_IMPORT_SYMBOLS)
+#define CJSON_PUBLIC(type)   __declspec(dllimport) type CJSON_STDCALL
+#endif
+#else /* !__WINDOWS__ */
+#define CJSON_CDECL
+#define CJSON_STDCALL
+
+#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY)
+#define CJSON_PUBLIC(type)   __attribute__((visibility("default"))) type
+#else
+#define CJSON_PUBLIC(type) type
+#endif
+#endif
+
+/* project version */
+#define CJSON_VERSION_MAJOR 1
+#define CJSON_VERSION_MINOR 7
+#define CJSON_VERSION_PATCH 12
+
+#include <stddef.h>
+
+/* cJSON Types: */
+#define cJSON_Invalid (0)
+#define cJSON_False  (1 << 0)
+#define cJSON_True   (1 << 1)
+#define cJSON_NULL   (1 << 2)
+#define cJSON_Number (1 << 3)
+#define cJSON_String (1 << 4)
+#define cJSON_Array  (1 << 5)
+#define cJSON_Object (1 << 6)
+#define cJSON_Raw    (1 << 7) /* raw json */
+
+#define cJSON_IsReference 256
+#define cJSON_StringIsConst 512
+
+/* The cJSON structure: */
+typedef struct cJSON
+{
+    /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
+    struct cJSON *next;
+    struct cJSON *prev;
+    /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
+    struct cJSON *child;
+
+    /* The type of the item, as above. */
+    int type;
+
+    /* The item's string, if type==cJSON_String  and type == cJSON_Raw */
+    char *valuestring;
+    /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
+    int valueint;
+    /* The item's number, if type==cJSON_Number */
+    double valuedouble;
+
+    /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
+    char *string;
+} cJSON;
+
+typedef struct cJSON_Hooks
+{
+      /* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */
+      void *(CJSON_CDECL *malloc_fn)(size_t sz);
+      void (CJSON_CDECL *free_fn)(void *ptr);
+} cJSON_Hooks;
+
+typedef int cJSON_bool;
+
+/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them.
+ * This is to prevent stack overflows. */
+#ifndef CJSON_NESTING_LIMIT
+#define CJSON_NESTING_LIMIT 1000
+#endif
+
+/* returns the version of cJSON as a string */
+CJSON_PUBLIC(const char*) cJSON_Version(void);
+
+/* Supply malloc, realloc and free functions to cJSON */
+CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks);
+
+/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */
+/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */
+CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
+/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
+/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */
+CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
+
+/* Render a cJSON entity to text for transfer/storage. */
+CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
+/* Render a cJSON entity to text for transfer/storage without any formatting. */
+CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item);
+/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
+CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt);
+/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */
+/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */
+CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
+/* Delete a cJSON entity and all subentities. */
+CJSON_PUBLIC(void) cJSON_Delete(cJSON *c);
+
+/* Returns the number of items in an array (or object). */
+CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
+/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */
+CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
+/* Get item "string" from object. Case insensitive. */
+CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);
+CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string);
+CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string);
+/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
+CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);
+
+/* Check if the item is a string and return its valuestring */
+CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item);
+
+/* These functions check the type of an item */
+CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item);
+
+/* These calls create a cJSON item of the appropriate type. */
+CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void);
+CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void);
+CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void);
+CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean);
+CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num);
+CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string);
+/* raw json */
+CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
+CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
+CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
+
+/* Create a string where valuestring references a string so
+ * it will not be freed by cJSON_Delete */
+CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string);
+/* Create an object/arrray that only references it's elements so
+ * they will not be freed by cJSON_Delete */
+CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child);
+CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child);
+
+/* These utilities create an Array of count items. */
+CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);
+CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);
+CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);
+CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count);
+
+/* Append item to the specified array/object. */
+CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item);
+CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
+/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object.
+ * WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before
+ * writing to `item->string` */
+CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
+/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
+CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
+CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
+
+/* Remove/Detatch items from Arrays/Objects. */
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item);
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);
+CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string);
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string);
+CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string);
+CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);
+
+/* Update array items. */
+CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement);
+CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
+CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
+CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem);
+
+/* Duplicate a cJSON item */
+CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);
+/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
+need to be released. With recurse!=0, it will duplicate any children connected to the item.
+The item->next and ->prev pointers are always zero on return from Duplicate. */
+/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal.
+ * case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */
+CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive);
+
+
+CJSON_PUBLIC(void) cJSON_Minify(char *json);
+
+/* Helper functions for creating and adding items to an object at the same time.
+ * They return the added item or NULL on failure. */
+CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name);
+CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name);
+CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name);
+CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);
+CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);
+CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);
+CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);
+CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name);
+CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name);
+
+/* When assigning an integer value, it needs to be propagated to valuedouble too. */
+#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))
+/* helper for the cJSON_SetNumberValue macro */
+CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
+#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number))
+
+/* Macro for iterating over an array or object */
+#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
+
+/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */
+CJSON_PUBLIC(void *) cJSON_malloc(size_t size);
+CJSON_PUBLIC(void) cJSON_free(void *object);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 1457 - 0
scbc.tools/cJson/cJSON_Utils.c

@@ -0,0 +1,1457 @@
+/*
+  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
+
+  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.
+*/
+
+/* disable warnings about old C89 functions in MSVC */
+#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER)
+#define _CRT_SECURE_NO_DEPRECATE
+#endif
+
+#ifdef __GNUCC__
+#pragma GCC visibility push(default)
+#endif
+#if defined(_MSC_VER)
+#pragma warning (push)
+/* disable warning about single line comments in system headers */
+#pragma warning (disable : 4001)
+#endif
+
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+
+#if defined(_MSC_VER)
+#pragma warning (pop)
+#endif
+#ifdef __GNUCC__
+#pragma GCC visibility pop
+#endif
+
+#include "cJSON_Utils.h"
+
+/* define our own boolean type */
+#ifdef true
+#undef true
+#endif
+#define true ((cJSON_bool)1)
+
+#ifdef false
+#undef false
+#endif
+#define false ((cJSON_bool)0)
+
+static unsigned char* cJSONUtils_strdup(const unsigned char* const string)
+{
+    size_t length = 0;
+    unsigned char *copy = NULL;
+
+    length = strlen((const char*)string) + sizeof("");
+    copy = (unsigned char*) cJSON_malloc(length);
+    if (copy == NULL)
+    {
+        return NULL;
+    }
+    memcpy(copy, string, length);
+
+    return copy;
+}
+
+/* string comparison which doesn't consider NULL pointers equal */
+static int compare_strings(const unsigned char *string1, const unsigned char *string2, const cJSON_bool case_sensitive)
+{
+    if ((string1 == NULL) || (string2 == NULL))
+    {
+        return 1;
+    }
+
+    if (string1 == string2)
+    {
+        return 0;
+    }
+
+    if (case_sensitive)
+    {
+        return strcmp((const char*)string1, (const char*)string2);
+    }
+
+    for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++)
+    {
+        if (*string1 == '\0')
+        {
+            return 0;
+        }
+    }
+
+    return tolower(*string1) - tolower(*string2);
+}
+
+/* Compare the next path element of two JSON pointers, two NULL pointers are considered unequal: */
+static cJSON_bool compare_pointers(const unsigned char *name, const unsigned char *pointer, const cJSON_bool case_sensitive)
+{
+    if ((name == NULL) || (pointer == NULL))
+    {
+        return false;
+    }
+
+    for (; (*name != '\0') && (*pointer != '\0') && (*pointer != '/'); (void)name++, pointer++) /* compare until next '/' */
+    {
+        if (*pointer == '~')
+        {
+            /* check for escaped '~' (~0) and '/' (~1) */
+            if (((pointer[1] != '0') || (*name != '~')) && ((pointer[1] != '1') || (*name != '/')))
+            {
+                /* invalid escape sequence or wrong character in *name */
+                return false;
+            }
+            else
+            {
+                pointer++;
+            }
+        }
+        else if ((!case_sensitive && (tolower(*name) != tolower(*pointer))) || (case_sensitive && (*name != *pointer)))
+        {
+            return false;
+        }
+    }
+    if (((*pointer != 0) && (*pointer != '/')) != (*name != 0))
+    {
+        /* one string has ended, the other not */
+        return false;;
+    }
+
+    return true;
+}
+
+/* calculate the length of a string if encoded as JSON pointer with ~0 and ~1 escape sequences */
+static size_t pointer_encoded_length(const unsigned char *string)
+{
+    size_t length;
+    for (length = 0; *string != '\0'; (void)string++, length++)
+    {
+        /* character needs to be escaped? */
+        if ((*string == '~') || (*string == '/'))
+        {
+            length++;
+        }
+    }
+
+    return length;
+}
+
+/* copy a string while escaping '~' and '/' with ~0 and ~1 JSON pointer escape codes */
+static void encode_string_as_pointer(unsigned char *destination, const unsigned char *source)
+{
+    for (; source[0] != '\0'; (void)source++, destination++)
+    {
+        if (source[0] == '/')
+        {
+            destination[1] = '1';
+            destination++;
+        }
+        else if (source[0] == '~')
+        {
+            destination[0] = '~';
+            destination[1] = '1';
+            destination++;
+        }
+        else
+        {
+            destination[0] = source[0];
+        }
+    }
+
+    destination[0] = '\0';
+}
+
+CJSON_PUBLIC(char *) cJSONUtils_FindPointerFromObjectTo(const cJSON * const object, const cJSON * const target)
+{
+    size_t child_index = 0;
+    cJSON *current_child = 0;
+
+    if ((object == NULL) || (target == NULL))
+    {
+        return NULL;
+    }
+
+    if (object == target)
+    {
+        /* found */
+        return (char*)cJSONUtils_strdup((const unsigned char*)"");
+    }
+
+    /* recursively search all children of the object or array */
+    for (current_child = object->child; current_child != NULL; (void)(current_child = current_child->next), child_index++)
+    {
+        unsigned char *target_pointer = (unsigned char*)cJSONUtils_FindPointerFromObjectTo(current_child, target);
+        /* found the target? */
+        if (target_pointer != NULL)
+        {
+            if (cJSON_IsArray(object))
+            {
+                /* reserve enough memory for a 64 bit integer + '/' and '\0' */
+                unsigned char *full_pointer = (unsigned char*)cJSON_malloc(strlen((char*)target_pointer) + 20 + sizeof("/"));
+                /* check if conversion to unsigned long is valid
+                 * This should be eliminated at compile time by dead code elimination
+                 * if size_t is an alias of unsigned long, or if it is bigger */
+                if (child_index > ULONG_MAX)
+                {
+                    cJSON_free(target_pointer);
+                    return NULL;
+                }
+                sprintf((char*)full_pointer, "/%lu%s", (unsigned long)child_index, target_pointer); /* /<array_index><path> */
+                cJSON_free(target_pointer);
+
+                return (char*)full_pointer;
+            }
+
+            if (cJSON_IsObject(object))
+            {
+                unsigned char *full_pointer = (unsigned char*)cJSON_malloc(strlen((char*)target_pointer) + pointer_encoded_length((unsigned char*)current_child->string) + 2);
+                full_pointer[0] = '/';
+                encode_string_as_pointer(full_pointer + 1, (unsigned char*)current_child->string);
+                strcat((char*)full_pointer, (char*)target_pointer);
+                cJSON_free(target_pointer);
+
+                return (char*)full_pointer;
+            }
+
+            /* reached leaf of the tree, found nothing */
+            cJSON_free(target_pointer);
+            return NULL;
+        }
+    }
+
+    /* not found */
+    return NULL;
+}
+
+/* non broken version of cJSON_GetArrayItem */
+static cJSON *get_array_item(const cJSON *array, size_t item)
+{
+    cJSON *child = array ? array->child : NULL;
+    while ((child != NULL) && (item > 0))
+    {
+        item--;
+        child = child->next;
+    }
+
+    return child;
+}
+
+static cJSON_bool decode_array_index_from_pointer(const unsigned char * const pointer, size_t * const index)
+{
+    size_t parsed_index = 0;
+    size_t position = 0;
+
+    if ((pointer[0] == '0') && ((pointer[1] != '\0') && (pointer[1] != '/')))
+    {
+        /* leading zeroes are not permitted */
+        return 0;
+    }
+
+    for (position = 0; (pointer[position] >= '0') && (pointer[0] <= '9'); position++)
+    {
+        parsed_index = (10 * parsed_index) + (size_t)(pointer[position] - '0');
+
+    }
+
+    if ((pointer[position] != '\0') && (pointer[position] != '/'))
+    {
+        return 0;
+    }
+
+    *index = parsed_index;
+
+    return 1;
+}
+
+static cJSON *get_item_from_pointer(cJSON * const object, const char * pointer, const cJSON_bool case_sensitive)
+{
+    cJSON *current_element = object;
+
+    if (pointer == NULL)
+    {
+        return NULL;
+    }
+
+    /* follow path of the pointer */
+    while ((pointer[0] == '/') && (current_element != NULL))
+    {
+        pointer++;
+        if (cJSON_IsArray(current_element))
+        {
+            size_t index = 0;
+            if (!decode_array_index_from_pointer((const unsigned char*)pointer, &index))
+            {
+                return NULL;
+            }
+
+            current_element = get_array_item(current_element, index);
+        }
+        else if (cJSON_IsObject(current_element))
+        {
+            current_element = current_element->child;
+            /* GetObjectItem. */
+            while ((current_element != NULL) && !compare_pointers((unsigned char*)current_element->string, (const unsigned char*)pointer, case_sensitive))
+            {
+                current_element = current_element->next;
+            }
+        }
+        else
+        {
+            return NULL;
+        }
+
+        /* skip to the next path token or end of string */
+        while ((pointer[0] != '\0') && (pointer[0] != '/'))
+        {
+            pointer++;
+        }
+    }
+
+    return current_element;
+}
+
+CJSON_PUBLIC(cJSON *) cJSONUtils_GetPointer(cJSON * const object, const char *pointer)
+{
+    return get_item_from_pointer(object, pointer, false);
+}
+
+CJSON_PUBLIC(cJSON *) cJSONUtils_GetPointerCaseSensitive(cJSON * const object, const char *pointer)
+{
+    return get_item_from_pointer(object, pointer, true);
+}
+
+/* JSON Patch implementation. */
+static void decode_pointer_inplace(unsigned char *string)
+{
+    unsigned char *decoded_string = string;
+
+    if (string == NULL) {
+        return;
+    }
+
+    for (; *string; (void)decoded_string++, string++)
+    {
+        if (string[0] == '~')
+        {
+            if (string[1] == '0')
+            {
+                decoded_string[0] = '~';
+            }
+            else if (string[1] == '1')
+            {
+                decoded_string[1] = '/';
+            }
+            else
+            {
+                /* invalid escape sequence */
+                return;
+            }
+
+            string++;
+        }
+    }
+
+    decoded_string[0] = '\0';
+}
+
+/* non-broken cJSON_DetachItemFromArray */
+static cJSON *detach_item_from_array(cJSON *array, size_t which)
+{
+    cJSON *c = array->child;
+    while (c && (which > 0))
+    {
+        c = c->next;
+        which--;
+    }
+    if (!c)
+    {
+        /* item doesn't exist */
+        return NULL;
+    }
+    if (c->prev)
+    {
+        /* not the first element */
+        c->prev->next = c->next;
+    }
+    if (c->next)
+    {
+        c->next->prev = c->prev;
+    }
+    if (c==array->child)
+    {
+        array->child = c->next;
+    }
+    /* make sure the detached item doesn't point anywhere anymore */
+    c->prev = c->next = NULL;
+
+    return c;
+}
+
+/* detach an item at the given path */
+static cJSON *detach_path(cJSON *object, const unsigned char *path, const cJSON_bool case_sensitive)
+{
+    unsigned char *parent_pointer = NULL;
+    unsigned char *child_pointer = NULL;
+    cJSON *parent = NULL;
+    cJSON *detached_item = NULL;
+
+    /* copy path and split it in parent and child */
+    parent_pointer = cJSONUtils_strdup(path);
+    if (parent_pointer == NULL) {
+        goto cleanup;
+    }
+
+    child_pointer = (unsigned char*)strrchr((char*)parent_pointer, '/'); /* last '/' */
+    if (child_pointer == NULL)
+    {
+        goto cleanup;
+    }
+    /* split strings */
+    child_pointer[0] = '\0';
+    child_pointer++;
+
+    parent = get_item_from_pointer(object, (char*)parent_pointer, case_sensitive);
+    decode_pointer_inplace(child_pointer);
+
+    if (cJSON_IsArray(parent))
+    {
+        size_t index = 0;
+        if (!decode_array_index_from_pointer(child_pointer, &index))
+        {
+            goto cleanup;
+        }
+        detached_item = detach_item_from_array(parent, index);
+    }
+    else if (cJSON_IsObject(parent))
+    {
+        detached_item = cJSON_DetachItemFromObject(parent, (char*)child_pointer);
+    }
+    else
+    {
+        /* Couldn't find object to remove child from. */
+        goto cleanup;
+    }
+
+cleanup:
+    if (parent_pointer != NULL)
+    {
+        cJSON_free(parent_pointer);
+    }
+
+    return detached_item;
+}
+
+/* sort lists using mergesort */
+static cJSON *sort_list(cJSON *list, const cJSON_bool case_sensitive)
+{
+    cJSON *first = list;
+    cJSON *second = list;
+    cJSON *current_item = list;
+    cJSON *result = list;
+    cJSON *result_tail = NULL;
+
+    if ((list == NULL) || (list->next == NULL))
+    {
+        /* One entry is sorted already. */
+        return result;
+    }
+
+    while ((current_item != NULL) && (current_item->next != NULL) && (compare_strings((unsigned char*)current_item->string, (unsigned char*)current_item->next->string, case_sensitive) < 0))
+    {
+        /* Test for list sorted. */
+        current_item = current_item->next;
+    }
+    if ((current_item == NULL) || (current_item->next == NULL))
+    {
+        /* Leave sorted lists unmodified. */
+        return result;
+    }
+
+    /* reset pointer to the beginning */
+    current_item = list;
+    while (current_item != NULL)
+    {
+        /* Walk two pointers to find the middle. */
+        second = second->next;
+        current_item = current_item->next;
+        /* advances current_item two steps at a time */
+        if (current_item != NULL)
+        {
+            current_item = current_item->next;
+        }
+    }
+    if ((second != NULL) && (second->prev != NULL))
+    {
+        /* Split the lists */
+        second->prev->next = NULL;
+        second->prev = NULL;
+    }
+
+    /* Recursively sort the sub-lists. */
+    first = sort_list(first, case_sensitive);
+    second = sort_list(second, case_sensitive);
+    result = NULL;
+
+    /* Merge the sub-lists */
+    while ((first != NULL) && (second != NULL))
+    {
+        cJSON *smaller = NULL;
+        if (compare_strings((unsigned char*)first->string, (unsigned char*)second->string, case_sensitive) < 0)
+        {
+            smaller = first;
+        }
+        else
+        {
+            smaller = second;
+        }
+
+        if (result == NULL)
+        {
+            /* start merged list with the smaller element */
+            result_tail = smaller;
+            result = smaller;
+        }
+        else
+        {
+            /* add smaller element to the list */
+            result_tail->next = smaller;
+            smaller->prev = result_tail;
+            result_tail = smaller;
+        }
+
+        if (first == smaller)
+        {
+            first = first->next;
+        }
+        else
+        {
+            second = second->next;
+        }
+    }
+
+    if (first != NULL)
+    {
+        /* Append rest of first list. */
+        if (result == NULL)
+        {
+            return first;
+        }
+        result_tail->next = first;
+        first->prev = result_tail;
+    }
+    if (second != NULL)
+    {
+        /* Append rest of second list */
+        if (result == NULL)
+        {
+            return second;
+        }
+        result_tail->next = second;
+        second->prev = result_tail;
+    }
+
+    return result;
+}
+
+static void sort_object(cJSON * const object, const cJSON_bool case_sensitive)
+{
+    if (object == NULL)
+    {
+        return;
+    }
+    object->child = sort_list(object->child, case_sensitive);
+}
+
+static cJSON_bool compare_json(cJSON *a, cJSON *b, const cJSON_bool case_sensitive)
+{
+    if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)))
+    {
+        /* mismatched type. */
+        return false;
+    }
+    switch (a->type & 0xFF)
+    {
+        case cJSON_Number:
+            /* numeric mismatch. */
+            if ((a->valueint != b->valueint) || (a->valuedouble != b->valuedouble))
+            {
+                return false;
+            }
+            else
+            {
+                return true;
+            }
+
+        case cJSON_String:
+            /* string mismatch. */
+            if (strcmp(a->valuestring, b->valuestring) != 0)
+            {
+                return false;
+            }
+            else
+            {
+                return true;
+            }
+
+        case cJSON_Array:
+            for ((void)(a = a->child), b = b->child; (a != NULL) && (b != NULL); (void)(a = a->next), b = b->next)
+            {
+                cJSON_bool identical = compare_json(a, b, case_sensitive);
+                if (!identical)
+                {
+                    return false;
+                }
+            }
+
+            /* array size mismatch? (one of both children is not NULL) */
+            if ((a != NULL) || (b != NULL))
+            {
+                return false;
+            }
+            else
+            {
+                return true;
+            }
+
+        case cJSON_Object:
+            sort_object(a, case_sensitive);
+            sort_object(b, case_sensitive);
+            for ((void)(a = a->child), b = b->child; (a != NULL) && (b != NULL); (void)(a = a->next), b = b->next)
+            {
+                cJSON_bool identical = false;
+                /* compare object keys */
+                if (compare_strings((unsigned char*)a->string, (unsigned char*)b->string, case_sensitive))
+                {
+                    /* missing member */
+                    return false;
+                }
+                identical = compare_json(a, b, case_sensitive);
+                if (!identical)
+                {
+                    return false;
+                }
+            }
+
+            /* object length mismatch (one of both children is not null) */
+            if ((a != NULL) || (b != NULL))
+            {
+                return false;
+            }
+            else
+            {
+                return true;
+            }
+
+        default:
+            break;
+    }
+
+    /* null, true or false */
+    return true;
+}
+
+/* non broken version of cJSON_InsertItemInArray */
+static cJSON_bool insert_item_in_array(cJSON *array, size_t which, cJSON *newitem)
+{
+    cJSON *child = array->child;
+    while (child && (which > 0))
+    {
+        child = child->next;
+        which--;
+    }
+    if (which > 0)
+    {
+        /* item is after the end of the array */
+        return 0;
+    }
+    if (child == NULL)
+    {
+        cJSON_AddItemToArray(array, newitem);
+        return 1;
+    }
+
+    /* insert into the linked list */
+    newitem->next = child;
+    newitem->prev = child->prev;
+    child->prev = newitem;
+
+    /* was it at the beginning */
+    if (child == array->child)
+    {
+        array->child = newitem;
+    }
+    else
+    {
+        newitem->prev->next = newitem;
+    }
+
+    return 1;
+}
+
+static cJSON *get_object_item(const cJSON * const object, const char* name, const cJSON_bool case_sensitive)
+{
+    if (case_sensitive)
+    {
+        return cJSON_GetObjectItemCaseSensitive(object, name);
+    }
+
+    return cJSON_GetObjectItem(object, name);
+}
+
+enum patch_operation { INVALID, ADD, REMOVE, REPLACE, MOVE, COPY, TEST };
+
+static enum patch_operation decode_patch_operation(const cJSON * const patch, const cJSON_bool case_sensitive)
+{
+    cJSON *operation = get_object_item(patch, "op", case_sensitive);
+    if (!cJSON_IsString(operation))
+    {
+        return INVALID;
+    }
+
+    if (strcmp(operation->valuestring, "add") == 0)
+    {
+        return ADD;
+    }
+
+    if (strcmp(operation->valuestring, "remove") == 0)
+    {
+        return REMOVE;
+    }
+
+    if (strcmp(operation->valuestring, "replace") == 0)
+    {
+        return REPLACE;
+    }
+
+    if (strcmp(operation->valuestring, "move") == 0)
+    {
+        return MOVE;
+    }
+
+    if (strcmp(operation->valuestring, "copy") == 0)
+    {
+        return COPY;
+    }
+
+    if (strcmp(operation->valuestring, "test") == 0)
+    {
+        return TEST;
+    }
+
+    return INVALID;
+}
+
+/* overwrite and existing item with another one and free resources on the way */
+static void overwrite_item(cJSON * const root, const cJSON replacement)
+{
+    if (root == NULL)
+    {
+        return;
+    }
+
+    if (root->string != NULL)
+    {
+        cJSON_free(root->string);
+    }
+    if (root->valuestring != NULL)
+    {
+        cJSON_free(root->valuestring);
+    }
+    if (root->child != NULL)
+    {
+        cJSON_Delete(root->child);
+    }
+
+    memcpy(root, &replacement, sizeof(cJSON));
+}
+
+static int apply_patch(cJSON *object, const cJSON *patch, const cJSON_bool case_sensitive)
+{
+    cJSON *path = NULL;
+    cJSON *value = NULL;
+    cJSON *parent = NULL;
+    enum patch_operation opcode = INVALID;
+    unsigned char *parent_pointer = NULL;
+    unsigned char *child_pointer = NULL;
+    int status = 0;
+
+    path = get_object_item(patch, "path", case_sensitive);
+    if (!cJSON_IsString(path))
+    {
+        /* malformed patch. */
+        status = 2;
+        goto cleanup;
+    }
+
+    opcode = decode_patch_operation(patch, case_sensitive);
+    if (opcode == INVALID)
+    {
+        status = 3;
+        goto cleanup;
+    }
+    else if (opcode == TEST)
+    {
+        /* compare value: {...} with the given path */
+        status = !compare_json(get_item_from_pointer(object, path->valuestring, case_sensitive), get_object_item(patch, "value", case_sensitive), case_sensitive);
+        goto cleanup;
+    }
+
+    /* special case for replacing the root */
+    if (path->valuestring[0] == '\0')
+    {
+        if (opcode == REMOVE)
+        {
+            static const cJSON invalid = { NULL, NULL, NULL, cJSON_Invalid, NULL, 0, 0, NULL};
+
+            overwrite_item(object, invalid);
+
+            status = 0;
+            goto cleanup;
+        }
+
+        if ((opcode == REPLACE) || (opcode == ADD))
+        {
+            value = get_object_item(patch, "value", case_sensitive);
+            if (value == NULL)
+            {
+                /* missing "value" for add/replace. */
+                status = 7;
+                goto cleanup;
+            }
+
+            value = cJSON_Duplicate(value, 1);
+            if (value == NULL)
+            {
+                /* out of memory for add/replace. */
+                status = 8;
+                goto cleanup;
+            }
+
+            overwrite_item(object, *value);
+
+            /* delete the duplicated value */
+            cJSON_free(value);
+            value = NULL;
+
+            /* the string "value" isn't needed */
+            if (object->string != NULL)
+            {
+                cJSON_free(object->string);
+                object->string = NULL;
+            }
+
+            status = 0;
+            goto cleanup;
+        }
+    }
+
+    if ((opcode == REMOVE) || (opcode == REPLACE))
+    {
+        /* Get rid of old. */
+        cJSON *old_item = detach_path(object, (unsigned char*)path->valuestring, case_sensitive);
+        if (old_item == NULL)
+        {
+            status = 13;
+            goto cleanup;
+        }
+        cJSON_Delete(old_item);
+        if (opcode == REMOVE)
+        {
+            /* For Remove, this job is done. */
+            status = 0;
+            goto cleanup;
+        }
+    }
+
+    /* Copy/Move uses "from". */
+    if ((opcode == MOVE) || (opcode == COPY))
+    {
+        cJSON *from = get_object_item(patch, "from", case_sensitive);
+        if (from == NULL)
+        {
+            /* missing "from" for copy/move. */
+            status = 4;
+            goto cleanup;
+        }
+
+        if (opcode == MOVE)
+        {
+            value = detach_path(object, (unsigned char*)from->valuestring, case_sensitive);
+        }
+        if (opcode == COPY)
+        {
+            value = get_item_from_pointer(object, from->valuestring, case_sensitive);
+        }
+        if (value == NULL)
+        {
+            /* missing "from" for copy/move. */
+            status = 5;
+            goto cleanup;
+        }
+        if (opcode == COPY)
+        {
+            value = cJSON_Duplicate(value, 1);
+        }
+        if (value == NULL)
+        {
+            /* out of memory for copy/move. */
+            status = 6;
+            goto cleanup;
+        }
+    }
+    else /* Add/Replace uses "value". */
+    {
+        value = get_object_item(patch, "value", case_sensitive);
+        if (value == NULL)
+        {
+            /* missing "value" for add/replace. */
+            status = 7;
+            goto cleanup;
+        }
+        value = cJSON_Duplicate(value, 1);
+        if (value == NULL)
+        {
+            /* out of memory for add/replace. */
+            status = 8;
+            goto cleanup;
+        }
+    }
+
+    /* Now, just add "value" to "path". */
+
+    /* split pointer in parent and child */
+    parent_pointer = cJSONUtils_strdup((unsigned char*)path->valuestring);
+    child_pointer = (unsigned char*)strrchr((char*)parent_pointer, '/');
+    if (child_pointer != NULL)
+    {
+        child_pointer[0] = '\0';
+        child_pointer++;
+    }
+    parent = get_item_from_pointer(object, (char*)parent_pointer, case_sensitive);
+    decode_pointer_inplace(child_pointer);
+
+    /* add, remove, replace, move, copy, test. */
+    if ((parent == NULL) || (child_pointer == NULL))
+    {
+        /* Couldn't find object to add to. */
+        status = 9;
+        goto cleanup;
+    }
+    else if (cJSON_IsArray(parent))
+    {
+        if (strcmp((char*)child_pointer, "-") == 0)
+        {
+            cJSON_AddItemToArray(parent, value);
+            value = NULL;
+        }
+        else
+        {
+            size_t index = 0;
+            if (!decode_array_index_from_pointer(child_pointer, &index))
+            {
+                status = 11;
+                goto cleanup;
+            }
+
+            if (!insert_item_in_array(parent, index, value))
+            {
+                status = 10;
+                goto cleanup;
+            }
+            value = NULL;
+        }
+    }
+    else if (cJSON_IsObject(parent))
+    {
+        if (case_sensitive)
+        {
+            cJSON_DeleteItemFromObjectCaseSensitive(parent, (char*)child_pointer);
+        }
+        else
+        {
+            cJSON_DeleteItemFromObject(parent, (char*)child_pointer);
+        }
+        cJSON_AddItemToObject(parent, (char*)child_pointer, value);
+        value = NULL;
+    }
+    else /* parent is not an object */
+    {
+        /* Couldn't find object to add to. */
+        status = 9;
+        goto cleanup;
+    }
+
+cleanup:
+    if (value != NULL)
+    {
+        cJSON_Delete(value);
+    }
+    if (parent_pointer != NULL)
+    {
+        cJSON_free(parent_pointer);
+    }
+
+    return status;
+}
+
+CJSON_PUBLIC(int) cJSONUtils_ApplyPatches(cJSON * const object, const cJSON * const patches)
+{
+    const cJSON *current_patch = NULL;
+    int status = 0;
+
+    if (!cJSON_IsArray(patches))
+    {
+        /* malformed patches. */
+        return 1;
+    }
+
+    if (patches != NULL)
+    {
+        current_patch = patches->child;
+    }
+
+    while (current_patch != NULL)
+    {
+        status = apply_patch(object, current_patch, false);
+        if (status != 0)
+        {
+            return status;
+        }
+        current_patch = current_patch->next;
+    }
+
+    return 0;
+}
+
+CJSON_PUBLIC(int) cJSONUtils_ApplyPatchesCaseSensitive(cJSON * const object, const cJSON * const patches)
+{
+    const cJSON *current_patch = NULL;
+    int status = 0;
+
+    if (!cJSON_IsArray(patches))
+    {
+        /* malformed patches. */
+        return 1;
+    }
+
+    if (patches != NULL)
+    {
+        current_patch = patches->child;
+    }
+
+    while (current_patch != NULL)
+    {
+        status = apply_patch(object, current_patch, true);
+        if (status != 0)
+        {
+            return status;
+        }
+        current_patch = current_patch->next;
+    }
+
+    return 0;
+}
+
+static void compose_patch(cJSON * const patches, const unsigned char * const operation, const unsigned char * const path, const unsigned char *suffix, const cJSON * const value)
+{
+    cJSON *patch = NULL;
+
+    if ((patches == NULL) || (operation == NULL) || (path == NULL))
+    {
+        return;
+    }
+
+    patch = cJSON_CreateObject();
+    if (patch == NULL)
+    {
+        return;
+    }
+    cJSON_AddItemToObject(patch, "op", cJSON_CreateString((const char*)operation));
+
+    if (suffix == NULL)
+    {
+        cJSON_AddItemToObject(patch, "path", cJSON_CreateString((const char*)path));
+    }
+    else
+    {
+        size_t suffix_length = pointer_encoded_length(suffix);
+        size_t path_length = strlen((const char*)path);
+        unsigned char *full_path = (unsigned char*)cJSON_malloc(path_length + suffix_length + sizeof("/"));
+
+        sprintf((char*)full_path, "%s/", (const char*)path);
+        encode_string_as_pointer(full_path + path_length + 1, suffix);
+
+        cJSON_AddItemToObject(patch, "path", cJSON_CreateString((const char*)full_path));
+        cJSON_free(full_path);
+    }
+
+    if (value != NULL)
+    {
+        cJSON_AddItemToObject(patch, "value", cJSON_Duplicate(value, 1));
+    }
+    cJSON_AddItemToArray(patches, patch);
+}
+
+CJSON_PUBLIC(void) cJSONUtils_AddPatchToArray(cJSON * const array, const char * const operation, const char * const path, const cJSON * const value)
+{
+    compose_patch(array, (const unsigned char*)operation, (const unsigned char*)path, NULL, value);
+}
+
+static void create_patches(cJSON * const patches, const unsigned char * const path, cJSON * const from, cJSON * const to, const cJSON_bool case_sensitive)
+{
+    if ((from == NULL) || (to == NULL))
+    {
+        return;
+    }
+
+    if ((from->type & 0xFF) != (to->type & 0xFF))
+    {
+        compose_patch(patches, (const unsigned char*)"replace", path, 0, to);
+        return;
+    }
+
+    switch (from->type & 0xFF)
+    {
+        case cJSON_Number:
+            if ((from->valueint != to->valueint) || (from->valuedouble != to->valuedouble))
+            {
+                compose_patch(patches, (const unsigned char*)"replace", path, NULL, to);
+            }
+            return;
+
+        case cJSON_String:
+            if (strcmp(from->valuestring, to->valuestring) != 0)
+            {
+                compose_patch(patches, (const unsigned char*)"replace", path, NULL, to);
+            }
+            return;
+
+        case cJSON_Array:
+        {
+            size_t index = 0;
+            cJSON *from_child = from->child;
+            cJSON *to_child = to->child;
+            unsigned char *new_path = (unsigned char*)cJSON_malloc(strlen((const char*)path) + 20 + sizeof("/")); /* Allow space for 64bit int. log10(2^64) = 20 */
+
+            /* generate patches for all array elements that exist in both "from" and "to" */
+            for (index = 0; (from_child != NULL) && (to_child != NULL); (void)(from_child = from_child->next), (void)(to_child = to_child->next), index++)
+            {
+                /* check if conversion to unsigned long is valid
+                 * This should be eliminated at compile time by dead code elimination
+                 * if size_t is an alias of unsigned long, or if it is bigger */
+                if (index > ULONG_MAX)
+                {
+                    cJSON_free(new_path);
+                    return;
+                }
+                sprintf((char*)new_path, "%s/%lu", path, (unsigned long)index); /* path of the current array element */
+                create_patches(patches, new_path, from_child, to_child, case_sensitive);
+            }
+
+            /* remove leftover elements from 'from' that are not in 'to' */
+            for (; (from_child != NULL); (void)(from_child = from_child->next))
+            {
+                /* check if conversion to unsigned long is valid
+                 * This should be eliminated at compile time by dead code elimination
+                 * if size_t is an alias of unsigned long, or if it is bigger */
+                if (index > ULONG_MAX)
+                {
+                    cJSON_free(new_path);
+                    return;
+                }
+                sprintf((char*)new_path, "%lu", (unsigned long)index);
+                compose_patch(patches, (const unsigned char*)"remove", path, new_path, NULL);
+            }
+            /* add new elements in 'to' that were not in 'from' */
+            for (; (to_child != NULL); (void)(to_child = to_child->next), index++)
+            {
+                compose_patch(patches, (const unsigned char*)"add", path, (const unsigned char*)"-", to_child);
+            }
+            cJSON_free(new_path);
+            return;
+        }
+
+        case cJSON_Object:
+        {
+            cJSON *from_child = NULL;
+            cJSON *to_child = NULL;
+            sort_object(from, case_sensitive);
+            sort_object(to, case_sensitive);
+
+            from_child = from->child;
+            to_child = to->child;
+            /* for all object values in the object with more of them */
+            while ((from_child != NULL) || (to_child != NULL))
+            {
+                int diff;
+                if (from_child == NULL)
+                {
+                    diff = 1;
+                }
+                else if (to_child == NULL)
+                {
+                    diff = -1;
+                }
+                else
+                {
+                    diff = compare_strings((unsigned char*)from_child->string, (unsigned char*)to_child->string, case_sensitive);
+                }
+
+                if (diff == 0)
+                {
+                    /* both object keys are the same */
+                    size_t path_length = strlen((const char*)path);
+                    size_t from_child_name_length = pointer_encoded_length((unsigned char*)from_child->string);
+                    unsigned char *new_path = (unsigned char*)cJSON_malloc(path_length + from_child_name_length + sizeof("/"));
+
+                    sprintf((char*)new_path, "%s/", path);
+                    encode_string_as_pointer(new_path + path_length + 1, (unsigned char*)from_child->string);
+
+                    /* create a patch for the element */
+                    create_patches(patches, new_path, from_child, to_child, case_sensitive);
+                    cJSON_free(new_path);
+
+                    from_child = from_child->next;
+                    to_child = to_child->next;
+                }
+                else if (diff < 0)
+                {
+                    /* object element doesn't exist in 'to' --> remove it */
+                    compose_patch(patches, (const unsigned char*)"remove", path, (unsigned char*)from_child->string, NULL);
+
+                    from_child = from_child->next;
+                }
+                else
+                {
+                    /* object element doesn't exist in 'from' --> add it */
+                    compose_patch(patches, (const unsigned char*)"add", path, (unsigned char*)to_child->string, to_child);
+
+                    to_child = to_child->next;
+                }
+            }
+            return;
+        }
+
+        default:
+            break;
+    }
+}
+
+CJSON_PUBLIC(cJSON *) cJSONUtils_GeneratePatches(cJSON * const from, cJSON * const to)
+{
+    cJSON *patches = NULL;
+
+    if ((from == NULL) || (to == NULL))
+    {
+        return NULL;
+    }
+
+    patches = cJSON_CreateArray();
+    create_patches(patches, (const unsigned char*)"", from, to, false);
+
+    return patches;
+}
+
+CJSON_PUBLIC(cJSON *) cJSONUtils_GeneratePatchesCaseSensitive(cJSON * const from, cJSON * const to)
+{
+    cJSON *patches = NULL;
+
+    if ((from == NULL) || (to == NULL))
+    {
+        return NULL;
+    }
+
+    patches = cJSON_CreateArray();
+    create_patches(patches, (const unsigned char*)"", from, to, true);
+
+    return patches;
+}
+
+CJSON_PUBLIC(void) cJSONUtils_SortObject(cJSON * const object)
+{
+    sort_object(object, false);
+}
+
+CJSON_PUBLIC(void) cJSONUtils_SortObjectCaseSensitive(cJSON * const object)
+{
+    sort_object(object, true);
+}
+
+static cJSON *merge_patch(cJSON *target, const cJSON * const patch, const cJSON_bool case_sensitive)
+{
+    cJSON *patch_child = NULL;
+
+    if (!cJSON_IsObject(patch))
+    {
+        /* scalar value, array or NULL, just duplicate */
+        cJSON_Delete(target);
+        return cJSON_Duplicate(patch, 1);
+    }
+
+    if (!cJSON_IsObject(target))
+    {
+        cJSON_Delete(target);
+        target = cJSON_CreateObject();
+    }
+
+    patch_child = patch->child;
+    while (patch_child != NULL)
+    {
+        if (cJSON_IsNull(patch_child))
+        {
+            /* NULL is the indicator to remove a value, see RFC7396 */
+            if (case_sensitive)
+            {
+                cJSON_DeleteItemFromObjectCaseSensitive(target, patch_child->string);
+            }
+            else
+            {
+                cJSON_DeleteItemFromObject(target, patch_child->string);
+            }
+        }
+        else
+        {
+            cJSON *replace_me = NULL;
+            cJSON *replacement = NULL;
+
+            if (case_sensitive)
+            {
+                replace_me = cJSON_DetachItemFromObjectCaseSensitive(target, patch_child->string);
+            }
+            else
+            {
+                replace_me = cJSON_DetachItemFromObject(target, patch_child->string);
+            }
+
+            replacement = merge_patch(replace_me, patch_child, case_sensitive);
+            if (replacement == NULL)
+            {
+                return NULL;
+            }
+
+            cJSON_AddItemToObject(target, patch_child->string, replacement);
+        }
+        patch_child = patch_child->next;
+    }
+    return target;
+}
+
+CJSON_PUBLIC(cJSON *) cJSONUtils_MergePatch(cJSON *target, const cJSON * const patch)
+{
+    return merge_patch(target, patch, false);
+}
+
+CJSON_PUBLIC(cJSON *) cJSONUtils_MergePatchCaseSensitive(cJSON *target, const cJSON * const patch)
+{
+    return merge_patch(target, patch, true);
+}
+
+static cJSON *generate_merge_patch(cJSON * const from, cJSON * const to, const cJSON_bool case_sensitive)
+{
+    cJSON *from_child = NULL;
+    cJSON *to_child = NULL;
+    cJSON *patch = NULL;
+    if (to == NULL)
+    {
+        /* patch to delete everything */
+        return cJSON_CreateNull();
+    }
+    if (!cJSON_IsObject(to) || !cJSON_IsObject(from))
+    {
+        return cJSON_Duplicate(to, 1);
+    }
+
+    sort_object(from, case_sensitive);
+    sort_object(to, case_sensitive);
+
+    from_child = from->child;
+    to_child = to->child;
+    patch = cJSON_CreateObject();
+    while (from_child || to_child)
+    {
+        int diff;
+        if (from_child != NULL)
+        {
+            if (to_child != NULL)
+            {
+                diff = strcmp(from_child->string, to_child->string);
+            }
+            else
+            {
+                diff = -1;
+            }
+        }
+        else
+        {
+            diff = 1;
+        }
+
+        if (diff < 0)
+        {
+            /* from has a value that to doesn't have -> remove */
+            cJSON_AddItemToObject(patch, from_child->string, cJSON_CreateNull());
+
+            from_child = from_child->next;
+        }
+        else if (diff > 0)
+        {
+            /* to has a value that from doesn't have -> add to patch */
+            cJSON_AddItemToObject(patch, to_child->string, cJSON_Duplicate(to_child, 1));
+
+            to_child = to_child->next;
+        }
+        else
+        {
+            /* object key exists in both objects */
+            if (!compare_json(from_child, to_child, case_sensitive))
+            {
+                /* not identical --> generate a patch */
+                cJSON_AddItemToObject(patch, to_child->string, cJSONUtils_GenerateMergePatch(from_child, to_child));
+            }
+
+            /* next key in the object */
+            from_child = from_child->next;
+            to_child = to_child->next;
+        }
+    }
+    if (patch->child == NULL)
+    {
+        /* no patch generated */
+        cJSON_Delete(patch);
+        return NULL;
+    }
+
+    return patch;
+}
+
+CJSON_PUBLIC(cJSON *) cJSONUtils_GenerateMergePatch(cJSON * const from, cJSON * const to)
+{
+    return generate_merge_patch(from, to, false);
+}
+
+CJSON_PUBLIC(cJSON *) cJSONUtils_GenerateMergePatchCaseSensitive(cJSON * const from, cJSON * const to)
+{
+    return generate_merge_patch(from, to, true);
+}

+ 88 - 0
scbc.tools/cJson/cJSON_Utils.h

@@ -0,0 +1,88 @@
+/*
+  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
+
+  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.
+*/
+
+#ifndef cJSON_Utils__h
+#define cJSON_Utils__h
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "cJSON.h"
+
+/* Implement RFC6901 (https://tools.ietf.org/html/rfc6901) JSON Pointer spec. */
+CJSON_PUBLIC(cJSON *) cJSONUtils_GetPointer(cJSON * const object, const char *pointer);
+CJSON_PUBLIC(cJSON *) cJSONUtils_GetPointerCaseSensitive(cJSON * const object, const char *pointer);
+
+/* Implement RFC6902 (https://tools.ietf.org/html/rfc6902) JSON Patch spec. */
+/* NOTE: This modifies objects in 'from' and 'to' by sorting the elements by their key */
+CJSON_PUBLIC(cJSON *) cJSONUtils_GeneratePatches(cJSON * const from, cJSON * const to);
+CJSON_PUBLIC(cJSON *) cJSONUtils_GeneratePatchesCaseSensitive(cJSON * const from, cJSON * const to);
+/* Utility for generating patch array entries. */
+CJSON_PUBLIC(void) cJSONUtils_AddPatchToArray(cJSON * const array, const char * const operation, const char * const path, const cJSON * const value);
+/* Returns 0 for success. */
+CJSON_PUBLIC(int) cJSONUtils_ApplyPatches(cJSON * const object, const cJSON * const patches);
+CJSON_PUBLIC(int) cJSONUtils_ApplyPatchesCaseSensitive(cJSON * const object, const cJSON * const patches);
+
+/*
+// Note that ApplyPatches is NOT atomic on failure. To implement an atomic ApplyPatches, use:
+//int cJSONUtils_AtomicApplyPatches(cJSON **object, cJSON *patches)
+//{
+//    cJSON *modme = cJSON_Duplicate(*object, 1);
+//    int error = cJSONUtils_ApplyPatches(modme, patches);
+//    if (!error)
+//    {
+//        cJSON_Delete(*object);
+//        *object = modme;
+//    }
+//    else
+//    {
+//        cJSON_Delete(modme);
+//    }
+//
+//    return error;
+//}
+// Code not added to library since this strategy is a LOT slower.
+*/
+
+/* Implement RFC7386 (https://tools.ietf.org/html/rfc7396) JSON Merge Patch spec. */
+/* target will be modified by patch. return value is new ptr for target. */
+CJSON_PUBLIC(cJSON *) cJSONUtils_MergePatch(cJSON *target, const cJSON * const patch);
+CJSON_PUBLIC(cJSON *) cJSONUtils_MergePatchCaseSensitive(cJSON *target, const cJSON * const patch);
+/* generates a patch to move from -> to */
+/* NOTE: This modifies objects in 'from' and 'to' by sorting the elements by their key */
+CJSON_PUBLIC(cJSON *) cJSONUtils_GenerateMergePatch(cJSON * const from, cJSON * const to);
+CJSON_PUBLIC(cJSON *) cJSONUtils_GenerateMergePatchCaseSensitive(cJSON * const from, cJSON * const to);
+
+/* Given a root object and a target object, construct a pointer from one to the other. */
+CJSON_PUBLIC(char *) cJSONUtils_FindPointerFromObjectTo(const cJSON * const object, const cJSON * const target);
+
+/* Sorts the members of the object into alphabetical order. */
+CJSON_PUBLIC(void) cJSONUtils_SortObject(cJSON * const object);
+CJSON_PUBLIC(void) cJSONUtils_SortObjectCaseSensitive(cJSON * const object);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 136 - 0
scbc.tools/filehelper/filehelper.cpp

@@ -0,0 +1,136 @@
+#include "pch.h"
+#include "filehelper.h"
+#include <shlwapi.h>
+
+// 排序和乱序使用stl;
+#include <cstdlib>
+#include <ctime>
+#include <algorithm>
+// _mkdir头文件;
+#include <direct.h>
+
+int myrandom(int i) { return std::rand() % i; }
+
+filehelper::filehelper(void)
+{
+	
+}
+
+filehelper::~filehelper(void)
+{
+
+}
+
+/************************************************************************/
+/*  函数:[2/21/2017 Jeff];
+/*  描述:;
+/*  参数:;
+/*  	[IN] :;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+void filehelper::random(IN STR_VEC& vtContent, IN BOOL bSort /* = TRUE */)
+{
+	if (bSort)
+	{//排序;
+		std::sort(vtContent.begin(), vtContent.end());
+	}
+	else
+	{//乱序;
+		//设置随即数生成器的种子;
+		std::srand(unsigned(std::time(0)));
+		std::random_shuffle(vtContent.begin(), vtContent.end(), myrandom);
+	}
+}
+
+/************************************************************************/
+/*  函数:[2/21/2017 Jeff];
+/*  描述:;
+/*  参数:;
+/*  	[IN] :;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+void filehelper::split(OUT vector<TString>& vtSplit, IN const TString str, IN const TString strSplit)
+{
+	if (str.size() == 0 || strSplit.size() == 0)
+		return;
+
+	INT nIndex = 0;
+	vtSplit.clear();
+	TString strtmp = str;
+	TString strtmp2;
+	do 
+	{
+		if (TString::npos != (nIndex = strtmp.find_first_of(strSplit)))
+		{
+			strtmp2 = strtmp.substr(0, nIndex);
+			if (strtmp2.size())vtSplit.push_back(strtmp2);
+			strtmp = strtmp.substr(nIndex + strSplit.size());
+		}
+	} while (strtmp.find_first_of(strSplit) != TString::npos);
+
+	if (strtmp.size())
+		vtSplit.push_back(strtmp);
+}
+
+//////////////////////////////////////////////////////////////////////////
+BOOL filehelper::getsubfolder(LPCTSTR lpfolder, STR_VEC *pvtfolders)
+{
+	// 路径不存在;
+	if (!PathFileExists(lpfolder))
+		return FALSE;
+
+	// 指针空;
+	if (pvtfolders == NULL) return FALSE;
+	m_pvtfolders = pvtfolders;
+
+	findsubfolder(lpfolder);
+
+	return TRUE;
+}
+
+//////////////////////////////////////////////////////////////////////////
+BOOL filehelper::getallfiles(LPCTSTR lpfolder, LPCTSTR lpfindext, STR_VEC *pvtfiles)
+{
+	// 路径不存在;
+	if (!PathFileExists(lpfolder))
+		return FALSE;
+
+	// 指针空;
+	if (pvtfiles == NULL) return FALSE;
+	m_pvtfiles = pvtfiles;
+
+	findfiles_findin_subfolder(lpfolder);
+
+	return TRUE;
+}
+
+BOOL filehelper::getfolderfiles(LPCTSTR lpfolder, LPCTSTR lpfindext, STR_VEC *pvtfiles)
+{
+	// 路径不存在;
+	if (!PathFileExists(lpfolder))
+		return FALSE;
+
+	// 指针空;
+	if (pvtfiles == NULL) return FALSE;
+	m_pvtfiles = pvtfiles;
+
+	findfiles_findout_subfolder(lpfolder);
+
+	return TRUE;
+}

+ 61 - 0
scbc.tools/filehelper/filehelper.h

@@ -0,0 +1,61 @@
+/************************************************************************/
+/*  Copyright (C), 2016-2020, [IT], 保留所有权利;
+/*  模 块 名:;
+/*  描    述:;
+/*
+/*  版    本:[V];	
+/*  作    者:[IT];
+/*  日    期:[12/22/2016];
+/*
+/*
+/*  注    意:;
+/*
+/*  修改记录:[IT];
+/*  修改日期:;
+/*  修改版本:;
+/*  修改内容:;
+/************************************************************************/
+#ifndef __FILEHELPING_20150818__
+#define __FILEHELPING_20150818__
+
+#pragma once
+
+#include "findfile.h"
+
+#define USE_IMGEXT 0
+
+class filehelper :public findfile
+{
+public:
+	filehelper(void);
+	~filehelper(void);
+
+public:
+	// 排序或乱序;
+	static void random(IN STR_VEC& vtContent, IN BOOL bSort = TRUE);
+	// 分隔数组;
+	static void split(OUT vector<TString>& vtSplit, IN const TString str, IN const TString strSplit);
+
+public:
+	// 只获取当前要目录的子文件夹,不获取子文件夹中的文件夹;
+	BOOL getsubfolder(
+		LPCTSTR lpfolder,								// 要查找的目录;
+		STR_VEC *pvtfolders								// 返回子文件夹;
+		);
+
+	// 查找当前目录及子目录下的所有文件;
+	BOOL getallfiles(
+		LPCTSTR lpfolder,								// 要查找的目录;
+		LPCTSTR lpfindext,								// 要查找的扩展名;
+		STR_VEC *pvtfiles								// 返回要查找的文件全名;
+		);
+
+	// 只查找当前目录的文件,不查找子目录;
+	BOOL getfolderfiles(
+		LPCTSTR lpfolder,								// 要查找的目录;
+		LPCTSTR lpfindext,								// 要查找的扩展名;
+		STR_VEC *pvtfiles							// 返回要查找的文件全名;
+		);
+};
+
+#endif

+ 327 - 0
scbc.tools/filehelper/findfile.cpp

@@ -0,0 +1,327 @@
+#include "pch.h"
+#include "findfile.h"
+#include <algorithm>
+
+// 查找文件的最大数量限制在nMaxLimit;
+CONST size_t nMaxLimit = 0xFFFFFFFF;	//--4294967295;
+// 查找文件的默认数量限制在nDefLimit;
+CONST size_t nDefLimit = 0xFFFFF;	//--1048575
+
+// 路径分隔符;
+CONST TCHAR		c_pathSeparator = _T('\\');
+CONST TString	s_pathSeparator = _T("\\");
+CONST TString	g_sVertical = _T("|");
+
+// 正确的扩展名及格式样列;
+// 这个值最好可以从配置文件ini或xml中获取,不用在代码里写死;
+CONST TString	g_sCorrectExt = _T("*.jpg|*.jpeg|*.png|*.bmp|*.cr2|*.nef|*.raw");
+
+
+findfile::findfile(void):
+m_nlimit(nDefLimit),
+m_pvtfiles(NULL),
+m_pvtnames(NULL),
+m_pvtfolders(NULL),
+m_pvtfiles_sth(NULL),
+m_pvtfiles_mth(NULL)
+{
+	
+}
+
+findfile::~findfile(void)
+{
+}
+
+/************************************************************************/
+/*
+函数:match
+描述:判断指定的文件命名是否匹配指定的扩展名;
+参数:
+IN	sFileExt	扩展名;
+IN	sFile		文件名;
+返回:匹配返回非0值,否则返回0;
+注意:
+*/
+/************************************************************************/
+void findfile::setlimit(IN CONST INT &nLimit)
+{
+	if (nLimit < 1)
+		m_nlimit = nDefLimit;
+	if (nLimit < nMaxLimit)
+		m_nlimit = nLimit;
+}
+
+// 获取文件名;
+TString findfile::getfilename(IN CONST TString &file)
+{
+	TString name;
+	TString strfile = file;
+	int nIndex = strfile.find_last_of(_T('\\'));	// 如果file不包含 '\\' ,得不到文件名;
+	if (nIndex == TString::npos)
+	{
+		nIndex = strfile.find_last_of(_T('.'));
+		if ( nIndex == TString::npos )
+			return _T("");
+
+		return strfile.substr(0, nIndex);
+	}
+
+	name = strfile.substr(nIndex+1);
+	nIndex = name.find_last_of(_T('.'));
+	if (nIndex == TString::npos)
+		return _T("");
+
+	return name.substr(0, nIndex);
+}
+
+void findfile::find1st(TString folder, TString &file)
+{
+	TString path = folder;
+	if (path.size() > 0 && c_pathSeparator != path[path.size() - 1])
+		path.append(s_pathSeparator);
+
+	TString _file = _T("*");
+	TString s = path + _file;
+
+	WIN32_FIND_DATA fileinfo = { 0 };
+	HANDLE handle = FindFirstFile(s.c_str(), &fileinfo);
+
+	if (NULL != handle && INVALID_HANDLE_VALUE != handle)
+	{
+		do
+		{
+			// '.'和 '..'的系统文件去除;
+			if (_T('.') != fileinfo.cFileName[0])
+			{
+				if ((FILE_ATTRIBUTE_DIRECTORY & fileinfo.dwFileAttributes) != FILE_ATTRIBUTE_DIRECTORY)	// 目录;
+				{
+					file = path + fileinfo.cFileName;
+					break;
+				}
+			}
+		} while (FindNextFile(handle, &fileinfo));
+
+		FindClose(handle);
+	}
+}
+
+// 全部;
+void findfile::findall(IN CONST TString& folder)
+{
+	TString path = folder;
+	if (path.size() > 0 && c_pathSeparator != path[path.size() - 1])
+		path.append(s_pathSeparator);
+
+	TString file = _T("*");
+	TString s = path + file;
+
+	WIN32_FIND_DATA fileinfo = { 0 };
+	HANDLE handle = FindFirstFile(s.c_str(), &fileinfo);
+
+	if (NULL != handle && INVALID_HANDLE_VALUE != handle)
+	{
+		do
+		{
+			// 检查是否超过最大数;
+			if (checklimit()) break;
+
+			// '.'和 '..'的系统文件去除;
+			if (_T('.') != fileinfo.cFileName[0])
+			{
+				if ((FILE_ATTRIBUTE_DIRECTORY & fileinfo.dwFileAttributes) == FILE_ATTRIBUTE_DIRECTORY)	// 目录;
+				{
+					m_pvtfolders->push_back(path + fileinfo.cFileName);
+					findall(path + fileinfo.cFileName);
+				}
+				else
+				{
+					if (!checklimit())
+					{
+						m_pvtnames->push_back(fileinfo.cFileName);
+						m_pvtfiles->push_back(path + fileinfo.cFileName);
+					}
+				}
+			}
+
+		} while (FindNextFile(handle, &fileinfo));
+
+		FindClose(handle);
+	}
+}
+
+void findfile::findsubfolder(IN CONST TString& folder)	// 查找子目录;
+{
+	TString path = folder;
+	if (path.size() > 0 && c_pathSeparator != path[path.size() - 1])
+		path.append(s_pathSeparator);
+
+	TString file = _T("*");
+	TString s = path + file;
+
+	WIN32_FIND_DATA fileinfo = { 0 };
+	HANDLE handle = FindFirstFile(s.c_str(), &fileinfo);
+
+	if (NULL != handle && INVALID_HANDLE_VALUE != handle)
+	{
+		do
+		{
+			if (_T('.') != fileinfo.cFileName[0])// '.'和 '..'的系统文件去除;
+			{
+				if ((FILE_ATTRIBUTE_DIRECTORY & fileinfo.dwFileAttributes) == FILE_ATTRIBUTE_DIRECTORY)	// 目录;
+				{
+					m_pvtfolders->push_back(path + fileinfo.cFileName);
+				}
+			}
+		} while (FindNextFile(handle, &fileinfo));
+
+		FindClose(handle);
+	}
+}
+
+void findfile::findallsubfolder(IN CONST TString& folder)
+{
+	TString path = folder;
+	if (path.size() > 0 && c_pathSeparator != path[path.size() - 1])
+		path.append(s_pathSeparator);
+
+	TString file = _T("*");
+	TString s = path + file;
+
+	WIN32_FIND_DATA fileinfo = { 0 };
+	HANDLE handle = FindFirstFile(s.c_str(), &fileinfo);
+
+	if (NULL != handle && INVALID_HANDLE_VALUE != handle)
+	{
+		do
+		{
+			if (_T('.') != fileinfo.cFileName[0])// '.'和 '..'的系统文件去除;
+			{
+				if ((FILE_ATTRIBUTE_DIRECTORY & fileinfo.dwFileAttributes) == FILE_ATTRIBUTE_DIRECTORY)	// 目录;
+				{
+					m_pvtfolders->push_back(path + fileinfo.cFileName);
+					findallsubfolder(path + fileinfo.cFileName); // 不入子目录查找;
+				}
+			}
+		} while (FindNextFile(handle, &fileinfo));
+
+		FindClose(handle);
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////
+void findfile::findfiles_findin_subfolder(IN CONST TString& folder)
+{
+	TString path = folder;
+	if (path.size() > 0 && c_pathSeparator != path[path.size() - 1])
+		path.append(s_pathSeparator);
+
+	TString file = _T("*");
+	TString s = path + file;
+
+	WIN32_FIND_DATA fileinfo = { 0 };
+	HANDLE handle = FindFirstFile(s.c_str(), &fileinfo);
+
+	if (NULL != handle && INVALID_HANDLE_VALUE != handle)
+	{
+		do
+		{
+			// 检查是否超过最大数;
+			if (checklimit()) break;
+
+			// '.'和 '..'的系统文件去除;
+			if (_T('.') != fileinfo.cFileName[0])
+			{
+				if ((FILE_ATTRIBUTE_DIRECTORY & fileinfo.dwFileAttributes) == FILE_ATTRIBUTE_DIRECTORY)	// 目录;
+				{
+					findfiles_findin_subfolder(path + fileinfo.cFileName);
+				}
+				else
+				{
+					if (!checklimit())
+					{
+						m_pvtfiles->push_back(path + fileinfo.cFileName);
+					}
+				}
+			}
+		} while (FindNextFile(handle, &fileinfo));
+
+		FindClose(handle);
+	}
+}
+
+void findfile::findfiles_findout_subfolder(IN CONST TString& folder)
+{
+	TString path = folder;
+	if (path.size() > 0 && c_pathSeparator != path[path.size() - 1])
+		path.append(s_pathSeparator);
+
+	TString file = _T("*");
+	TString s = path + file;
+
+	WIN32_FIND_DATA fileinfo = { 0 };
+	HANDLE handle = FindFirstFile(s.c_str(), &fileinfo);
+
+	if (NULL != handle && INVALID_HANDLE_VALUE != handle)
+	{
+		do
+		{
+			// 检查是否超过最大数;
+			if (checklimit()) break;
+
+			// '.'和 '..'的系统文件去除;
+			if (_T('.') != fileinfo.cFileName[0])
+			{
+				if ((FILE_ATTRIBUTE_DIRECTORY & fileinfo.dwFileAttributes) != FILE_ATTRIBUTE_DIRECTORY)	// 目录;
+				{
+					if (!checklimit())
+					{
+						m_pvtfiles->push_back(path + fileinfo.cFileName);
+					}
+				}
+			}
+		} while (FindNextFile(handle, &fileinfo));
+
+		FindClose(handle);
+	}
+}
+
+void findfile::findfiles_within_subfolder(IN CONST TString& folder)
+{
+	TString path = folder;
+	if (path.size() > 0 && c_pathSeparator != path[path.size() - 1])
+		path.append(s_pathSeparator);
+
+	TString file = _T("*");
+	TString s = path + file;
+
+	WIN32_FIND_DATA fileinfo = { 0 };
+	HANDLE handle = FindFirstFile(s.c_str(), &fileinfo);
+
+	if (NULL != handle && INVALID_HANDLE_VALUE != handle)
+	{
+		do
+		{
+			// 检查是否超过最大数;
+			if (checklimit()) break;
+
+			// '.'和 '..'的系统文件去除;
+			if (_T('.') != fileinfo.cFileName[0])
+			{
+				if ((FILE_ATTRIBUTE_DIRECTORY & fileinfo.dwFileAttributes) == FILE_ATTRIBUTE_DIRECTORY)	// 目录;
+				{
+					m_pvtfolders->push_back(path + fileinfo.cFileName);
+					findfiles_within_subfolder(path + fileinfo.cFileName);
+				}
+				else
+				{
+					if (!checklimit())
+					{
+						m_pvtfiles->push_back(path + fileinfo.cFileName);
+					}
+				}
+			}
+		} while (FindNextFile(handle, &fileinfo));
+
+		FindClose(handle);
+	}
+}

+ 86 - 0
scbc.tools/filehelper/findfile.h

@@ -0,0 +1,86 @@
+/************************************************************************/
+/*  Copyright (C), 2016-2020, [IT], 保留所有权利;
+/*  模 块 名:;
+/*  描    述:;
+/*
+/*  版    本:[V];	
+/*  作    者:[IT];
+/*  日    期:[12/22/2016];
+/*
+/*
+/*  注    意:;
+/*
+/*  修改记录:[IT];
+/*  修改日期:;
+/*  修改版本:;
+/*  修改内容:;
+/************************************************************************/
+#ifndef __FIND_FILE_20151003__
+#define __FIND_FILE_20151003__
+
+#include <string>
+#include <vector>
+using namespace std;
+
+#ifndef _UNICODE
+typedef string TString;
+#else
+typedef wstring TString;
+#endif
+
+typedef vector<TString> STR_VEC;
+
+#pragma once
+
+class findfile
+{
+public:
+	findfile(void);
+	virtual ~findfile(void);
+
+//protected:
+public:
+	INT m_nlimit;
+	STR_VEC m_vtEffctExt;
+	STR_VEC *m_pvtfiles;
+	STR_VEC *m_pvtnames;
+	STR_VEC *m_pvtfolders;
+
+	STR_VEC *m_pvtfiles_sth;	// s小图;
+	STR_VEC *m_pvtfiles_mth;	// m小图;	
+public:
+	static inline int findfile::match(IN CONST TString &strExt, IN CONST TString &strfile)
+	{
+		int pos = strfile.find_last_of(_T('.'));
+		if (TString::npos != pos)
+			return !_tcsicmp(strExt.c_str(), strfile.substr(pos).c_str());
+
+		return FALSE;
+	}
+	
+	static TString getfilename(IN CONST TString &file);
+protected:
+	INT  getlimit() const { return m_nlimit; }
+	void setlimit(IN CONST INT &nlimit);
+
+	inline INT checklimit() { return m_pvtfiles->size() == getlimit(); }
+	BOOL IsaDirectory(CONST TString &sDirectory) { return (FILE_ATTRIBUTE_DIRECTORY == GetFileAttributes(sDirectory.c_str())); }
+
+public:
+	void find1st(TString folder, TString &file);
+	// 查找所有文件,包括子文件夹名、文件名、文件路径;
+	void findall(IN CONST TString& folder);
+	// 只返回2级子目录名(测试ok);
+	void findsubfolder(IN CONST TString& folder);
+	// 只返回所有子目录名(测试ok);
+	void findallsubfolder(IN CONST TString& folder);
+
+	// 查找文件路径,以及查找子目录的文件路径,但不获取子目录名(测试ok);
+	void findfiles_findin_subfolder(IN CONST TString& folder);
+	// 查找文件路径,不查找子目录的文件(测试ok);
+	void findfiles_findout_subfolder(IN CONST TString& folder);
+	// 查找文件路径,以及查找子目录的文件路径,同时获取子目录名(测试ok);
+	void findfiles_within_subfolder(IN CONST TString& folder);
+};
+
+#endif

BIN
scbc.tools/lib/Log4C.dll


BIN
scbc.tools/lib/Log4C.lib


BIN
scbc.tools/lib/libcurl.lib


BIN
scbc.tools/lib/libcurld.lib


BIN
scbc.tools/lib/libeay32.lib


BIN
scbc.tools/lib/ssleay32.lib


+ 23 - 0
scbc.tools/scbc.tools.sln

@@ -0,0 +1,23 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "scbc.tools", "scbc.tools\scbc.tools.vcproj", "{95CA9F08-85F6-4FD6-A80D-15EEC854B118}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		DebugExe|Win32 = DebugExe|Win32
+		Release|Win32 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{95CA9F08-85F6-4FD6-A80D-15EEC854B118}.Debug|Win32.ActiveCfg = Debug|Win32
+		{95CA9F08-85F6-4FD6-A80D-15EEC854B118}.Debug|Win32.Build.0 = Debug|Win32
+		{95CA9F08-85F6-4FD6-A80D-15EEC854B118}.DebugExe|Win32.ActiveCfg = DebugExe|Win32
+		{95CA9F08-85F6-4FD6-A80D-15EEC854B118}.DebugExe|Win32.Build.0 = DebugExe|Win32
+		{95CA9F08-85F6-4FD6-A80D-15EEC854B118}.Release|Win32.ActiveCfg = Release|Win32
+		{95CA9F08-85F6-4FD6-A80D-15EEC854B118}.Release|Win32.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

+ 130 - 0
scbc.tools/scbc.tools/Base64.cpp

@@ -0,0 +1,130 @@
+#include "stdafx.h"
+#include "Base64.h"
+
+CBase64::CBase64(void)
+{
+}
+
+CBase64::~CBase64(void)
+{
+}
+
+const char CBase64::sm_base64digits[65] =
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+const char CBase64::sm_base64val[128] = {
+	BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
+	BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
+	BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD, 62, BAD,BAD,BAD, 63,
+	52, 53, 54, 55,  56, 57, 58, 59,  60, 61,BAD,BAD, BAD,BAD,BAD,BAD,
+	BAD,  0,  1,  2,   3,  4,  5,  6,   7,  8,  9, 10,  11, 12, 13, 14,
+	15, 16, 17, 18,  19, 20, 21, 22,  23, 24, 25,BAD, BAD,BAD,BAD,BAD,
+	BAD, 26, 27, 28,  29, 30, 31, 32,  33, 34, 35, 36,  37, 38, 39, 40,
+	41, 42, 43, 44,  45, 46, 47, 48,  49, 50, 51,BAD, BAD,BAD,BAD,BAD
+};
+
+/************************************************************************/
+/*  函数:[6/2/2016 IT];
+/*  描述:将字节转换为Base64字符;
+/*  参数:;
+/*  	[IN] pbinary:			要转换成Base64字符的二进制字节数组;
+/*  	[IN] nbinaryLen:		pbinary所指向的缓存大小;
+/*  	[OUT] pOutBase64:		返回转换后的Base64字符,以'\0'结束;
+/*  返回:返回转换成功后的Base64字符数;
+/*  注意:注意参数1是字节BYTE,返回的pOutBase64是人为加上'\0'结束符;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+void CBase64::binToBase64(IN const unsigned char *pbinary, IN size_t nbinaryLen, OUT char *pOutBase64)
+{
+	for ( ; nbinaryLen >= 3; nbinaryLen -= 3, pbinary += 3) 
+	{
+		*pOutBase64++ = sm_base64digits[pbinary[0] >> 2];
+		*pOutBase64++ = sm_base64digits[((pbinary[0] << 4) & 0x30) | (pbinary[1] >> 4)];
+		*pOutBase64++ = sm_base64digits[((pbinary[1] << 2) & 0x3c) | (pbinary[2] >> 6)];
+		*pOutBase64++ = sm_base64digits[pbinary[2] & 0x3f];
+	}
+
+	if (nbinaryLen > 0) 
+	{
+		unsigned char fragment;
+		*pOutBase64++ = sm_base64digits[pbinary[0] >> 2];
+		fragment = (pbinary[0] << 4) & 0x30;
+
+		if (nbinaryLen > 1)
+			fragment |= pbinary[1] >> 4;
+
+		*pOutBase64++ = sm_base64digits[fragment];
+		*pOutBase64++ = (nbinaryLen < 2) ? '=' : sm_base64digits[(pbinary[1] << 2) & 0x3c];
+		*pOutBase64++ = '=';
+	}
+	*pOutBase64 = '\0';
+}
+
+/************************************************************************/
+/*  函数:[6/2/2016 IT];
+/*  描述:将Base64字符串转为化二进制字节字符串;
+/*  参数:;
+/*  	[IN] pBase64:		要转化成二进制字节字符串的Base64字符;
+/*  	[OUT] pbinary:		返回转化成二进制字节的字符串;
+/*  	[IN] maxLen:		pbinary指向的缓存大小;
+/*  返回:返回转化成二进制字节字符数;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+int CBase64::base64ToBin(IN const char *pBase64, OUT unsigned char *pbinary, IN size_t maxLen)
+{
+	size_t len = 0;
+	unsigned char digit1, digit2, digit3, digit4;
+
+	if (pBase64[0] == '+' && pBase64[1] == ' ')
+		pBase64 += 2;
+	if (pBase64[0] == '\r')
+		return 0;
+
+	while (*pBase64 && *pBase64 != '\r' /*&& digit4 != '='*/) 
+	{
+		digit1 = pBase64[0];
+		if (decode64(digit1) == BAD)
+			return -1;
+		digit2 = pBase64[1];
+		if (decode64(digit2) == BAD)
+			return -1;
+		digit3 = pBase64[2];
+		if (digit3 != '=' && decode64(digit3) == BAD)
+			return -1; 
+		digit4 = pBase64[3];
+		if (digit4 != '=' && decode64(digit4) == BAD)
+			return -1;
+		pBase64 += 4;
+
+		++len;
+		if (maxLen && len > maxLen)
+			return -1;
+
+		*(pbinary++) = (decode64(digit1) << 2) | (decode64(digit2) >> 4);
+		if (digit3 != '=') 
+		{
+			++len;
+			if (maxLen && len > maxLen)
+				return -1;
+			*(pbinary++) = ((decode64(digit2) << 4) & 0xf0) | (decode64(digit3) >> 2);
+			if (digit4 != '=') 
+			{
+				++len;
+				if (maxLen && len > maxLen)
+					return -1;
+				*(pbinary++) = ((decode64(digit3) << 6) & 0xc0) | decode64(digit4);
+			} // if
+		} // if
+	} // while
+
+	return len;
+}

+ 70 - 0
scbc.tools/scbc.tools/Base64.h

@@ -0,0 +1,70 @@
+/************************************************************************/
+/*  Copyright (C), 2016-2020, [IT], 保留所有权利;
+/*  模 块 名:;
+/*  描    述:;
+/*
+/*  版    本:[V];	
+/*  作    者:[IT];
+/*  日    期:[5/24/2016];
+/*
+/*
+/*  注    意:;
+/*
+/*  修改记录:[IT];
+/*  修改日期:;
+/*  修改版本:;
+/*  修改内容:;
+/************************************************************************/
+#ifndef __BASE64_CODE__
+#define __BASE64_CODE__
+
+#pragma once
+
+class CBase64
+{
+public:
+	CBase64(void);
+	~CBase64(void);
+
+	/************************************************************************/
+	/*  函数:[5/24/2016 IT];
+	/*  描述:获取指定字符串长度对应的Base64字符长度;
+	/*  参数:;
+	/*  	[IN] len:要计算的字符长度;
+	/*  返回:返回指定长度len的字符串转换为编码Base64对应的长度,并多加一个'\0'结束符;
+	/*  注意:;
+	/************************************************************************/
+	static int CalcBase64Len(IN const size_t& len) {
+		return (len / 3 + (len % 3 ? 1 : 0)) * 4 + 1; // one more byte for '\0'
+	}
+
+	static void binToBase64(IN const unsigned char *pbinary, IN size_t nbinaryLen, OUT char *pOutBase64);
+
+	/************************************************************************/
+	/*  函数:[5/24/2016 IT];
+	/*  描述:获取指定Base64字符串长度对应的字节长度;
+	/*  参数:;
+	/*  	[IN] len:要计算的Base64字符长度;
+	/*  返回:返回指定长度len的Base64字符串转换为字节对应的长度;
+	/*  注意:;
+	/************************************************************************/
+	static int CalcBinLen(size_t len) {
+		return len / 4 * 3; 
+	}
+
+	static int base64ToBin(IN const char *pBase64, OUT unsigned char *pbinary, IN size_t maxLen);
+
+private:
+	static char decode64(unsigned char ch) {
+		return ch < 128 ? sm_base64val[ch] : BAD;
+	}
+
+private:
+	enum {BAD = -1};
+	// 必须是ASCII字符;
+	static const char sm_base64digits[65];
+	// 必须是ASCII字符;
+	static const char sm_base64val[128];
+};
+
+#endif // __BASE64_CODE__

+ 235 - 0
scbc.tools/scbc.tools/CharConvert.cpp

@@ -0,0 +1,235 @@
+#include "stdafx.h"
+#include "CharConvert.h"
+
+/* string to utf8 */
+std::string stringToUTF8(const std::string& str)
+{
+	int nwLen = MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, NULL, 0);
+	wchar_t* pwBuf = new wchar_t[nwLen + 1];
+	ZeroMemory(pwBuf, nwLen * 2 + 2);
+
+	MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.length(), pwBuf, nwLen);
+
+	int nLen = ::WideCharToMultiByte(CP_UTF8, 0, pwBuf, -1, NULL, NULL, NULL, NULL);
+
+	char* pBuf = new char[nLen + 1];
+	ZeroMemory(pBuf, nLen + 1);
+
+	WideCharToMultiByte(CP_UTF8, 0, pwBuf, nwLen, pBuf, nLen, NULL, NULL);
+
+	std::string retStr(pBuf);
+
+	delete[] pwBuf;
+	delete[] pBuf;
+
+	pwBuf = NULL;
+	pBuf = NULL;
+
+	return(retStr);
+}
+
+/* utf8 to string */
+std::string UTF8Tostring(const std::string& str)
+{
+	int nwLen = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, NULL, 0);
+
+	wchar_t* pwBuf = new wchar_t[nwLen + 1];
+	memset(pwBuf, 0, nwLen * 2 + 2);
+
+	MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), pwBuf, nwLen);
+
+	int nLen = WideCharToMultiByte(CP_ACP, 0, pwBuf, -1, NULL, NULL, NULL, NULL);
+
+	char* pBuf = new char[nLen + 1];
+	memset(pBuf, 0, nLen + 1);
+
+	WideCharToMultiByte(CP_ACP, 0, pwBuf, nwLen, pBuf, nLen, NULL, NULL);
+
+	std::string retStr = pBuf;
+
+	delete[] pwBuf;
+	delete[] pBuf;
+
+	pwBuf = NULL;
+	pBuf = NULL;
+
+	return(retStr);
+}
+
+/* UTF8 to URL String */
+std::string UTF8ToURLString(const std::string& str)
+{
+	std::string	strRes;
+	unsigned int iIndex = 0, iCount = str.length();
+
+	while(iIndex < iCount)
+	{
+		if((unsigned char)str.c_str()[iIndex] < 0x7F)
+		{
+			if ((unsigned char)str.c_str()[iIndex] == (unsigned char)(' '))
+			{
+				strRes.append(1, '+');
+			}
+			else
+			{
+				strRes.append(1, (unsigned char)str.c_str()[iIndex]);
+			}
+			++iIndex;
+		}
+		else
+		{
+			char chBuf[10];
+
+			sprintf_s(chBuf, "%%%02X%%%02X%%%02X", (unsigned char)str.c_str()[iIndex], (unsigned char)str.c_str()[iIndex + 1], (unsigned char)str.c_str()[iIndex + 3]);
+
+			std::string strTmp = chBuf;
+			strRes += strTmp;
+			iIndex += 3;
+		}
+	}
+
+	return strRes;
+}
+
+/* Hex string to char */
+char HexStrToChar(const std::string& str)
+{
+	char chRet = 0;
+
+	for (char i = 0; i < 2; i++)
+	{
+		char chTemp = str.at(i);
+		chRet *= 16;
+		
+		if(chTemp >= '0' && chTemp <= '9')
+			chRet += chTemp - '0';
+		else if(chTemp >= 'a' && chTemp <= 'f')
+			chRet += (chTemp - 'a') + 10;
+		else if(chTemp >= 'A' && chTemp <= 'F')
+			chRet += (chTemp - 'A') + 10;
+	}
+
+	return(chRet);
+}
+
+/* string to int */
+unsigned int StrToInt(const std::string& str)
+{
+	unsigned int uiRet = 0;
+
+	for(unsigned char ucIndex = 0; ucIndex < str.length(); ucIndex++)
+	{
+		char chTemp = str.at(ucIndex);
+		uiRet *= 10;
+		uiRet += chTemp - '0';
+	}
+
+	return(uiRet);
+}
+
+/************************************************************************/
+/*  函数:[4/2/2019 Wang];
+/*  描述:;
+/*  参数:;
+/*  	[IN] :;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/************************************************************************/
+unsigned char TwoHexCharToChar(char ch1,char ch2)  
+{
+	char Numb1;
+	char Numb2;
+
+	if (ch1 >= 'A')
+		Numb1 = (toupper(ch1)-'0'-7)*16;
+	else
+		Numb1 = (ch1 - '0')*16;
+
+	if (ch2 >= 'A')
+		Numb2 = (toupper(ch2) - '0' - 7);
+	else
+		Numb2 = (ch2 - '0');
+
+	return (Numb1 + Numb2);
+}
+
+
+/************************************************************************/
+/*  函数:[4/2/2019 Wang];
+/*  描述:16进制字符串转字节,16进制字符以空格间隔,如"AA BB CC 0A";
+/*  参数:;
+/*  	[IN] :;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/************************************************************************/
+std::string HexStr2Bytes(std::string strHex)
+{
+	byte value = 0;
+	std::string strBytes;
+	int nSize = strHex.size();
+	for (int i = 0; i < nSize; i+=3 )
+	{
+		strBytes.push_back(TwoHexCharToChar(strHex[i], strHex[i+1]));
+	}
+
+	return strBytes;
+}
+
+
+std::string Bytes2HexStr(const unsigned char *pbuffer, int nLen )
+{
+	std::string hex;
+	char szhex[5] = {0};
+	for ( int i = 0; i < nLen; i++ )
+	{
+		memset(szhex, 0, 5);
+		_stprintf_s(szhex, "%02X ", pbuffer[i]);
+		hex.append(szhex);
+	}
+
+	return hex;
+}
+
+//BYTE HexStrToChar(const string& szData)
+//{
+//	BYTE	byteRet = 0;
+//
+//	for (int i = 0; i < 2; ++i)
+//	{
+//		BYTE byteTmp = szData.at(i);
+//
+//		byteRet *= 16;
+//
+//		if (byteTmp >= '0' && byteTmp <= '9')
+//			byteRet += byteTmp - '0';
+//		else if (byteTmp >= 'a' && byteTmp <= 'f')
+//			byteRet += (byteTmp - 'a') + 10;
+//		else if (byteTmp >= 'A' && byteTmp <= 'F')
+//			byteRet += (byteTmp - 'A') + 10;
+//	}
+//
+//	return(byteRet);
+//}
+
+//std::string CString2string(CString csStrData)
+//{
+//	int iLen = csStrData.GetLength() + 1;
+//	char* pSrc = new char[iLen];
+//	if (pSrc == NULL)
+//	{
+//		return "";
+//	}
+//
+//	memset(pSrc, 0, iLen);
+//
+//	wchar_t* pwSrc = NULL;
+//	pwSrc = (wchar_t*)(csStrData.GetBuffer(iLen * sizeof(wchar_t)));
+//	WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)pwSrc, -1, pSrc, iLen, NULL, NULL);
+//
+//	string strRet = string(pSrc);
+//	delete[] pSrc;
+//	csStrData.ReleaseBuffer(iLen);
+//	return strRet;
+//}

+ 22 - 0
scbc.tools/scbc.tools/CharConvert.h

@@ -0,0 +1,22 @@
+#ifndef __CHAR_CONVERT_H__
+#define __CHAR_CONVERT_H__
+
+#include <string>
+//using namespace std;
+
+/* Functions */
+std::string stringToUTF8(const std::string& str);
+std::string UTF8Tostring(const std::string& str);
+std::string UTF8ToURLString(const std::string& str);
+
+char HexStrToChar(const std::string& str);
+unsigned int StrToInt(const std::string& str);
+//unsigned int UnicodeToString(const CString strIn, string& szOut);
+//std::string CString2string(CString csStrData);
+//string CString2string(CString csStrData);
+//BYTE HexStrToChar(const string& szData);
+extern std::string HexStr2Bytes(std::string strHex);
+extern unsigned char TwoHexCharToChar(char ch1,char ch2) ;
+extern std::string Bytes2HexStr( const unsigned char *pbuffer, int nLen );
+
+#endif	/* __CHAR_CONVERT_H__ */

+ 739 - 0
scbc.tools/scbc.tools/CharEncoding.cpp

@@ -0,0 +1,739 @@
+#include "stdafx.h"
+#include "CharEncoding.h"
+
+WCHAR* CharEncoding::ASCII2UNICODE(IN LPCCH lpASCIIStr)
+{
+	if ( lpASCIIStr == NULL )
+		return NULL;
+
+	// 获取宽字符字节数;
+	int cchWideChar  = MultiByteToWideChar(CP_ACP, 0, lpASCIIStr, -1, NULL, 0);
+	if ( cchWideChar == 0)
+		return NULL;
+
+	// 转换成宽字符串;
+	WCHAR *pWideChar = new WCHAR[cchWideChar + 1];
+	memset(pWideChar, 0 , sizeof(WCHAR)*(cchWideChar + 1));
+	int nWriteNum = MultiByteToWideChar(CP_ACP, 0, lpASCIIStr, -1, pWideChar, cchWideChar );
+	if ( nWriteNum != cchWideChar)
+	{ 
+		if (pWideChar) 
+			delete []pWideChar;
+		return NULL;
+	}
+
+	return pWideChar;
+}
+
+BOOL CharEncoding::ASCII2UNICODE(IN LPCCH lpASCIIStr, OUT PWCH pUNICODEStr, IN CONST INT& nUNICODEStrLen)
+{
+	if ( lpASCIIStr == NULL )
+		return FALSE;
+
+	// 获取宽字符字节数;
+	int cchWideChar  = MultiByteToWideChar(CP_ACP, 0, lpASCIIStr, -1, NULL, 0);
+	if ( cchWideChar == 0 || cchWideChar >= nUNICODEStrLen)
+		return FALSE;
+
+	// 转换成宽字符串;
+	memset(pUNICODEStr, 0 , sizeof(WCHAR)*nUNICODEStrLen);
+	int nWriteNum = MultiByteToWideChar(CP_ACP, 0, lpASCIIStr, -1, pUNICODEStr, cchWideChar );
+	if ( nWriteNum != cchWideChar)
+		return FALSE;
+
+	return TRUE;
+}
+
+BOOL CharEncoding::ASCII2UNICODE(IN LPCCH lpASCIIStr, OUT wstring &strResult)
+{
+	if ( lpASCIIStr == NULL )
+		return FALSE;
+
+	// 获取宽字符字节数;
+	int cchWideChar  = MultiByteToWideChar(CP_ACP, 0, lpASCIIStr, -1, NULL, 0);
+	if ( cchWideChar == 0 )
+		return FALSE;
+
+	// 转换成宽字符串;
+	WCHAR *pResult = new WCHAR[cchWideChar];
+	memset(pResult, 0 , sizeof(WCHAR)*cchWideChar);
+	int nWriteNum = MultiByteToWideChar(CP_ACP, 0, lpASCIIStr, -1, pResult, cchWideChar );
+	if ( nWriteNum != cchWideChar)
+		return FALSE;
+
+	strResult = pResult;
+	if ( pResult )
+		delete[] pResult;
+
+	return TRUE;
+}
+
+CHAR* CharEncoding::UNICODE2ASCII(IN LPWCH lpUNICODEStr)
+{
+	if ( lpUNICODEStr == NULL )
+		return NULL;
+
+	// 获取多字节字符字节数;
+	int cbMultiByte = WideCharToMultiByte(CP_OEMCP, 0, lpUNICODEStr, -1, NULL, 0, NULL, NULL);
+	if ( cbMultiByte == 0 )
+		return NULL;
+
+	// 转换成多字节字符;
+	CHAR *pMultiByteStr = new CHAR[cbMultiByte+1];
+	memset(pMultiByteStr, 0, cbMultiByte + 1);
+	int nWriteNum = WideCharToMultiByte(CP_OEMCP, 0, lpUNICODEStr, -1, pMultiByteStr, cbMultiByte, NULL, NULL);
+	if (nWriteNum != cbMultiByte)
+	{
+		if (pMultiByteStr) 
+			delete []pMultiByteStr;
+		return NULL;
+	}
+
+	return pMultiByteStr;
+}
+
+BOOL CharEncoding::UNICODE2ASCII(IN LPWCH lpUNICODEStr, OUT LPCH pASCIIStr, IN CONST INT& nASCIIStrLen)
+{
+	if ( lpUNICODEStr == NULL )
+		return FALSE;
+
+	// 获取多字节字符字节数;
+	int cbMultiByte = WideCharToMultiByte(CP_OEMCP, 0, lpUNICODEStr, -1, NULL, 0, NULL, NULL);
+	if ( cbMultiByte == 0 || cbMultiByte >= nASCIIStrLen )
+		return FALSE;
+
+	// 转换成多字节字符;
+	memset((void*)pASCIIStr, 0, nASCIIStrLen);
+	int nWriteNum = WideCharToMultiByte(CP_OEMCP, 0, lpUNICODEStr, -1, pASCIIStr, cbMultiByte, NULL, NULL);
+	if (nWriteNum != cbMultiByte)
+	{
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+BOOL CharEncoding::UNICODE2ASCII(IN LPWCH lpUNICODEStr, OUT string &strResult)
+{
+	if ( lpUNICODEStr == NULL )
+		return FALSE;
+
+	// 获取多字节字符字节数;
+	int cbMultiByte = WideCharToMultiByte(CP_OEMCP, 0, lpUNICODEStr, -1, NULL, 0, NULL, NULL);
+	if ( cbMultiByte == 0 )
+		return FALSE;
+
+	// 转换成多字节字符;
+	CHAR* pResult = new CHAR[cbMultiByte];
+	memset(pResult, 0, cbMultiByte);
+	int nWriteNum = WideCharToMultiByte(CP_OEMCP, 0, lpUNICODEStr, -1, pResult, cbMultiByte, NULL, NULL);
+	if (nWriteNum != cbMultiByte)
+		return FALSE;
+
+	strResult = pResult;
+	if ( pResult )
+		delete[] pResult;
+
+	return TRUE;
+}
+
+CHAR* CharEncoding::UNICODE2UTF8(IN LPWCH lpUNICODEStr)
+{
+	if ( lpUNICODEStr == NULL )
+		return NULL;
+
+	// 获取多字节字符字节数;
+	int cbMultiByte = WideCharToMultiByte(CP_UTF8, 0, lpUNICODEStr, -1, NULL, 0, NULL, NULL);
+	if ( cbMultiByte == 0 )
+		return NULL;
+
+	// 转换成多字节字符;
+	CHAR* pMultiByteStr = new CHAR[cbMultiByte+1];
+	memset(pMultiByteStr, 0, cbMultiByte + 1);
+	int nWriteNum = WideCharToMultiByte(CP_UTF8, 0, lpUNICODEStr, -1, pMultiByteStr, cbMultiByte, NULL, NULL);
+	if (nWriteNum != cbMultiByte)
+	{
+		if (pMultiByteStr) 
+			delete []pMultiByteStr;
+		return NULL;
+	}
+
+	return pMultiByteStr;
+}
+
+BOOL CharEncoding::UNICODE2UTF8(IN LPWCH lpUNICODEStr, OUT LPCH pUTF8Str, IN CONST INT& nUTF8StrLen)
+{
+	if ( lpUNICODEStr == NULL )
+		return FALSE;
+
+	// 获取多字节字符字节数;
+	int cbMultiByte = WideCharToMultiByte(CP_UTF8, 0, lpUNICODEStr, -1, NULL, 0, NULL, NULL);
+	if ( cbMultiByte == 0 || cbMultiByte >= nUTF8StrLen )
+		return FALSE;
+
+	// 转换成多字节字符;
+	memset(pUTF8Str, 0, nUTF8StrLen);
+	int nWriteNum = WideCharToMultiByte(CP_UTF8, 0, lpUNICODEStr, -1, pUTF8Str, cbMultiByte, NULL, NULL);
+	if (nWriteNum != cbMultiByte)
+	{
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+BOOL CharEncoding::UNICODE2UTF8(IN LPWCH lpUNICODEStr, OUT string &strResult)
+{
+	if ( lpUNICODEStr == NULL )
+		return FALSE;
+
+	// 获取多字节字符字节数;
+	int cbMultiByte = WideCharToMultiByte(CP_UTF8, 0, lpUNICODEStr, -1, NULL, 0, NULL, NULL);
+	if ( cbMultiByte == 0 )
+		return FALSE;
+
+	// 转换成多字节字符;
+	CHAR *pResult = new CHAR[cbMultiByte];
+	memset(pResult, 0, cbMultiByte);
+	int nWriteNum = WideCharToMultiByte(CP_UTF8, 0, lpUNICODEStr, -1, pResult, cbMultiByte, NULL, NULL);
+	if (nWriteNum != cbMultiByte)
+		return FALSE;
+
+	strResult = pResult;
+	if ( pResult )
+		delete[] pResult;
+
+	return TRUE;
+}
+
+CHAR* CharEncoding::ASCII2UTF8(IN LPCCH lpASCIIStr)
+{
+	// 将ASCII字符串转成UNICODE字符串;
+	WCHAR* pWideChar = ASCII2UNICODE(lpASCIIStr);
+	if ( pWideChar == NULL )
+		return NULL;
+
+	// 再将UICODE转成UTF8;
+	CHAR* pUTF8 = UNICODE2UTF8(pWideChar);
+	if ( pWideChar )
+		delete []pWideChar;
+
+	return pUTF8;
+}
+
+BOOL CharEncoding::ASCII2UTF8(IN LPCCH lpASCIIStr, OUT LPCH pUTF8Str, IN CONST INT& nUTF8StrLen)
+{
+	// 将ASCII字符串转成UNICODE字符串;
+	WCHAR* pWideChar = ASCII2UNICODE(lpASCIIStr);
+	if ( pWideChar == NULL )
+		return FALSE;
+
+	// 再将UICODE转成UTF8;
+	BOOL bResult = UNICODE2UTF8(pWideChar, pUTF8Str, nUTF8StrLen);
+
+	if ( pWideChar )
+		delete []pWideChar;
+
+	return bResult;
+}
+
+BOOL CharEncoding::ASCII2UTF8(IN LPCCH lpASCIIStr, OUT string &strResult)
+{
+	// 将ASCII字符串转成UNICODE字符串;
+	WCHAR* pWideChar = ASCII2UNICODE(lpASCIIStr);
+	if ( pWideChar == NULL )
+		return FALSE;
+
+	// 再将UICODE转成UTF8;
+	BOOL bResult = UNICODE2UTF8(pWideChar, strResult);
+
+	if ( pWideChar )
+		delete []pWideChar;
+
+	return bResult;
+}
+
+WCHAR* CharEncoding::UTF82UNICODE(IN LPCCH lpUTF8)
+{
+	if ( lpUTF8 == NULL )
+		return NULL;
+
+	// 获取unicode字符数;
+	int cchWideChar = MultiByteToWideChar(CP_UTF8, 0, lpUTF8, -1, NULL, 0);
+	if ( cchWideChar == 0)
+		return NULL;
+
+	// 转换成宽字符串;
+	WCHAR *pWideChar = new WCHAR[cchWideChar + 1];
+	memset(pWideChar, 0 , sizeof(WCHAR)*(cchWideChar + 1));
+	int nWriteNum = MultiByteToWideChar(CP_UTF8, 0, lpUTF8, -1, pWideChar, cchWideChar );
+	if ( nWriteNum != cchWideChar)
+	{ 
+		if (pWideChar) 
+			delete []pWideChar;
+		return NULL;
+	}
+
+	return pWideChar;
+}
+
+BOOL CharEncoding::UTF82UNICODE(IN LPCCH lpUTF8, OUT PWCH pUNICODEStr, IN CONST INT& nUNICODEStrLen)
+{
+	if ( lpUTF8 == NULL )
+		return FALSE;
+
+	// 获取宽字符字节数;
+	int cchWideChar  = MultiByteToWideChar(CP_UTF8, 0, lpUTF8, -1, NULL, 0);
+	if ( cchWideChar == 0 || cchWideChar >= nUNICODEStrLen)
+		return FALSE;
+
+	// 转换成宽字符串;
+	memset(pUNICODEStr, 0 , sizeof(WCHAR)*nUNICODEStrLen);
+	int nWriteNum = MultiByteToWideChar(CP_UTF8, 0, lpUTF8, -1, pUNICODEStr, cchWideChar );
+	if ( nWriteNum != cchWideChar)
+		return FALSE;
+
+	return TRUE;
+}
+
+BOOL CharEncoding::UTF82UNICODE(IN LPCCH lpUTF8, OUT wstring &strResult)
+{
+	if ( lpUTF8 == NULL )
+		return FALSE;
+
+	// 获取宽字符字节数;
+	int cchWideChar  = MultiByteToWideChar(CP_UTF8, 0, lpUTF8, -1, NULL, 0);
+	if ( cchWideChar == 0 )
+		return FALSE;
+
+	// 转换成宽字符串;
+	WCHAR* pResult = new WCHAR[cchWideChar];
+	memset(pResult, 0 , sizeof(WCHAR)*cchWideChar);
+	int nWriteNum = MultiByteToWideChar(CP_UTF8, 0, lpUTF8, -1, pResult, cchWideChar );
+	if ( nWriteNum != cchWideChar)
+		return FALSE;
+
+	strResult = pResult;
+	if ( pResult )
+		delete[] pResult;
+
+	return TRUE;
+}
+
+CHAR* CharEncoding::UTF82ASCII(IN LPCCH lpUTF8)
+{
+	// 将ASCII字符串转成UNICODE字符串;
+	WCHAR* pWideChar = UTF82UNICODE(lpUTF8);
+	if ( pWideChar == NULL )
+		return NULL;
+
+	// 再将UICODE转成UTF8;
+	CHAR* pUTF8 = UNICODE2ASCII(pWideChar);
+	if ( pWideChar )
+		delete []pWideChar;
+
+	return pUTF8;
+}
+
+BOOL CharEncoding::UTF82ASCII(IN LPCCH lpUTF8, OUT LPCH pASCIIStr, IN CONST INT& nASCIIStrLen)
+{
+	// 将ASCII字符串转成UNICODE字符串;
+	WCHAR* pWideChar = UTF82UNICODE(lpUTF8);
+	if ( pWideChar == NULL )
+		return FALSE;
+
+	// 再将UICODE转成UTF8;
+	BOOL bResult = UNICODE2ASCII(pWideChar, pASCIIStr, nASCIIStrLen);
+
+	if ( pWideChar )
+		delete []pWideChar;
+
+	return bResult;
+}
+
+BOOL CharEncoding::UTF82ASCII(IN LPCCH lpUTF8, OUT string &strResult)
+{
+	// 将ASCII字符串转成UNICODE字符串;
+	WCHAR* pWideChar = UTF82UNICODE(lpUTF8);
+	if ( pWideChar == NULL )
+		return FALSE;
+
+	// 再将UICODE转成UTF8;
+	BOOL bResult = UNICODE2ASCII(pWideChar, strResult);
+
+	if ( pWideChar )
+		delete []pWideChar;
+
+	return bResult;
+}
+
+//做为解Url使用
+char CharEncoding::CharToInt(char ch)
+{
+	if (ch >= '0' && ch <= '9')return (char)(ch - '0');
+	if (ch >= 'a' && ch <= 'f')return (char)(ch - 'a' + 10);
+	if (ch >= 'A' && ch <= 'F')return (char)(ch - 'A' + 10);
+	return -1;
+}
+
+char CharEncoding::StrToBin(IN char (&str)[2])
+{
+	char tempWord[2];
+	char chn;
+
+	tempWord[0] = CharToInt(str[0]);                         //make the B to 11 -- 00001011
+	tempWord[1] = CharToInt(str[1]);                         //make the 0 to 0  -- 00000000
+
+	chn = (tempWord[0] << 4) | tempWord[1];                //to change the BO to 10110000
+
+	return chn;
+}
+
+//GB2312 转为 UTF-8
+void CharEncoding::GB2312ToUTF_8(string& pOut, const char *pText, int pLen)
+{
+	char buf[4];
+	memset(buf, 0, 4);
+
+	pOut.clear();
+
+	int i = 0;
+	while (i < pLen)
+	{
+		//如果是英文直接复制就可以;
+		if (pText[i] >= 0)
+		{
+			char asciistr[2] = { 0 };
+			asciistr[0] = (pText[i++]);
+			pOut.append(asciistr);
+		}
+		else
+		{
+			WCHAR pbuffer[2] = {0};
+			MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pText + i, 2, pbuffer, 1);
+			UNICODE2UTF8(pbuffer, buf, 4);
+			pOut.append(buf);
+			i += 2;
+		}
+	}
+
+	return;
+}
+
+/************************************************************************/
+/*  函数:[7/26/2016 IT];
+/*  描述:将字符串编码成为GB2312格式的URL;;
+/*  参数:;
+/*  	[IN] :;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+string CharEncoding::EnCode_GB2312URL(IN CHAR* pText)
+{
+	string dd;
+	size_t len = strlen(pText);
+	for (size_t i = 0; i < len; i++)
+	{
+		if (isalnum((BYTE)pText[i]))
+		{
+			char tempbuff[2];
+			sprintf_s(tempbuff, "%c", pText[i]);
+			dd.append(tempbuff);
+		}
+		else if (isspace((BYTE)pText[i]))
+		{
+			dd.append("+");
+		}
+		else
+		{
+			char tempbuff[4];
+			sprintf_s(tempbuff, "%%%X%X", ((BYTE*)pText)[i] >> 4, ((BYTE*)pText)[i] % 16);
+			dd.append(tempbuff);
+		}
+	}
+	return dd;
+}
+
+void CharEncoding::EnCode_GB2312URL(IN CHAR* pText, OUT string& strResult)
+{
+	size_t len = strlen(pText);
+	for (size_t i = 0; i < len; i++)
+	{
+		if (isalnum((BYTE)pText[i]))
+		{
+			char tempbuff[2];
+			sprintf_s(tempbuff, "%c", pText[i]);
+			strResult.append(tempbuff);
+		}
+		else if (isspace((BYTE)pText[i]))
+		{
+			strResult.append("+");
+		}
+		else
+		{
+			char tempbuff[4];
+			sprintf_s(tempbuff, "%%%X%X", ((BYTE*)pText)[i] >> 4, ((BYTE*)pText)[i] % 16);
+			strResult.append(tempbuff);
+		}
+	}
+}
+
+/************************************************************************/
+/*  函数:[7/26/2016 IT];
+/*  描述:;
+/*  参数:;
+/*  	[IN] :;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+string CharEncoding::EnCode_UTF8URL(IN const CHAR* pText)
+{
+	string tt = "";
+	string dd = "";
+	ASCII2UTF8(pText,tt);
+
+	size_t len = tt.length();
+	for (size_t i = 0; i < len; i++)
+	{
+		if (isalnum((BYTE)tt.at(i)))
+		{
+			char tempbuff[2] = { 0 };
+			sprintf_s(tempbuff, "%c", (BYTE)tt.at(i));
+			dd.append(tempbuff);
+		}
+		else if (isspace((BYTE)tt.at(i)))
+		{
+			dd.append("+");
+		}
+		else
+		{
+			char tempbuff[4];
+			sprintf_s(tempbuff, "%%%X%X", ((BYTE)tt.at(i)) >> 4, ((BYTE)tt.at(i)) % 16);
+			dd.append(tempbuff);
+		}
+	}
+	return dd;
+}
+
+void CharEncoding::EnCode_UTF8URL(IN const CHAR* pText, OUT string& strResult)
+{
+	string tt = "";
+	ASCII2UTF8(pText,tt);
+
+	size_t len = tt.length();
+	for (size_t i = 0; i < len; i++)
+	{
+		if (isalnum((BYTE)tt.at(i)))
+		{
+			char tempbuff[2] = { 0 };
+			sprintf_s(tempbuff, "%c", (BYTE)tt.at(i));
+			strResult.append(tempbuff);
+		}
+		else if (isspace((BYTE)tt.at(i)))
+		{
+			strResult.append("+");
+		}
+		else
+		{
+			char tempbuff[4];
+			sprintf_s(tempbuff, "%%%X%X", ((BYTE)tt.at(i)) >> 4, ((BYTE)tt.at(i)) % 16);
+			strResult.append(tempbuff);
+		}
+	}
+}
+
+string CharEncoding::EnCode_UNICODEURL(IN const CHAR* pText)
+{
+	return "";
+}
+
+/************************************************************************/
+/*  函数:[7/26/2016 IT];
+/*  描述:;
+/*  参数:;
+/*  	[IN] :;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+string CharEncoding::DeCode_URLGB2312(IN const CHAR* pURLText)
+{
+	string output = "";
+	char tmp[2];
+	int i = 0, idx = 0, len = strlen(pURLText);
+
+	while (i < len){
+		if (pURLText[i] == '%')
+		{
+			tmp[0] = pURLText[i + 1];
+			tmp[1] = pURLText[i + 2];
+			output += StrToBin(tmp);
+			i = i + 3;
+		}
+		else if (pURLText[i] == '+')
+		{
+			output += ' ';
+			i++;
+		}
+		else{
+			output += pURLText[i];
+			i++;
+		}
+	}
+
+	return output;
+}
+
+void CharEncoding::DeCode_URLGB2312(IN const CHAR* pURLText, OUT string& strResult)
+{
+	char tmp[2];
+	int i = 0, idx = 0, len = strlen(pURLText);
+
+	while (i < len){
+		if (pURLText[i] == '%')
+		{
+			tmp[0] = pURLText[i + 1];
+			tmp[1] = pURLText[i + 2];
+			strResult += StrToBin(tmp);
+			i = i + 3;
+		}
+		else if (pURLText[i] == '+')
+		{
+			strResult += ' ';
+			i++;
+		}
+		else{
+			strResult += pURLText[i];
+			i++;
+		}
+	}
+}
+
+/************************************************************************/
+/*  函数:[7/26/2016 IT];
+/*  描述:;
+/*  参数:;
+/*  	[IN] :;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+string CharEncoding::DeCode_URLUTF8(IN const CHAR* pURLText)
+{
+	string output = "";
+	string temp = DeCode_URLGB2312(pURLText);
+	UTF82ASCII(temp.c_str(), output);
+	return output;
+}
+
+void CharEncoding::DeCode_URLUTF8(IN const CHAR* pURLText, OUT string& strResult)
+{
+	string temp = DeCode_URLGB2312(pURLText);
+	UTF82ASCII(temp.c_str(), strResult);
+}
+
+/************************************************************************/
+/*  函数:[7/26/2016 IT];
+/*  描述:;
+/*  参数:;
+/*  	[IN] :;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+string CharEncoding::DeCode_URLUNICODE(IN const CHAR* pURLText)
+{
+	string str = pURLText;
+	string strResult = "";
+
+	INT nIndex = 0;
+	string strTemp = "";
+
+	while ( str.find_first_of("\\u") != string::npos )
+	{
+		nIndex = str.find_first_of("\\u");
+		strResult.append(str.substr(0, nIndex));
+		strTemp = str.substr(nIndex + 2, 4);
+		str = str.substr(nIndex + 2 +4);
+		CHAR szReturn[10] = {0};
+
+		union  __UNION_VAR_INT{
+			BYTE   ch[2];   
+			int	   value;   
+		}unionVarInt;
+
+		unionVarInt.ch[0] =  (CharToInt(strTemp.at(2)) << 4) | (CharToInt(strTemp.at(3))  & 0x00FF);
+		unionVarInt.ch[1] =  (CharToInt(strTemp.at(0)) << 4) | (CharToInt(strTemp.at(1))  & 0x00FF);
+
+		WCHAR szWide[2] = {0};
+		szWide[0] = unionVarInt.value;
+		UNICODE2ASCII(szWide,szReturn,10);
+		strResult.append(szReturn);
+	}
+	strResult.append(str);
+
+	return strResult;
+}
+
+void CharEncoding::DeCode_URLUNICODE(IN const CHAR* pURLText, OUT string& strResult)
+{
+	string str = pURLText;
+
+	INT nIndex = 0;
+	string strTemp = "";
+
+	while ( str.find_first_of("\\u") != string::npos )
+	{
+		nIndex = str.find_first_of("\\u");
+		strResult.append(str.substr(0, nIndex));
+		strTemp = str.substr(nIndex + 2, 4);
+		str = str.substr(nIndex + 2 +4);
+		CHAR szReturn[10] = {0};
+
+		union  __UNION_VAR_INT{
+			BYTE   ch[2];   
+			int	   value;   
+		}unionVarInt;
+
+		unionVarInt.ch[0] =  (CharToInt(strTemp.at(2)) << 4) | (CharToInt(strTemp.at(3))  & 0x00FF);
+		unionVarInt.ch[1] =  (CharToInt(strTemp.at(0)) << 4) | (CharToInt(strTemp.at(1))  & 0x00FF);
+
+		WCHAR szWide[2] = {0};
+		szWide[0] = unionVarInt.value;
+		UNICODE2ASCII(szWide,szReturn,10);
+		strResult.append(szReturn);
+	}
+	strResult.append(str);
+}

+ 97 - 0
scbc.tools/scbc.tools/CharEncoding.h

@@ -0,0 +1,97 @@
+/************************************************************************/
+/*  Copyright (C), 2016-2020, [IT], 保留所有权利;
+/*  模 块 名:公共模块,未做性能优化;
+/*  描    述:;
+/*
+/*  版    本:[V];	
+/*  作    者:[IT];
+/*  日    期:[7/26/2016];
+/*
+/*
+/*  注    意:;
+/*
+/*  修改记录:[IT];
+/*  修改日期:;
+/*  修改版本:;
+/*  修改内容:;
+/************************************************************************/
+#ifndef __CHAR_ENCODING__
+#define __CHAR_ENCODING__
+
+#include <string>
+#include <vector>
+using namespace std;
+
+#ifndef _UNICODE
+typedef string TString;
+#else
+typedef wstring TString;
+#endif
+
+#pragma once
+
+
+class  CharEncoding
+{
+public:
+	// 将字符转化为对应的ASCII十进制值;
+	static char CharToInt(char ch);
+	// 将两个字符串转化成十六进制值;
+	static char StrToBin(IN char (&str)[2]);
+	static void GB2312ToUTF_8(string& pOut, const char *pText, int pLen);
+	// 将ASCII字符串转成UNICODE字符串;
+	static WCHAR* ASCII2UNICODE(IN LPCCH lpASCIIStr);
+	static BOOL   ASCII2UNICODE(IN LPCCH lpASCIIStr, OUT PWCH pUNICODEStr, IN CONST INT& nUNICODEStrLen);
+	static BOOL   ASCII2UNICODE(IN LPCCH lpASCIIStr, OUT wstring &strResult);
+
+	// 将UNICODE字符串转成ASCII字符串;
+	static CHAR* UNICODE2ASCII(IN LPWCH lpUNICODEStr);
+	static BOOL  UNICODE2ASCII(IN LPWCH lpUNICODEStr, OUT LPCH pASCIIStr, IN CONST INT& nASCIIStrLen);
+	static BOOL  UNICODE2ASCII(IN LPWCH lpUNICODEStr, OUT string &strResult);
+
+	// 将UNICODE字符串转成UFT8字符串;
+	static CHAR* UNICODE2UTF8(IN LPWCH lpUNICODEStr);
+	static BOOL  UNICODE2UTF8(IN LPWCH lpUNICODEStr, OUT LPCH pUTF8Str, IN CONST INT& nUTF8StrLen);
+	static BOOL  UNICODE2UTF8(IN LPWCH lpUNICODEStr, OUT string &strResult);
+
+	// 将ASCII字符串转成UTF8字符串;
+	static CHAR* ASCII2UTF8(IN LPCCH lpASCIIStr);
+	static BOOL  ASCII2UTF8(IN LPCCH lpASCIIStr, OUT LPCH pUTF8Str, IN CONST INT& nUTF8StrLen);
+	static BOOL  ASCII2UTF8(IN LPCCH lpASCIIStr, OUT string &strResult);
+
+	// 将UTF-8字符串转成UNICODE字符串;
+	static WCHAR* UTF82UNICODE(IN LPCCH lpUTF8);
+	static BOOL   UTF82UNICODE(IN LPCCH lpUTF8, OUT PWCH pUNICODEStr, IN CONST INT& nUNICODEStrLen);
+	static BOOL   UTF82UNICODE(IN LPCCH lpUTF8, OUT wstring &strResult);
+
+	// 将UTF-8字符串转成ASCII字符串;
+	static CHAR*  UTF82ASCII(IN LPCCH lpUTF8);
+	static BOOL   UTF82ASCII(IN LPCCH lpUTF8, OUT LPCH pASCIIStr, IN CONST INT& nASCIIStrLen);
+	static BOOL   UTF82ASCII(IN LPCCH lpUTF8, OUT string &strResult);
+
+	// 将UTF-8编码成GB2312;
+	static string UTF8IntoGB2313(IN CHAR* pUTF8Text, IN const INT& nUTF8TextLen);
+	// 将GB2312编码成UTF-8;
+	static string GB2312IntoUTF8(IN CHAR* pGB2312Text, IN const INT& nGB2312TextLen);
+
+	// 将字符串编码成为GB2312编码格式的URL;
+	static string EnCode_GB2312URL(IN CHAR* pText);
+	static void EnCode_GB2312URL(IN CHAR* pText, OUT string& strResult);
+	// 将字符串编码成为UTF-8编码格式的URL;
+	static string EnCode_UTF8URL(IN const CHAR* pText);
+	static void EnCode_UTF8URL(IN const CHAR* pText, OUT string& strResult);
+	// 将字符串编码成为UNICODE编码格式的URL;
+	static string EnCode_UNICODEURL(IN const CHAR* pText);	// 未完成该函数;
+
+	// 解码UTF-8编码格式的URL;
+	static string DeCode_URLUTF8(IN const CHAR* pURLText);
+	static void DeCode_URLUTF8(IN const CHAR* pURLText, OUT string& strResult);
+	// 解码GB2312编码格式的URL;
+	static string DeCode_URLGB2312(IN const CHAR* pURLText);
+	static void DeCode_URLGB2312(IN const CHAR* pURLText, OUT string& strResult);
+	// 解码UNICODE编码格式的URL;
+	static string DeCode_URLUNICODE(IN const CHAR* pURLText);
+	static void DeCode_URLUNICODE(IN const CHAR* pURLText, OUT string& strResult);
+};
+
+#endif

+ 84 - 0
scbc.tools/scbc.tools/CritSection.h

@@ -0,0 +1,84 @@
+#ifndef __CRITSECTION_20160221__
+#define __CRITSECTION_20160221__
+
+// ÁÙ½çÖµ;
+class ThreadSection
+{
+public:
+	ThreadSection(){
+		HRESULT hr = Init();
+		(hr);
+	}
+
+	~ThreadSection(){
+		DeleteCriticalSection(&_CriticalSection);
+	}
+
+	bool Lock()
+	{
+		bool result = false;
+		__try
+		{
+			EnterCriticalSection(&_CriticalSection);
+			result = true;
+		}
+		__except (STATUS_NO_MEMORY == GetExceptionCode())
+		{
+		}
+		return result;
+	}
+
+	bool Unlock()
+	{
+		bool result = false;
+		__try
+		{
+			LeaveCriticalSection(&_CriticalSection);
+			result = true;
+		}
+		__except (STATUS_NO_MEMORY == GetExceptionCode())
+		{
+		}
+		return result;
+	}
+
+private:
+	HRESULT Init() throw()
+	{
+		HRESULT hRes = E_FAIL;
+		__try
+		{
+			InitializeCriticalSection(&_CriticalSection);
+			hRes = S_OK;
+		}
+		__except (STATUS_NO_MEMORY == GetExceptionCode())
+		{
+			hRes = E_OUTOFMEMORY;
+		}
+		return hRes;
+	}
+
+	ThreadSection(const ThreadSection & tSection);
+	ThreadSection &operator=(const ThreadSection & tSection);
+	CRITICAL_SECTION _CriticalSection;
+};
+
+
+class AutoThreadSection
+{
+public:
+	AutoThreadSection(IN ThreadSection* pSection){
+		_pSection = pSection;
+		_pSection->Lock();
+	}
+
+	~AutoThreadSection(){
+		_pSection->Unlock();
+	}
+private:
+	AutoThreadSection(const AutoThreadSection & tSection);
+	AutoThreadSection &operator=(const AutoThreadSection & tSection);
+	ThreadSection * _pSection;
+};
+
+#endif //__CRITSECTION_20160221__

+ 663 - 0
scbc.tools/scbc.tools/CurlClient.cpp

@@ -0,0 +1,663 @@
+#include "stdafx.h"
+#include "CurlClient.h"
+#include "CharEncoding.h"
+#include <sys/stat.h>
+
+CCurlClient::CCurlClient(void)
+{
+	m_bDebug = FALSE;
+	m_headers = NULL;
+}
+
+CCurlClient::~CCurlClient(void)
+{
+	// 释放curl的全局对象;
+	curl_global_cleanup(); 
+}
+
+INT CCurlClient::Initialize()
+{
+	// 初始化全局调用模式;
+	CURLcode res = ::curl_global_init( CURL_GLOBAL_ALL );
+	if( CURLE_OK != res ) 
+	{
+		fprintf( stderr, "curl_global_init failed: %d \n", res ); 
+		return -1;
+	}
+
+	return 0;
+}
+
+static int OnDebug(CURL *, curl_infotype itype, char * pData, size_t size, void *)   
+{   
+	if(itype == CURLINFO_TEXT)   
+	{   
+		//TRACE("[TEXT]%s\n", pData); 
+		LOG4C((LOG_WARN, "[TEXT]%s\n", pData));   
+	}   
+	else if(itype == CURLINFO_HEADER_IN)   
+	{   
+		//TRACE("[HEADER_IN]%s\n", pData); 
+		LOG4C((LOG_WARN, "[HEADER_IN]%s\n", pData));
+	}   
+	else if(itype == CURLINFO_HEADER_OUT)   
+	{   
+		//TRACE("[HEADER_OUT]%s\n", pData);   
+		LOG4C((LOG_WARN, "[HEADER_OUT]%s\n", pData));
+	}   
+	else if(itype == CURLINFO_DATA_IN)   
+	{   
+		//TRACE("[DATA_IN]%s\n", pData);   
+		LOG4C((LOG_WARN, "[DATA_IN]%s\n", pData));
+	}   
+	else if(itype == CURLINFO_DATA_OUT)   
+	{   
+		//TRACE("[DATA_OUT]%s\n", pData);   
+		LOG4C((LOG_WARN, "[DATA_OUT]%s\n", pData));
+	}   
+	return 0;   
+}   
+
+size_t CCurlClient::OnWriteData(const void *ptr, size_t size, size_t nmemb, std::string *stream)   
+{   
+	if( NULL == stream || NULL == ptr )
+		return -1;
+
+	stream->append((char*)ptr, size * nmemb);   
+	return nmemb;   
+}  
+
+size_t CCurlClient::OnWriteFile(const void *ptr, size_t size, size_t nmemb, void *stream)   
+{   
+	if( NULL == stream || NULL == ptr )
+		return -1;
+
+	return fwrite(ptr, size, nmemb, (FILE*)stream);  
+}
+
+size_t CCurlClient::OnGetContentLength(void *ptr, size_t size, size_t nmemb, void *stream)
+{
+	int r;
+	long len = 0;
+
+	/* _snscanf() is Win32 specific */
+	// r = _snscanf(ptr, size * nmemb, "Content-Length: %ld\n", &len);
+	r = sscanf_s((char*)ptr, "Content-Length: %ld\n", &len);
+	if (r) /* Microsoft: we don't read the specs */
+		*((long *) stream) = len;
+
+	return size * nmemb;
+}
+
+int CCurlClient::Post(const std::string & strUrl, const std::string & strPost, std::string & strResponse, long time_out /*= 3*/)
+{   
+	CURLcode res;   
+	CURL* curl = curl_easy_init();   
+	if(NULL == curl)   
+	{   
+		return CURLE_FAILED_INIT;   
+	}   
+	if(m_bDebug)   
+	{// 是否开启调试日志输出;   
+		curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);   
+		curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);   
+	}   
+	// 设置URL地址;
+	curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());   
+	// 设置POST方式;
+	curl_easy_setopt(curl, CURLOPT_POST, 1);   
+	// 设置POST参数;
+	curl_easy_setopt(curl, CURLOPT_POSTFIELDS, strPost.c_str());  
+    // 设置回调函数-读取;	
+	curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);   
+	// 设置回调函数-写入;
+	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);   
+	// 设置回调函数-写入的缓存区;
+	curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);   
+	// 设置(多线程下,只是尽量减少)无签名;
+	curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);   
+	// 设置连接超时值(单位毫秒);
+	curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30000); 
+	// 设置操作超时值(单位毫秒);
+	curl_easy_setopt(curl, CURLOPT_TIMEOUT, time_out);
+	// 设置头;
+	curl_easy_setopt(curl, CURLOPT_HTTPHEADER, m_headers);
+
+	// 执行POST提交;
+	res = curl_easy_perform(curl);   
+	
+	// 释放资源;
+	curl_easy_cleanup(curl); 
+	//curl_global_cleanup();
+	ClearHeaders(); /* free the header list */
+
+	return res;   
+}  
+
+int CCurlClient::Post(IN LPCTSTR lpUrl, IN LPCTSTR lpPost, OUT LPTSTR lpResponse, IN CONST INT& nMaxlen, long time_out /*= 3*/)
+{
+	if ( lpUrl == NULL || lpPost == NULL )
+		return CURLE_FAILED_INIT;
+
+	string strUrl;
+	string strPost;
+	string strResponse;
+#ifdef UNICODE
+	CharEncoding::UNICODE2ASCII((LPWCH)lpUrl, strUrl);
+	CharEncoding::UNICODE2ASCII((LPWCH)lpPost, strPost);
+
+	int res = Post(strUrl, strPost, strResponse) ;
+	if ( CURLE_OK == res )
+	{
+		CharEncoding::ASCII2UNICODE(strResponse.c_str(), (LPWCH)lpResponse, nMaxlen);
+		return CURLE_OK;
+	}
+
+	return res;
+#else
+	strUrl = lpUrl;
+	strPost = lpPost;
+	int res = Post(strUrl, strPost, strResponse, time_out) ;
+	if ( CURLE_OK == res )
+	{
+		sprintf_s(lpResponse, nMaxlen, "%s", strResponse.c_str());
+		return CURLE_OK;
+	}
+	return res;
+#endif
+}
+
+int CCurlClient::Post(IN CString& strUrl, IN CString& strPost, OUT CString& strResponse, long time_out /*= 3*/)
+{
+	if ( strUrl.IsEmpty() || strPost.IsEmpty() )
+		return CURLE_FAILED_INIT;
+
+	string url;
+	string post;
+	string response;
+#ifdef UNICODE
+	CharEncoding::UNICODE2ASCII((LPWCH)strUrl.GetString(), url);
+	CharEncoding::UNICODE2ASCII((LPWCH)strPost.GetString(), post);
+
+	int res = Post(url, post, response) ;
+	if ( CURLE_OK == res )
+	{
+		WCHAR* pResult = CharEncoding::ASCII2UNICODE(response.c_str());
+		if ( pResult )
+		{
+			strResponse = pResult;
+			delete []pResult;
+			pResult = NULL;
+			return CURLE_OK;
+		}
+	}
+
+	return res;
+#else
+	url = strUrl.GetString();
+	post = strPost.GetString();
+	int res = Post(url, post, response, time_out) ;
+	if ( CURLE_OK == res )
+	{
+		strResponse = response.c_str();
+		return CURLE_OK;
+	}
+	return res;
+#endif
+}
+
+int CCurlClient::Get(const std::string & strUrl, std::string & strResponse, long time_out /*= 3*/)
+{   
+	CURLcode res;   
+	CURL* curl = curl_easy_init();   
+	if(NULL == curl)   
+	{   
+		return CURLE_FAILED_INIT;   
+	}   
+	if(m_bDebug)   
+	{   
+		curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);   
+		curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);   
+	}   
+
+	// 设置URL地址;
+	curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());   
+	// 设置回调函数-读取;
+	curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);   
+	// 设置回调函数-写入;
+	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);   
+	// 设置回调函数-写入的缓存区;
+	curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);   
+	/**  
+	* 当多个线程都使用超时处理的时候,同时主线程中有sleep或是wait等操作。  
+	* 如果不设置这个选项,libcurl将会发信号打断这个wait从而导致程序退出。  
+	*/  
+	// 设置(多线程下,只是尽量减少)无签名;	
+	curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);   
+	// 设置连接超时值;
+	curl_easy_setopt(curl,CURLOPT_CONNECTTIMEOUT,5000);
+	// 设置超时值;
+	curl_easy_setopt(curl,CURLOPT_TIMEOUT, time_out);
+	// 设置头;
+	curl_easy_setopt(curl, CURLOPT_HTTPHEADER, m_headers);
+
+	res = curl_easy_perform(curl);   
+	curl_easy_cleanup(curl);
+	//curl_global_cleanup();
+	ClearHeaders(); /* free the header list */
+
+	return res;   
+}  
+
+int CCurlClient::Get(IN LPCTSTR lpUrl, OUT LPTSTR lpResponse, IN CONST INT& nMaxlen, long time_out /*= 3*/)
+{
+	if ( lpUrl == NULL )
+		return CURLE_FAILED_INIT;
+
+	string strUrl;
+	string strResponse;
+#ifdef UNICODE
+	CharEncoding::UNICODE2ASCII((LPWCH)lpUrl, strUrl);
+
+	int res = Get(strUrl, strResponse) ;
+	if ( CURLE_OK == res )
+	{
+		CharEncoding::ASCII2UNICODE(strResponse.c_str(), (LPWCH)lpResponse, nMaxlen);
+		return CURLE_OK;
+	}
+
+	return res;
+#else
+	strUrl = lpUrl;
+	int res = Get(strUrl, strResponse, time_out) ;
+	if ( CURLE_OK == res )
+	{
+		sprintf_s(lpResponse, nMaxlen, "%s", strResponse.c_str());
+		return CURLE_OK;
+	}
+	return res;
+#endif
+}
+
+int CCurlClient::Get(IN CString& strUrl, OUT CString& strResponse, long time_out /*= 3*/)
+{
+	if ( strUrl.IsEmpty() )
+		return CURLE_FAILED_INIT;
+
+	string url;
+	string post;
+	string response;
+#ifdef UNICODE
+	CharEncoding::UNICODE2ASCII((LPWCH)strUrl.GetString(), url);
+
+	int res = Get(url, response) ;
+	if ( CURLE_OK == res )
+	{
+		WCHAR* pResult = CharEncoding::ASCII2UNICODE(response.c_str());
+		if ( pResult )
+		{
+			strResponse = pResult;
+			delete []pResult;
+			pResult = NULL;
+			return CURLE_OK;
+		}
+	}
+
+	return res;
+#else
+	url = strUrl.GetString();
+	int res = Get(url, response, time_out) ;
+	if ( CURLE_OK == res )
+	{
+		strResponse = response.c_str();
+		return CURLE_OK;
+	}
+	return res;
+#endif
+}
+
+int CCurlClient::Posts(const std::string & strUrl, const std::string & strPost, std::string & strResponse, const char * pCaPath, long time_out /*= 3*/)
+{   
+	CURLcode res;   
+	CURL* curl = curl_easy_init();   
+	if(NULL == curl)   
+	{   
+		return CURLE_FAILED_INIT;   
+	}   
+	if(m_bDebug)   
+	{   
+		curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);   
+		curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);   
+	}   
+	
+	// 设置URL地址;
+	curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());   
+	// 设置POST提交方式;
+	curl_easy_setopt(curl, CURLOPT_POST, 1);   
+	// 设置POST参数;
+	curl_easy_setopt(curl, CURLOPT_POSTFIELDS, strPost.c_str());   
+	// 设置回调函数-读取;
+	curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);   
+	// 设置回调函数-写入;
+	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);   
+	// 设置回调函数-写入的缓存区;
+	curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);   
+	// 设置;
+	curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);   
+	if(NULL == pCaPath || pCaPath[0] == '\0')   
+	{   
+		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);   
+		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);   
+	}   
+	else   
+	{   
+		//缺省情况就是PEM,所以无需设置,另外支持DER   
+		//curl_easy_setopt(curl,CURLOPT_SSLCERTTYPE,"PEM");   
+		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, true);   
+		curl_easy_setopt(curl, CURLOPT_CAINFO, pCaPath);   
+	}   
+	// 设置连接超时值;
+	curl_easy_setopt(curl,CURLOPT_CONNECTTIMEOUT,5000);
+	// 设置超时值;
+	curl_easy_setopt(curl,CURLOPT_TIMEOUT, time_out);
+	// 设置头;
+	curl_easy_setopt(curl, CURLOPT_HTTPHEADER, m_headers);
+	
+	// 执行POST提交;
+	res = curl_easy_perform(curl);   
+	
+	// 释放资源;
+	curl_easy_cleanup(curl); 
+	//curl_global_cleanup();
+	ClearHeaders(); /* free the header list */
+
+	return res;   
+}  
+
+int CCurlClient::Posts(IN LPCTSTR lpUrl, IN LPCTSTR lpPost, OUT LPTSTR lpResponse, IN CONST INT& nMaxlen, IN LPCTSTR lpCaPath /* = NULL */, long time_out /*= 3*/)
+{
+	if ( lpUrl == NULL || lpPost == NULL )
+		return CURLE_FAILED_INIT;
+
+	string strUrl;
+	string strPost;
+	string strCapath;
+	string strResponse;
+#ifdef UNICODE
+	CharEncoding::UNICODE2ASCII((LPWCH)lpUrl, strUrl);
+	CharEncoding::UNICODE2ASCII((LPWCH)lpPost, strPost);
+	CharEncoding::UNICODE2ASCII((LPWCH)lpCaPath, strCapath);
+
+	int res = Posts(strUrl, strPost, strResponse, strCapath.c_str()) ;
+	if ( CURLE_OK == res )
+	{
+		CharEncoding::ASCII2UNICODE(strResponse.c_str(), (LPWCH)lpResponse, nMaxlen);
+		return CURLE_OK;
+	}
+
+	return res;
+#else
+	strUrl = lpUrl;
+	strPost = lpPost;
+	strCapath = lpCaPath;
+	int res = Posts(strUrl, strPost, strResponse, strCapath.c_str(), time_out ) ;
+	if ( CURLE_OK == res )
+	{
+		sprintf_s(lpResponse, nMaxlen, "%s", strResponse.c_str());
+		return CURLE_OK;
+	}
+	return res;
+#endif
+}
+
+int CCurlClient::Posts(IN CString& strUrl, IN CString& strPost, OUT CString& strResponse, IN const CString& strCaPath /* = _T("") */, long time_out /*= 3*/)
+{
+	if ( strUrl.IsEmpty() || strPost.IsEmpty() )
+		return CURLE_FAILED_INIT;
+
+	string url;
+	string post;
+	string capth;
+	string response;
+#ifdef UNICODE
+	CharEncoding::UNICODE2ASCII((LPWCH)strUrl.GetString(), url);
+	CharEncoding::UNICODE2ASCII((LPWCH)strPost.GetString(), post);
+	CharEncoding::UNICODE2ASCII((LPWCH)strCaPath.GetString(), capth);
+
+	int res = Posts(url, post, response, capth.c_str()) ;
+	if ( CURLE_OK == res )
+	{
+		WCHAR* pResult = CharEncoding::ASCII2UNICODE(response.c_str());
+		if ( pResult )
+		{
+			strResponse = pResult;
+			delete []pResult;
+			pResult = NULL;
+			return CURLE_OK;
+		}
+	}
+
+	return res;
+#else
+	url = strUrl.GetString();
+	post = strPost.GetString();
+	capth = strCaPath.GetString();
+	int res = Posts(url, post, response, capth.c_str(), time_out) ;
+	if ( CURLE_OK == res )
+	{
+		strResponse = response.c_str();
+		return CURLE_OK;
+	}
+	return res;
+#endif
+}
+
+int CCurlClient::Gets(const std::string & strUrl, std::string & strResponse, const char * pCaPath, long time_out /*= 3*/)
+{   
+	CURLcode res;   
+	CURL* curl = curl_easy_init();   
+	if(NULL == curl)   
+	{   
+		return CURLE_FAILED_INIT;   
+	}   
+	if(m_bDebug)   
+	{   
+		curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);   
+		curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);   
+	}   
+	curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());   
+	curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);   
+	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);   
+	curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);   
+	curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);   
+	if(NULL == pCaPath || pCaPath[0] == '\0')   
+	{   
+		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);   
+		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);   
+	}   
+	else   
+	{   
+		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, true);   
+		curl_easy_setopt(curl, CURLOPT_CAINFO, pCaPath);   
+	}   
+	curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 5000);   
+	curl_easy_setopt(curl, CURLOPT_TIMEOUT, time_out);
+	// 设置头;
+	curl_easy_setopt(curl, CURLOPT_HTTPHEADER, m_headers);
+
+	res = curl_easy_perform(curl);   
+	curl_easy_cleanup(curl); 
+	//curl_global_cleanup();
+	ClearHeaders(); /* free the header list */
+
+	return res;   
+} 
+
+int CCurlClient::Gets(IN LPCTSTR lpUrl, OUT LPTSTR lpResponse, IN CONST INT& nMaxlen, IN LPCTSTR lpCaPath /* = NULL */, long time_out /*= 3*/)
+{
+	if ( lpUrl == NULL )
+		return CURLE_FAILED_INIT;
+
+	string strUrl;
+	string strCapath;
+	string strResponse;
+#ifdef UNICODE
+	CharEncoding::UNICODE2ASCII((LPWCH)lpUrl, strUrl);
+	CharEncoding::UNICODE2ASCII((LPWCH)lpCaPath, strCapath);
+
+	int res = Gets(strUrl, strResponse, strCapath.c_str()) ;
+	if ( CURLE_OK == res )
+	{
+		CharEncoding::ASCII2UNICODE(strResponse.c_str(), (LPWCH)lpResponse, nMaxlen);
+		return CURLE_OK;
+	}
+
+	return res;
+#else
+	strUrl = lpUrl;
+	strCapath = lpCaPath;
+	int res = Gets(strUrl, strResponse, strCapath.c_str(), time_out) ;
+	if ( CURLE_OK == res )
+	{
+		sprintf_s(lpResponse, nMaxlen, "%s", strResponse.c_str());
+		return CURLE_OK;
+	}
+	return res;
+#endif
+}
+
+int CCurlClient::Gets(IN CString& strUrl, OUT CString& strResponse, IN const CString& strCaPath /* = _T("") */, long time_out /*= 3*/)
+{
+	if ( strUrl.IsEmpty() )
+		return CURLE_FAILED_INIT;
+
+	string url;
+	string post;
+	string capth;
+	string response;
+#ifdef UNICODE
+	CharEncoding::UNICODE2ASCII((LPWCH)strUrl.GetString(), url);
+	CharEncoding::UNICODE2ASCII((LPWCH)strCaPath.GetString(), capth);
+
+	int res = Gets(url, response, capth.c_str()) ;
+	if ( CURLE_OK == res )
+	{
+		WCHAR* pResult = CharEncoding::ASCII2UNICODE(response.c_str());
+		if ( pResult )
+		{
+			strResponse = pResult;
+			delete []pResult;
+			pResult = NULL;
+			return CURLE_OK;
+		}
+	}
+
+	return res;
+#else
+	url = strUrl.GetString();
+	capth = strCaPath.GetString();
+	int res = Gets(url, response, capth.c_str(), time_out) ;
+	if ( CURLE_OK == res )
+	{
+		strResponse = response.c_str();
+		return CURLE_OK;
+	}
+	return res;
+#endif
+}
+
+bool CCurlClient::Download(const std::string &url, const std::string &path, long time_out /* = 3000 */)
+{
+	int nStatus = 0;
+	std::string data;
+	int npos = url.find("https://");
+	if ( npos == std::string::npos)
+		nStatus = Get(url, data, time_out);
+	else
+		nStatus = Gets(url, data, NULL, time_out);
+
+	if ( nStatus != CURLE_OK)
+		return false;
+
+	if ( data.size() )
+	{
+		FILE *pf = NULL;
+		_tfopen_s(&pf, path.c_str(), "wb");
+		if ( pf )
+		{
+			fwrite(data.c_str(), data.size(), 1, pf);
+			fclose(pf);
+			return true;
+		}
+	}
+
+	return false;
+}
+
+bool CCurlClient::DownloadEx(const std::string &url, const std::string &path, long time_out /* = 3000 */)
+{
+	FILE *pf = NULL;
+	curl_off_t local_file_len = -1;
+	long file_size = 0;
+
+	CURLcode res = CURLE_GOT_NOTHING;
+	int c = 0;
+	struct stat file_info;
+	int use_resume = 0;
+
+	// 获取本地文件大小;
+	if (stat(path.c_str(), &file_info) == 0 )
+	{
+		local_file_len = file_info.st_size;
+		use_resume = 1;
+	}
+
+	// 采用追加方式打开文件,便于实现断点续传;
+	int nErr = _tfopen_s(&pf, path.c_str(), "ab+");
+	if ( pf )
+	{
+		CURL* curl = curl_easy_init();   
+		if(NULL == curl)   
+		{   
+			//return CURLE_FAILED_INIT;   
+			return false;
+		}   
+		curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
+		curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, time_out);
+		// 设置http头部处理函数;
+		curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, OnGetContentLength);
+		curl_easy_setopt(curl, CURLOPT_HEADERDATA, &file_size);
+		if ( url.find("https://") != std::string::npos )
+		{
+			curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);   
+			curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);   
+		}
+		// 设置文件续传的位置给curl;
+		curl_easy_setopt(curl, CURLOPT_RESUME_FROM_LARGE, use_resume ? local_file_len : 0);
+		curl_easy_setopt(curl, CURLOPT_WRITEDATA, pf); 
+		//curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);//设置重定位URL,使用自动跳转,返回的头部中有Location(一般直接请求的url没找到),则继续请求Location对应的数据
+		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteFile);
+		curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L);
+		curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
+
+		res = curl_easy_perform(curl);
+		fclose(pf);
+		curl_easy_cleanup(curl); 
+
+		if ( res == CURLE_OK )
+			return true;
+	}
+
+	return false;
+}
+
+
+void CCurlClient::SetDebug(bool bDebug)   
+{   
+	m_bDebug = bDebug;   
+}   
+
+void CCurlClient::SetHeaders(const std::string headers)
+{
+	m_headers = curl_slist_append(m_headers, headers.c_str());
+}

+ 92 - 0
scbc.tools/scbc.tools/CurlClient.h

@@ -0,0 +1,92 @@
+#ifndef __CURLCLIENT__
+#define __CURLCLIENT__
+
+#include <string>
+#include <vector>
+using namespace std;
+#include "curl/curl.h"
+#include "curl/easy.h"
+#include "curl/curlver.h"
+
+#ifndef _UNICODE
+typedef string TString;
+#else
+typedef wstring TString;
+#endif
+
+#pragma once
+
+class  CCurlClient
+{
+public:
+	CCurlClient(void);
+	~CCurlClient(void);
+
+public:
+	INT Initialize();
+	/**  
+	* @brief HTTP POST请求  
+	* @param strUrl 输入参数,请求的Url地址,如:http://www.baidu.com  
+	* @param strPost 输入参数,使用如下格式para1=val1?2=val2&…  
+	* @param strResponse 输出参数,返回的内容  
+	* @return 返回是否Post成功  
+	*/   
+	int Post(const std::string & strUrl, const std::string & strPost, std::string & strResponse, long time_out = 3000);
+	int Post(IN LPCTSTR lpUrl, IN LPCTSTR lpPost, OUT LPTSTR lpResponse, IN CONST INT& nMaxlen, long time_out = 3000);
+	int Post(IN CString& strUrl, IN CString& strPost, OUT CString& strResponse, long time_out = 3000);
+
+	/**  
+	* @brief HTTP GET请求  
+	* @param strUrl 输入参数,请求的Url地址,如:http://www.baidu.com  
+	* @param strResponse 输出参数,返回的内容  
+	* @return 返回是否Post成功  
+	*/   
+	int Get(const std::string & strUrl, std::string & strResponse, long time_out = 3000);
+	int Get(IN LPCTSTR lpUrl, OUT LPTSTR lpResponse, IN CONST INT& nMaxlen, long time_out = 3000);
+	int Get(IN CString& strUrl, OUT CString& strResponse, long time_out = 3000);
+
+	/**  
+	* @brief HTTPS POST请求,无证书版本  
+	* @param strUrl 输入参数,请求的Url地址,如:https://www.alipay.com  
+	* @param strPost 输入参数,使用如下格式para1=val1?2=val2&…  
+	* @param strResponse 输出参数,返回的内容  
+	* @param pCaPath 输入参数,为CA证书的路径.如果输入为NULL,则不验证服务器端证书的有效性.  
+	* @return 返回是否Post成功  
+	*/   
+	int Posts(const std::string & strUrl, const std::string & strPost, std::string & strResponse, const char * pCaPath = NULL, long time_out = 3000);
+	int Posts(IN LPCTSTR lpUrl, IN LPCTSTR lpPost, OUT LPTSTR lpResponse, IN CONST INT& nMaxlen, IN LPCTSTR lpCaPath = NULL, long time_out = 3000);
+	int Posts(IN CString& strUrl, IN CString& strPost, OUT CString& strResponse, IN const CString& strCaPath = _T(""), long time_out = 3000);
+
+	/**  
+	* @brief HTTPS GET请求,无证书版本  
+	* @param strUrl 输入参数,请求的Url地址,如:https://www.alipay.com  
+	* @param strResponse 输出参数,返回的内容  
+	* @param pCaPath 输入参数,为CA证书的路径.如果输入为NULL,则不验证服务器端证书的有效性.  
+	* @return 返回是否Post成功  
+	*/   
+	int Gets(const std::string & strUrl, std::string & strResponse, const char * pCaPath = NULL, long time_out = 3000);
+	int Gets(IN LPCTSTR lpUrl, OUT LPTSTR lpResponse, IN CONST INT& nMaxlen, IN LPCTSTR lpCaPath = NULL, long time_out = 3000);
+	int Gets(IN CString& strUrl, OUT CString& strResponse, IN const CString& strCaPath = _T(""), long time_out = 3000);
+
+	bool Download(const std::string &url, const std::string &path, long time_out = 3000);
+	bool DownloadEx(const std::string &url, const std::string &path, long time_out = 3000);
+public:   
+	void SetDebug(bool bDebug); 
+	void SetHeaders(const std::string headers);
+	void ClearHeaders()
+	{
+		curl_slist_free_all(m_headers);
+		m_headers = NULL;
+	}
+
+
+private:   
+	// 是否启用调试输出;
+	BOOL	m_bDebug;	
+	struct curl_slist *m_headers;
+	static size_t OnWriteData(const void *ptr, size_t size, size_t nmemb, std::string *stream);
+	static size_t OnWriteFile(const void *ptr, size_t size, size_t nmemb, void *stream);
+	static size_t OnGetContentLength(void *ptr, size_t size, size_t nmemb, void *stream);
+};
+
+#endif

+ 836 - 0
scbc.tools/scbc.tools/Global.cpp

@@ -0,0 +1,836 @@
+#include "stdafx.h"
+#include "Global.h"
+#include <SetupAPI.h>
+#include <InitGuid.h>
+#include <WinIoCtl.h>
+#pragma comment(lib, "SetupAPI.lib")
+
+namespace Global
+{
+	//////////////////////////////////////////////////////////////////////////
+	// 全局变量;
+	BOOL g_bTestHost = FALSE;
+	TCHAR g_szCurModuleDir[MAX_PATH] = { 0 };
+	TCHAR g_szCurModulePath[MAX_PATH] = { 0 };
+	TCHAR g_szFna[MAX_PATH] = { 0 };
+	TCHAR g_szConfig[MAX_PATH] = { 0 };
+	std::string g_strMacs;
+	std::vector<MacAddress> g_vtMac;
+	TConfig g_tConfig;
+	Global::TChassis g_AutoOnlineChassis;
+
+	// usb;
+	static GUID UsbClassGuid = { 0xA5DCBF10L, 0x6530, 0x11D2, {0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED} };
+	// mac;
+	static GUID MacClassGuid = { 0xAD498944, 0x762F, 0x11D0, {0x8D, 0xCB, 0x00, 0xC0, 0x4F, 0xC3, 0x35, 0x8C} };
+	// hdd;
+	static GUID HDDClassGuid = { 0x53F56307, 0xB6BF, 0x11D0, {0x94, 0xF2, 0x00, 0xA0, 0xC9, 0x1E, 0xFB, 0x8B} };
+
+	//////////////////////////////////////////////////////////////////////////
+	// 全局函数;
+	/************************************************************************/
+	/*  函数:WriteTextLog[7/28/2009 Jeff];
+			/*  描述:写文本日志;
+			/*  参数:;
+			/*  	[IN] :;
+			/*  返回:void;
+			/*  注意:;
+			/*  示例:;
+			/*
+			/*  修改:;
+			/*  日期:;
+			/*  内容:;
+			/************************************************************************/
+	void WriteTextLog(const TCHAR* format, ...)
+	{
+		// 将日志内容输入到文件中;
+		// 获取今年年份;
+		__time64_t gmt = time(NULL); // 获取当前日历时间(1900-01-01开始的Unix时间戳);
+		struct tm gmtm = { 0 };
+		localtime_s(&gmtm, &gmt); // 时间戳转成本地时间;
+
+		// 解析出日志路径;
+		TCHAR szlogpath[MAX_PATH] = { 0 };
+		_stprintf_s(szlogpath, _T("%slog\\Serial Port Log %02d%02d.txt"), g_szCurModuleDir, gmtm.tm_mon + 1, gmtm.tm_mday);
+		// 打开或创建文件;
+		FILE* fp = NULL;
+		//if (_taccess(szlogpath, 0) != -1)
+#ifndef UNICODE
+		if (_access(szlogpath, 0) != -1)
+#else
+		if (_taccess(szlogpath, 0) != -1)
+#endif
+		{ // 存在;
+			if (0 == _tfopen_s(&fp, szlogpath, _T("a+")))
+				// 移动到末尾;
+				fseek(fp, 0, SEEK_END);
+		}
+		else
+		{ // 不存在;
+			_tfopen_s(&fp, szlogpath, _T("w+"));
+		}
+
+		if (fp == NULL)
+			return;
+
+		// 格式化前设置语言区域;
+		TCHAR* old_locale = _tcsdup(_tsetlocale(LC_CTYPE, NULL));
+		_tsetlocale(LC_CTYPE, _T("chs")); //设定中文;
+
+		// 格式化日志内容;
+		va_list args = NULL;
+		int len = 0;
+		TCHAR* buffer = NULL;
+		va_start(args, format);
+		// _vscprintf doesn't count. terminating '\0'
+		len = _vsctprintf(format, args) + 1;
+		buffer = (TCHAR*)malloc(len * sizeof(TCHAR));
+		_vstprintf_s(buffer, len, format, args);
+		_ftprintf(fp, _T("%04d-%02d-%02d %02d:%02d:%02d %s\n"), gmtm.tm_year + 1990, gmtm.tm_mon + 1, gmtm.tm_mday, gmtm.tm_hour, gmtm.tm_min, gmtm.tm_sec, buffer);
+
+		// 关闭文件,释放资源并设置回原语言区域;
+		free(buffer);
+		fclose(fp);
+		_tsetlocale(LC_CTYPE, old_locale);
+		free(old_locale); //还原区域设定;
+	}
+
+	// 读取配置文件-预留;
+	void GetConfig()
+	{
+		// 读取文件;
+		FILE* pf = NULL;
+		_tfopen_s(&pf, _T("./Config.json"), _T("rb"));
+		if (!pf)
+			return;
+		// 获取文件长度;
+		fseek(pf, 0, SEEK_END);
+		size_t file_size = ftell(pf);
+		fseek(pf, 0, SEEK_SET);
+		// 读取文件内容;
+		byte* pdata = (byte*)malloc(file_size);
+		fread(pdata, file_size, 1, pf);
+		fclose(pf);
+
+		// Json数据;
+		cJSON* pJson = cJSON_Parse((const char*)pdata);
+		if (pJson == NULL)
+		{
+			goto end;
+		}
+
+		// 获取数据;
+		g_tConfig.com = cJSON_GetObjectItem(pJson, _T("COM")) ? cJSON_GetObjectItem(pJson, _T("COM"))->valuestring : "";
+		g_tConfig.baudrate = cJSON_GetObjectItem(pJson, _T("Baudrate")) ? cJSON_GetObjectItem(pJson, _T("Baudrate"))->valuestring : "115200";
+		g_tConfig.mode = cJSON_GetObjectItem(pJson, _T("Mode")) ? cJSON_GetObjectItem(pJson, _T("Mode"))->valueint : 0;
+		g_tConfig.warncount = cJSON_GetObjectItem(pJson, _T("WarnCount")) ? cJSON_GetObjectItem(pJson, _T("WarnCount"))->valueint : 200;
+		g_tConfig.waitboot = cJSON_GetObjectItem(pJson, _T("WaitBoot")) ? cJSON_GetObjectItem(pJson, _T("WaitBoot"))->valueint : 5000;
+		g_tConfig.serverurl = cJSON_GetObjectItem(pJson, _T("server-url")) ? cJSON_GetObjectItem(pJson, _T("server-url"))->valuestring : "";
+		g_tConfig.chassis = cJSON_GetObjectItem(pJson, _T("Chassis")) ? cJSON_GetObjectItem(pJson, _T("Chassis"))->valuestring : "";
+
+		// 频道;
+		cJSON* pItem = NULL;
+		cJSON* pChannel = cJSON_GetObjectItem(pJson, "Channel");
+		if (pChannel)
+		{
+			int nCount = cJSON_GetArraySize(pChannel);
+			for (int i = 0; i < nCount; i++)
+			{
+				pItem = cJSON_GetArrayItem(pChannel, i);
+				if (pItem && pItem->child)
+				{
+					g_tConfig.channel.insert(pair<std::string, std::string>(pItem->child->string, pItem->child->valuestring));
+				}
+			}
+		}
+		// 语言;
+		cJSON* pLanguage = cJSON_GetObjectItem(pJson, "Language");
+		if (pLanguage)
+		{
+			int nCount = cJSON_GetArraySize(pLanguage);
+			for (int i = 0; i < nCount; i++)
+			{
+				pItem = cJSON_GetArrayItem(pLanguage, i);
+				if (pItem && pItem->child)
+				{
+					g_tConfig.language.insert(pair<std::string, std::string>(pItem->child->string, pItem->child->valuestring));
+				}
+			}
+		}
+		// 文件夹;
+		cJSON* pKeyFolder = cJSON_GetObjectItem(pJson, "KeyFolder");
+		if (pKeyFolder)
+		{
+			int nCount = cJSON_GetArraySize(pKeyFolder);
+			for (int i = 0; i < nCount; i++)
+			{
+				pItem = cJSON_GetArrayItem(pKeyFolder, i);
+				if (pItem && pItem->child)
+				{
+					g_tConfig.keyfolder.insert(pair<std::string, std::string>(pItem->child->string, pItem->child->valuestring));
+				}
+			}
+		}
+		// read check;
+		cJSON *pReadCheck = cJSON_GetObjectItem(pJson, "ReadCheck");
+		if ( pReadCheck )
+		{
+			g_tConfig.readcheck.IsPID = cJSON_GetObjectItem(pReadCheck, _T("PID")) ? cJSON_GetObjectItem(pReadCheck, _T("PID"))->valueint : 1;
+			g_tConfig.readcheck.IsCHANNEL = cJSON_GetObjectItem(pReadCheck, _T("CHANNEL")) ? cJSON_GetObjectItem(pReadCheck, _T("CHANNEL"))->valueint : 1;
+			g_tConfig.readcheck.IsOSD = cJSON_GetObjectItem(pReadCheck, _T("OSD")) ? cJSON_GetObjectItem(pReadCheck, _T("OSD"))->valueint : 1;
+			g_tConfig.readcheck.IsSHOP = cJSON_GetObjectItem(pReadCheck, _T("SHOP")) ? cJSON_GetObjectItem(pReadCheck, _T("SHOP"))->valueint : 1;
+			g_tConfig.readcheck.IsDID = cJSON_GetObjectItem(pReadCheck, _T("DID")) ? cJSON_GetObjectItem(pReadCheck, _T("DID"))->valueint : 1;
+			g_tConfig.readcheck.IsMAC = cJSON_GetObjectItem(pReadCheck, _T("MAC")) ? cJSON_GetObjectItem(pReadCheck, _T("MAC"))->valueint : 1;
+			g_tConfig.readcheck.IsHDCP = cJSON_GetObjectItem(pReadCheck, _T("HDCP")) ? cJSON_GetObjectItem(pReadCheck, _T("HDCP"))->valueint : 1;
+			g_tConfig.readcheck.IsHDCP22 = cJSON_GetObjectItem(pReadCheck, _T("HDCP22")) ? cJSON_GetObjectItem(pReadCheck, _T("HDCP22"))->valueint : 1;
+			g_tConfig.readcheck.IsWIDI = cJSON_GetObjectItem(pReadCheck, _T("WIDI")) ? cJSON_GetObjectItem(pReadCheck, _T("WIDI"))->valueint : 1;
+			g_tConfig.readcheck.IsWIDEVINE = cJSON_GetObjectItem(pReadCheck, _T("WIDEVINE")) ? cJSON_GetObjectItem(pReadCheck, _T("WIDEVINE"))->valueint : 1;
+			g_tConfig.readcheck.IsESN = cJSON_GetObjectItem(pReadCheck, _T("ESN")) ? cJSON_GetObjectItem(pReadCheck, _T("ESN"))->valueint : 1;
+			g_tConfig.readcheck.IsCI = cJSON_GetObjectItem(pReadCheck, _T("CI")) ? cJSON_GetObjectItem(pReadCheck, _T("CI"))->valueint : 1;
+		}
+
+#ifdef SUPER_VER
+		// write check;
+		cJSON* pWriteCheck = cJSON_GetObjectItem(pJson, "WriteCheck");
+		if (pWriteCheck)
+		{
+			//g_tConfig.writecheck.IsPID = cJSON_GetObjectItem(pWriteCheck, _T("PID")) ? cJSON_GetObjectItem(pWriteCheck, _T("PID"))->valueint : 1;
+			//g_tConfig.writecheck.IsCHANNEL = cJSON_GetObjectItem(pWriteCheck, _T("CHANNEL")) ? cJSON_GetObjectItem(pWriteCheck, _T("CHANNEL"))->valueint : 1;
+			//g_tConfig.writecheck.IsOSD = cJSON_GetObjectItem(pWriteCheck, _T("OSD")) ? cJSON_GetObjectItem(pWriteCheck, _T("OSD"))->valueint : 1;
+			//g_tConfig.writecheck.IsSHOP = cJSON_GetObjectItem(pWriteCheck, _T("SHOP")) ? cJSON_GetObjectItem(pWriteCheck, _T("SHOP"))->valueint : 1;
+			g_tConfig.writecheck.IsDID = cJSON_GetObjectItem(pWriteCheck, _T("DID")) ? cJSON_GetObjectItem(pWriteCheck, _T("DID"))->valueint : 1;
+			g_tConfig.writecheck.IsMAC = cJSON_GetObjectItem(pWriteCheck, _T("MAC")) ? cJSON_GetObjectItem(pWriteCheck, _T("MAC"))->valueint : 1;
+			g_tConfig.writecheck.IsHDCP = cJSON_GetObjectItem(pWriteCheck, _T("HDCP")) ? cJSON_GetObjectItem(pWriteCheck, _T("HDCP"))->valueint : 1;
+			g_tConfig.writecheck.IsHDCP22 = cJSON_GetObjectItem(pWriteCheck, _T("HDCP22")) ? cJSON_GetObjectItem(pWriteCheck, _T("HDCP22"))->valueint : 1;
+			g_tConfig.writecheck.IsWIDI = cJSON_GetObjectItem(pWriteCheck, _T("WIDI")) ? cJSON_GetObjectItem(pWriteCheck, _T("WIDI"))->valueint : 1;
+			g_tConfig.writecheck.IsWIDEVINE = cJSON_GetObjectItem(pWriteCheck, _T("WIDEVINE")) ? cJSON_GetObjectItem(pWriteCheck, _T("WIDEVINE"))->valueint : 1;
+			g_tConfig.writecheck.IsESN = cJSON_GetObjectItem(pWriteCheck, _T("ESN")) ? cJSON_GetObjectItem(pWriteCheck, _T("ESN"))->valueint : 1;
+			g_tConfig.writecheck.IsCI = cJSON_GetObjectItem(pWriteCheck, _T("CI")) ? cJSON_GetObjectItem(pWriteCheck, _T("CI"))->valueint : 1;
+		}
+
+		// write done;
+		cJSON* pWriteDone = cJSON_GetObjectItem(pJson, "WriteDone");
+		if (pWriteDone)
+		{
+			g_tConfig.writedone.IsPID = cJSON_GetObjectItem(pWriteDone, _T("PID")) ? cJSON_GetObjectItem(pWriteDone, _T("PID"))->valueint : 1;
+			g_tConfig.writedone.IsCHANNEL = cJSON_GetObjectItem(pWriteDone, _T("CHANNEL")) ? cJSON_GetObjectItem(pWriteDone, _T("CHANNEL"))->valueint : 1;
+			g_tConfig.writedone.IsOSD = cJSON_GetObjectItem(pWriteDone, _T("OSD")) ? cJSON_GetObjectItem(pWriteDone, _T("OSD"))->valueint : 1;
+			g_tConfig.writedone.IsSHOP = cJSON_GetObjectItem(pWriteDone, _T("SHOP")) ? cJSON_GetObjectItem(pWriteDone, _T("SHOP"))->valueint : 1;
+			g_tConfig.writedone.IsDID = cJSON_GetObjectItem(pWriteDone, _T("DID")) ? cJSON_GetObjectItem(pWriteDone, _T("DID"))->valueint : 1;
+			g_tConfig.writedone.IsMAC = cJSON_GetObjectItem(pWriteDone, _T("MAC")) ? cJSON_GetObjectItem(pWriteDone, _T("MAC"))->valueint : 1;
+			g_tConfig.writedone.IsHDCP = cJSON_GetObjectItem(pWriteDone, _T("HDCP")) ? cJSON_GetObjectItem(pWriteDone, _T("HDCP"))->valueint : 1;
+			g_tConfig.writedone.IsHDCP22 = cJSON_GetObjectItem(pWriteDone, _T("HDCP22")) ? cJSON_GetObjectItem(pWriteDone, _T("HDCP22"))->valueint : 1;
+			g_tConfig.writedone.IsWIDI = cJSON_GetObjectItem(pWriteDone, _T("WIDI")) ? cJSON_GetObjectItem(pWriteDone, _T("WIDI"))->valueint : 1;
+			g_tConfig.writedone.IsWIDEVINE = cJSON_GetObjectItem(pWriteDone, _T("WIDEVINE")) ? cJSON_GetObjectItem(pWriteDone, _T("WIDEVINE"))->valueint : 1;
+			g_tConfig.writedone.IsESN = cJSON_GetObjectItem(pWriteDone, _T("ESN")) ? cJSON_GetObjectItem(pWriteDone, _T("ESN"))->valueint : 1;
+			g_tConfig.writedone.IsCI = cJSON_GetObjectItem(pWriteDone, _T("CI")) ? cJSON_GetObjectItem(pWriteDone, _T("CI"))->valueint : 1;
+		}
+#endif
+		// 配置;
+		cJSON* pChassis = cJSON_GetObjectItem(pJson, "Chassis-list");
+		if (pChassis)
+		{
+			int nCount = cJSON_GetArraySize(pChassis);
+			for (int i = 0; i < nCount; i++)
+			{
+				pItem = cJSON_GetArrayItem(pChassis, i);
+				if (pItem && pItem->child)
+				{
+					std::string name;
+					TChassis tchassis;
+
+					name = cJSON_GetObjectItem(pItem, _T("name")) ? cJSON_GetObjectItem(pItem, _T("name"))->valuestring : "";
+					tchassis.IsCopyDID = cJSON_GetObjectItem(pItem, _T("IsCopyDID")) ? cJSON_GetObjectItem(pItem, _T("IsCopyDID"))->valueint : 0;
+					tchassis.IsCopyMAC = cJSON_GetObjectItem(pItem, _T("IsCopyMAC")) ? cJSON_GetObjectItem(pItem, _T("IsCopyMAC"))->valueint : 0;
+					tchassis.IsCopyKEY = cJSON_GetObjectItem(pItem, _T("IsCopyKEY")) ? cJSON_GetObjectItem(pItem, _T("IsCopyKEY"))->valueint : 0;
+					tchassis.IsCopyESN = cJSON_GetObjectItem(pItem, _T("IsCopyESN")) ? cJSON_GetObjectItem(pItem, _T("IsCopyESN"))->valueint : 0;
+					tchassis.IsCopyWiDi = cJSON_GetObjectItem(pItem, _T("IsCopyWiDi")) ? cJSON_GetObjectItem(pItem, _T("IsCopyWiDi"))->valueint : 0;
+					tchassis.IsCopyWidevine = cJSON_GetObjectItem(pItem, _T("IsCopyWidevine")) ? cJSON_GetObjectItem(pItem, _T("IsCopyWidevine"))->valueint : 0;
+					tchassis.IsCopyKEY2_2 = cJSON_GetObjectItem(pItem, _T("IsCopyKEY2_2")) ? cJSON_GetObjectItem(pItem, _T("IsCopyKEY2_2"))->valueint : 0;
+					tchassis.IsCopyKEY2_3 = cJSON_GetObjectItem(pItem, _T("IsCopyKEY2_3")) ? cJSON_GetObjectItem(pItem, _T("IsCopyKEY2_3"))->valueint : 0;
+					tchassis.IsCopyCikey = cJSON_GetObjectItem(pItem, _T("IsCopyCikey")) ? cJSON_GetObjectItem(pItem, _T("IsCopyCikey"))->valueint : 0;
+					tchassis.IsCopyChannel = cJSON_GetObjectItem(pItem, _T("IsCopyChannel")) ? cJSON_GetObjectItem(pItem, _T("IsCopyChannel"))->valueint : 0;
+					tchassis.IsCopyWB = cJSON_GetObjectItem(pItem, _T("IsCopyWB")) ? cJSON_GetObjectItem(pItem, _T("IsCopyWB"))->valueint : 0;
+					tchassis.IsDisplayClientType = cJSON_GetObjectItem(pItem, _T("IsDisplayClientType")) ? cJSON_GetObjectItem(pItem, _T("IsDisplayClientType"))->valueint : 0;
+					tchassis.IsWritePID = cJSON_GetObjectItem(pItem, _T("IsWritePID")) ? cJSON_GetObjectItem(pItem, _T("IsWritePID"))->valueint : 0;
+					tchassis.IsWBInit = cJSON_GetObjectItem(pItem, _T("IsWBInit")) ? cJSON_GetObjectItem(pItem, _T("IsWBInit"))->valueint : 0;
+					tchassis.IsMTKInit = cJSON_GetObjectItem(pItem, _T("IsMTKInit")) ? cJSON_GetObjectItem(pItem, _T("IsMTKInit"))->valueint : 0;
+					tchassis.IsOsdLanguage = cJSON_GetObjectItem(pItem, _T("IsOsdLanguage")) ? cJSON_GetObjectItem(pItem, _T("IsOsdLanguage"))->valueint : 0;
+					tchassis.IsShopLanguage = cJSON_GetObjectItem(pItem, _T("IsShopLanguage")) ? cJSON_GetObjectItem(pItem, _T("IsShopLanguage"))->valueint : 0;
+					tchassis.IsCopyClientType = cJSON_GetObjectItem(pItem, _T("IsCopyClientType")) ? cJSON_GetObjectItem(pItem, _T("IsCopyClientType"))->valueint : 0;
+					tchassis.IsMGKKeyEnb = cJSON_GetObjectItem(pItem, _T("IsMGKKeyEnb")) ? cJSON_GetObjectItem(pItem, _T("IsMGKKeyEnb"))->valueint : 0;
+					tchassis.IsNovaTakHDCPEnb = cJSON_GetObjectItem(pItem, _T("IsNovaTakHDCPEnb")) ? cJSON_GetObjectItem(pItem, _T("IsNovaTakHDCPEnb"))->valueint : 0;
+
+					tchassis.ProjectID = cJSON_GetObjectItem(pItem, _T("ProjectID")) ? cJSON_GetObjectItem(pItem, _T("ProjectID"))->valueint : 0;
+					tchassis.Channel = cJSON_GetObjectItem(pItem, _T("Channel")) ? cJSON_GetObjectItem(pItem, _T("Channel"))->valuestring : "";
+					tchassis.WBFile = cJSON_GetObjectItem(pItem, _T("WBFile")) ? cJSON_GetObjectItem(pItem, _T("WBFile"))->valuestring : "";
+					tchassis.Delay = cJSON_GetObjectItem(pItem, _T("Delay")) ? cJSON_GetObjectItem(pItem, _T("Delay"))->valueint : 50;
+					tchassis.CheckString = cJSON_GetObjectItem(pItem, _T("CheckString")) ? cJSON_GetObjectItem(pItem, _T("CheckString"))->valuestring : "";
+					tchassis.ClientType = cJSON_GetObjectItem(pItem, _T("ClientType")) ? cJSON_GetObjectItem(pItem, _T("ClientType"))->valuestring : "";
+					tchassis.MACType = cJSON_GetObjectItem(pItem, _T("MACType")) ? cJSON_GetObjectItem(pItem, _T("MACType"))->valuestring : "";
+					tchassis.HDCPKeyType = cJSON_GetObjectItem(pItem, _T("HDCPKeyType")) ? cJSON_GetObjectItem(pItem, _T("HDCPKeyType"))->valuestring : "";
+					tchassis.HDCPKey22Type = cJSON_GetObjectItem(pItem, _T("HDCPKey22Type")) ? cJSON_GetObjectItem(pItem, _T("HDCPKey22Type"))->valuestring : "";
+					tchassis.HDCPKey23Type = cJSON_GetObjectItem(pItem, _T("HDCPKey23Type")) ? cJSON_GetObjectItem(pItem, _T("HDCPKey23Type"))->valuestring : "";
+					tchassis.ESNType = cJSON_GetObjectItem(pItem, _T("ESNType")) ? cJSON_GetObjectItem(pItem, _T("ESNType"))->valuestring : "";
+					tchassis.WiDiType = cJSON_GetObjectItem(pItem, _T("WiDiType")) ? cJSON_GetObjectItem(pItem, _T("WiDiType"))->valuestring : "";
+					tchassis.WidevineType = cJSON_GetObjectItem(pItem, _T("WidevineType")) ? cJSON_GetObjectItem(pItem, _T("WidevineType"))->valuestring : "";
+					tchassis.CIKeyType = cJSON_GetObjectItem(pItem, _T("CIKeyType")) ? cJSON_GetObjectItem(pItem, _T("CIKeyType"))->valuestring : "";
+					tchassis.MGKKeyType = cJSON_GetObjectItem(pItem, _T("MGKKeyType")) ? cJSON_GetObjectItem(pItem, _T("MGKKeyType"))->valuestring : "";
+					tchassis.NovaTakHDCPType = cJSON_GetObjectItem(pItem, _T("NovaTakHDCPType")) ? cJSON_GetObjectItem(pItem, _T("NovaTakHDCPType"))->valuestring : "";
+
+					g_tConfig.chassislist.insert(pair<std::string, CHASSIS>(name, tchassis));
+				}
+			}
+		}
+
+	end:
+		if (pdata)
+			free(pdata);
+
+		if (pJson)
+			cJSON_Delete(pJson);
+	}
+
+	void SetConfig()
+	{
+		// Json数据;
+		cJSON* pJson = cJSON_CreateObject();
+		cJSON_AddStringToObject(pJson, "COM", g_tConfig.com.c_str());
+		cJSON_AddStringToObject(pJson, "server-url", g_tConfig.serverurl.c_str());
+		cJSON_AddStringToObject(pJson, "Chassis", g_tConfig.chassis.c_str());
+		cJSON_AddNumberToObject(pJson, "Mode", g_tConfig.mode);
+		cJSON_AddNumberToObject(pJson, "WarnCount", g_tConfig.warncount);
+		cJSON_AddNumberToObject(pJson, "WaitBoot", g_tConfig.waitboot);
+		cJSON_AddStringToObject(pJson, "Baudrate", g_tConfig.baudrate.c_str());
+
+		// 频道;
+		cJSON* pItem = NULL;
+		cJSON* pChannel = cJSON_AddArrayToObject(pJson, _T("Channel"));
+		if (pChannel)
+		{
+			std::map<std::string, std::string>::iterator it = g_tConfig.channel.begin();
+			for (; it != g_tConfig.channel.end(); it++)
+			{
+				pItem = cJSON_AddObjectToObject(pChannel, it->first.c_str());
+				cJSON_AddStringToObject(pItem, it->first.c_str(), it->second.c_str());
+			}
+		}
+
+		// 语言;
+		cJSON* pLanguage = cJSON_AddArrayToObject(pJson, _T("Language"));
+		if (pLanguage)
+		{
+			std::map<std::string, std::string>::iterator it = g_tConfig.language.begin();
+			for (; it != g_tConfig.language.end(); it++)
+			{
+				pItem = cJSON_AddObjectToObject(pLanguage, it->first.c_str());
+				cJSON_AddStringToObject(pItem, it->first.c_str(), it->second.c_str());
+			}
+		}
+
+		// 文件夹;
+		cJSON* pKeyFolder = cJSON_AddArrayToObject(pJson, _T("KeyFolder"));
+		if (pKeyFolder)
+		{
+			std::map<std::string, std::string>::iterator it = g_tConfig.keyfolder.begin();
+			for (; it != g_tConfig.keyfolder.end(); it++)
+			{
+				pItem = cJSON_AddObjectToObject(pKeyFolder, it->first.c_str());
+				cJSON_AddStringToObject(pItem, it->first.c_str(), it->second.c_str());
+			}
+		}
+
+		// read check;
+		cJSON* pReadCheck = cJSON_AddObjectToObject(pJson, "ReadCheck");
+		if (pReadCheck)
+		{
+			cJSON_AddBoolToObject(pReadCheck, _T("PID"), g_tConfig.readcheck.IsPID);
+			cJSON_AddBoolToObject(pReadCheck, _T("CHANNEL"), g_tConfig.readcheck.IsCHANNEL);
+			cJSON_AddBoolToObject(pReadCheck, _T("OSD"), g_tConfig.readcheck.IsOSD);
+			cJSON_AddBoolToObject(pReadCheck, _T("SHOP"), g_tConfig.readcheck.IsSHOP);
+			cJSON_AddBoolToObject(pReadCheck, _T("DID"), g_tConfig.readcheck.IsDID);
+			cJSON_AddBoolToObject(pReadCheck, _T("MAC"), g_tConfig.readcheck.IsMAC);
+			cJSON_AddBoolToObject(pReadCheck, _T("HDCP"), g_tConfig.readcheck.IsHDCP);
+			cJSON_AddBoolToObject(pReadCheck, _T("HDCP22"), g_tConfig.readcheck.IsHDCP22);
+			cJSON_AddBoolToObject(pReadCheck, _T("WIDI"), g_tConfig.readcheck.IsWIDI);
+			cJSON_AddBoolToObject(pReadCheck, _T("WIDEVINE"), g_tConfig.readcheck.IsWIDEVINE);
+			cJSON_AddBoolToObject(pReadCheck, _T("ESN"), g_tConfig.readcheck.IsESN);
+			cJSON_AddBoolToObject(pReadCheck, _T("CI"), g_tConfig.readcheck.IsCI);
+		}
+#ifdef SUPER_VER
+		// write check;
+		cJSON* pWriteCheck = cJSON_AddObjectToObject(pJson, "WriteCheck");
+		if (pWriteCheck)
+		{
+			//cJSON_AddBoolToObject(pWriteCheck, _T("PID"), g_tConfig.writecheck.IsPID);
+			//cJSON_AddBoolToObject(pWriteCheck, _T("CHANNEL"), g_tConfig.writecheck.IsCHANNEL);
+			//cJSON_AddBoolToObject(pWriteCheck, _T("OSD"), g_tConfig.writecheck.IsOSD);
+			//cJSON_AddBoolToObject(pWriteCheck, _T("SHOP"), g_tConfig.writecheck.IsSHOP);
+			cJSON_AddBoolToObject(pWriteCheck, _T("DID"), g_tConfig.writecheck.IsDID);
+			cJSON_AddBoolToObject(pWriteCheck, _T("MAC"), g_tConfig.writecheck.IsMAC);
+			cJSON_AddBoolToObject(pWriteCheck, _T("HDCP"), g_tConfig.writecheck.IsHDCP);
+			cJSON_AddBoolToObject(pWriteCheck, _T("HDCP22"), g_tConfig.writecheck.IsHDCP22);
+			cJSON_AddBoolToObject(pWriteCheck, _T("WIDI"), g_tConfig.writecheck.IsWIDI);
+			cJSON_AddBoolToObject(pWriteCheck, _T("WIDEVINE"), g_tConfig.writecheck.IsWIDEVINE);
+			cJSON_AddBoolToObject(pWriteCheck, _T("ESN"), g_tConfig.writecheck.IsESN);
+			cJSON_AddBoolToObject(pWriteCheck, _T("CI"), g_tConfig.writecheck.IsCI);
+		}
+
+		// write done;
+		cJSON* pWriteDone= cJSON_AddObjectToObject(pJson, "WriteDone");
+		if (pWriteDone)
+		{
+			cJSON_AddBoolToObject(pWriteDone, _T("PID"), g_tConfig.writedone.IsPID);
+			cJSON_AddBoolToObject(pWriteDone, _T("CHANNEL"), g_tConfig.writedone.IsCHANNEL);
+			cJSON_AddBoolToObject(pWriteDone, _T("OSD"), g_tConfig.writedone.IsOSD);
+			cJSON_AddBoolToObject(pWriteDone, _T("SHOP"), g_tConfig.writedone.IsSHOP);
+			cJSON_AddBoolToObject(pWriteDone, _T("DID"), g_tConfig.writedone.IsDID);
+			cJSON_AddBoolToObject(pWriteDone, _T("MAC"), g_tConfig.writedone.IsMAC);
+			cJSON_AddBoolToObject(pWriteDone, _T("HDCP"), g_tConfig.writedone.IsHDCP);
+			cJSON_AddBoolToObject(pWriteDone, _T("HDCP22"), g_tConfig.writedone.IsHDCP22);
+			cJSON_AddBoolToObject(pWriteDone, _T("WIDI"), g_tConfig.writedone.IsWIDI);
+			cJSON_AddBoolToObject(pWriteDone, _T("WIDEVINE"), g_tConfig.writedone.IsWIDEVINE);
+			cJSON_AddBoolToObject(pWriteDone, _T("ESN"), g_tConfig.writedone.IsESN);
+			cJSON_AddBoolToObject(pWriteDone, _T("CI"), g_tConfig.writedone.IsCI);
+		}
+#endif
+		// 配置;
+		cJSON* pChassis = cJSON_AddArrayToObject(pJson, _T("Chassis-list"));
+		if (pChassis)
+		{
+			std::map<std::string, TChassis>::iterator it = g_tConfig.chassislist.begin();
+			for (; it != g_tConfig.chassislist.end(); it++)
+			{
+				pItem = cJSON_AddObjectToObject(pChassis, it->first.c_str());
+				cJSON_AddStringToObject(pItem, _T("name"), it->first.c_str());
+				// bool
+				cJSON_AddBoolToObject(pItem, _T("IsCopyDID"), it->second.IsCopyDID);
+				cJSON_AddBoolToObject(pItem, _T("IsCopyMAC"), it->second.IsCopyMAC);
+				cJSON_AddBoolToObject(pItem, _T("IsCopyKEY"), it->second.IsCopyKEY);
+				cJSON_AddBoolToObject(pItem, _T("IsCopyESN"), it->second.IsCopyESN);
+				cJSON_AddBoolToObject(pItem, _T("IsCopyWiDi"), it->second.IsCopyWiDi);
+				cJSON_AddBoolToObject(pItem, _T("IsCopyWidevine"), it->second.IsCopyWidevine);
+				cJSON_AddBoolToObject(pItem, _T("IsCopyKEY2_2"), it->second.IsCopyKEY2_2);
+				cJSON_AddBoolToObject(pItem, _T("IsCopyKEY2_3"), it->second.IsCopyKEY2_3);
+				cJSON_AddBoolToObject(pItem, _T("IsCopyCikey"), it->second.IsCopyCikey);
+				cJSON_AddBoolToObject(pItem, _T("IsCopyChannel"), it->second.IsCopyChannel);
+				cJSON_AddBoolToObject(pItem, _T("IsCopyWB"), it->second.IsCopyWB);
+				cJSON_AddBoolToObject(pItem, _T("IsDisplayClientType"), it->second.IsDisplayClientType);
+				cJSON_AddBoolToObject(pItem, _T("IsWritePID"), it->second.IsWritePID);
+				cJSON_AddBoolToObject(pItem, _T("IsWBInit"), it->second.IsWBInit);
+				cJSON_AddBoolToObject(pItem, _T("IsMTKInit"), it->second.IsMTKInit);
+				cJSON_AddBoolToObject(pItem, _T("IsOsdLanguage"), it->second.IsOsdLanguage);
+				cJSON_AddBoolToObject(pItem, _T("IsShopLanguage"), it->second.IsShopLanguage);
+				cJSON_AddBoolToObject(pItem, _T("IsCopyClientType"), it->second.IsCopyClientType);
+				cJSON_AddBoolToObject(pItem, _T("IsMGKKeyEnb"), it->second.IsMGKKeyEnb);
+				cJSON_AddBoolToObject(pItem, _T("IsNovaTakHDCPEnb"), it->second.IsNovaTakHDCPEnb);
+				// ini
+				cJSON_AddNumberToObject(pItem, _T("ProjectID"), it->second.ProjectID);
+				cJSON_AddNumberToObject(pItem, _T("Delay"), it->second.Delay);
+				// string
+				cJSON_AddStringToObject(pItem, _T("Channel"), it->second.Channel.c_str());
+				cJSON_AddStringToObject(pItem, _T("WBFile"), it->second.WBFile.c_str());
+				cJSON_AddStringToObject(pItem, _T("CheckString"), it->second.CheckString.c_str());
+				cJSON_AddStringToObject(pItem, _T("ClientType"), it->second.ClientType.c_str());
+				cJSON_AddStringToObject(pItem, _T("MACType"), it->second.MACType.c_str());
+				cJSON_AddStringToObject(pItem, _T("HDCPKeyType"), it->second.HDCPKeyType.c_str());
+				cJSON_AddStringToObject(pItem, _T("HDCPKey22Type"), it->second.HDCPKey22Type.c_str());
+				cJSON_AddStringToObject(pItem, _T("HDCPKey23Type"), it->second.HDCPKey23Type.c_str());
+				cJSON_AddStringToObject(pItem, _T("ESNType"), it->second.ESNType.c_str());
+				cJSON_AddStringToObject(pItem, _T("WiDiType"), it->second.WiDiType.c_str());
+				cJSON_AddStringToObject(pItem, _T("WidevineType"), it->second.WidevineType.c_str());
+				cJSON_AddStringToObject(pItem, _T("CIKeyType"), it->second.CIKeyType.c_str());
+				cJSON_AddStringToObject(pItem, _T("MGKKeyType"), it->second.MGKKeyType.c_str());
+				cJSON_AddStringToObject(pItem, _T("NovaTakHDCPType"), it->second.NovaTakHDCPType.c_str());
+			}
+		}
+
+		char* pJsonText = cJSON_Print(pJson);
+
+		// 保存到文件中;
+		FILE* pf = NULL;
+		_tfopen_s(&pf, _T("./Config.json"), _T("wb"));
+		if (pf)
+		{
+			fwrite(pJsonText, _tcslen(pJsonText), 1, pf);
+			fclose(pf);
+		}
+
+		if (pJsonText)
+			delete[] pJsonText;
+		cJSON_Delete(pJson);
+	}
+
+	// 去除空格;
+	std::string& trim(std::string& str)
+	{
+		int nIndex = 0;
+		while ((nIndex = str.find_first_of(' ')) != std::string::npos)
+			str.erase(nIndex, 1);
+
+		return str;
+	}
+
+	// hModule 模块句柄 NULL表示当前模块;
+	bool GetVersion(IN const TCHAR* fname, OUT WORD* pdwFileVersion, OUT WORD* pdwProductVerion)
+	{
+		VS_FIXEDFILEINFO* pVi = NULL;
+		DWORD dwHandle = 0;
+		int size = GetFileVersionInfoSize(fname, &dwHandle);
+		if (size > 0)
+		{
+			BYTE* buffer = new BYTE[size];
+			memset(buffer, 0, size);
+
+			if (GetFileVersionInfo(fname, 0, size, buffer))
+			{
+				if (VerQueryValue(buffer, _T("\\"), (LPVOID*)& pVi, (PUINT)& size))
+				{
+					pdwFileVersion[0] = HIWORD(pVi->dwFileVersionMS);
+					pdwFileVersion[1] = LOWORD(pVi->dwFileVersionMS);
+					pdwFileVersion[2] = HIWORD(pVi->dwFileVersionLS);
+					pdwFileVersion[3] = LOWORD(pVi->dwFileVersionLS);
+
+					pdwProductVerion[0] = HIWORD(pVi->dwProductVersionMS);
+					pdwProductVerion[1] = LOWORD(pVi->dwProductVersionMS);
+					pdwProductVerion[2] = HIWORD(pVi->dwProductVersionLS);
+					pdwProductVerion[3] = LOWORD(pVi->dwProductVersionLS);
+
+					delete[] buffer;
+					return true;
+				}
+			}
+
+			delete[] buffer;
+		}
+
+		return false;
+	}
+
+	BOOL GetVersion(IN HMODULE hModule, OUT DWORD(&dwFVArray)[4], OUT DWORD(&dwPVArray)[4])
+	{
+		TCHAR fname[MAX_PATH];
+		VS_FIXEDFILEINFO* pVi;
+		DWORD dwHandle;
+
+		if (GetModuleFileName(hModule, fname, MAX_PATH))
+		{
+			INT nSize = GetFileVersionInfoSize(fname, &dwHandle);
+
+			if (nSize > 0)
+			{
+				BYTE* pBuffer = new BYTE[nSize];
+				memset(pBuffer, 0, nSize);
+
+				if (GetFileVersionInfo(fname, 0, nSize, pBuffer))
+				{
+					if (VerQueryValue(pBuffer, _T("\\"), (LPVOID*)& pVi, (PUINT)& nSize))
+					{
+						dwFVArray[0] = HIWORD(pVi->dwFileVersionMS);
+						dwFVArray[1] = LOWORD(pVi->dwFileVersionMS);
+						dwFVArray[2] = HIWORD(pVi->dwFileVersionLS);
+						dwFVArray[3] = LOWORD(pVi->dwFileVersionLS);
+
+						dwPVArray[0] = HIWORD(pVi->dwProductVersionMS);
+						dwPVArray[1] = LOWORD(pVi->dwProductVersionMS);
+						dwPVArray[2] = HIWORD(pVi->dwProductVersionLS);
+						dwPVArray[3] = LOWORD(pVi->dwProductVersionLS);
+
+						delete[]pBuffer;
+						return TRUE;
+					}
+				}
+
+				if (pBuffer)
+					delete[]pBuffer;
+			}
+		}
+
+		return FALSE;
+	}
+
+	WCHAR* ASCII2UNICODE(IN LPCCH lpASCIIStr)
+	{
+		if (lpASCIIStr == NULL)
+			return NULL;
+
+		// 获取宽字符字节数;
+		int cchWideChar = MultiByteToWideChar(CP_ACP, 0, lpASCIIStr, -1, NULL, 0);
+		if (cchWideChar == 0)
+			return NULL;
+
+		// 转换成宽字符串;
+		WCHAR* pWideChar = new WCHAR[cchWideChar + 1];
+		memset(pWideChar, 0, sizeof(WCHAR) * (cchWideChar + 1));
+		int nWriteNum = MultiByteToWideChar(CP_ACP, 0, lpASCIIStr, -1, pWideChar, cchWideChar);
+		if (nWriteNum != cchWideChar)
+		{
+			if (pWideChar)
+				delete[] pWideChar;
+			return NULL;
+		}
+
+		return pWideChar;
+	}
+
+	BOOL UNICODE2UTF8(IN LPWCH lpUNICODEStr, OUT string& strResult)
+	{
+		if (lpUNICODEStr == NULL)
+			return FALSE;
+
+		// 获取多字节字符字节数;
+		int cbMultiByte = WideCharToMultiByte(CP_UTF8, 0, lpUNICODEStr, -1, NULL, 0, NULL, NULL);
+		if (cbMultiByte == 0)
+			return FALSE;
+
+		// 转换成多字节字符;
+		CHAR* pResult = new CHAR[cbMultiByte];
+		memset(pResult, 0, cbMultiByte);
+		int nWriteNum = WideCharToMultiByte(CP_UTF8, 0, lpUNICODEStr, -1, pResult, cbMultiByte, NULL, NULL);
+		if (nWriteNum != cbMultiByte)
+			return FALSE;
+
+		strResult = pResult;
+		if (pResult)
+			delete[] pResult;
+
+		return TRUE;
+	}
+
+	BOOL ASCII2UTF8(IN LPCCH lpASCIIStr, OUT string& strResult)
+	{
+		// 将ASCII字符串转成UNICODE字符串;
+		WCHAR* pWideChar = ASCII2UNICODE(lpASCIIStr);
+		if (pWideChar == NULL)
+			return FALSE;
+
+		// 再将UICODE转成UTF8;
+		BOOL bResult = UNICODE2UTF8(pWideChar, strResult);
+
+		if (pWideChar)
+			delete[] pWideChar;
+
+		return bResult;
+	}
+
+	string EnCode_UTF8URL(IN const CHAR* pText)
+	{
+		string tt = "";
+		string dd = "";
+		ASCII2UTF8(pText, tt);
+
+		size_t len = tt.length();
+		for (size_t i = 0; i < len; i++)
+		{
+			if (isalnum((BYTE)tt.at(i)))
+			{
+				char tempbuff[2] = { 0 };
+				sprintf_s(tempbuff, "%c", (BYTE)tt.at(i));
+				dd.append(tempbuff);
+			}
+			else if (isspace((BYTE)tt.at(i)))
+			{
+				dd.append("+");
+			}
+			else
+			{
+				char tempbuff[4];
+				sprintf_s(tempbuff, "%%%X%X", ((BYTE)tt.at(i)) >> 4, ((BYTE)tt.at(i)) % 16);
+				dd.append(tempbuff);
+			}
+		}
+		return dd;
+	}
+
+	void EnCode_UTF8URL(IN const CHAR* pText, OUT string& strResult)
+	{
+		string tt = "";
+		ASCII2UTF8(pText, tt);
+
+		size_t len = tt.length();
+		for (size_t i = 0; i < len; i++)
+		{
+			if (isalnum((BYTE)tt.at(i)))
+			{
+				char tempbuff[2] = { 0 };
+				sprintf_s(tempbuff, "%c", (BYTE)tt.at(i));
+				strResult.append(tempbuff);
+			}
+			else if (isspace((BYTE)tt.at(i)))
+			{
+				strResult.append("+");
+			}
+			else
+			{
+				char tempbuff[4];
+				sprintf_s(tempbuff, "%%%X%X", ((BYTE)tt.at(i)) >> 4, ((BYTE)tt.at(i)) % 16);
+				strResult.append(tempbuff);
+			}
+		}
+	}
+
+	// 通过注册表查找系统当前串口信息;
+	BOOL GetSysSerialPort(std::vector<std::string>& vtports)
+	{
+		HKEY hKey;
+		LSTATUS lReg = 0;
+		DWORD dwMaxValLen = 0;
+		DWORD dwValNum = 0;
+		lReg = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\SERIALCOMM", 0, KEY_QUERY_VALUE, &hKey);
+		if (lReg != ERROR_SUCCESS)
+		{
+			LOG4C((LOG_WARN, "Open Registry Error"));
+			return FALSE;
+		}
+
+		lReg = RegQueryInfoKeyA(hKey, NULL, NULL, NULL, NULL, NULL, NULL, &dwValNum, &dwMaxValLen, NULL, NULL, NULL);
+		if (lReg != ERROR_SUCCESS)
+		{
+			LOG4C((LOG_WARN, "Getting Key Info Error"));
+			return FALSE;
+		}
+
+		if (vtports.size())
+		{
+			vtports.clear();
+		}
+
+		LPSTR lpValName, lpComNum;
+		DWORD dwValName, dwValSize = 6;
+		for (DWORD i = 0; i < dwValNum; i++)
+		{
+			dwValName = dwMaxValLen + 1;
+			dwValSize = 6;
+			lpValName = (LPSTR)VirtualAlloc(NULL, dwValName, MEM_COMMIT, PAGE_READWRITE);
+			lReg = RegEnumValueA(hKey, i, lpValName, &dwValName, NULL, NULL, NULL, NULL);
+			if ((lReg != ERROR_SUCCESS) && (lReg != ERROR_NO_MORE_ITEMS))
+			{
+				LOG4C((LOG_WARN, "Enum  Registry  Error or No More Items"));
+				continue;
+			}
+			lpComNum = (LPSTR)VirtualAlloc(NULL, 6, MEM_COMMIT, PAGE_READWRITE);
+			lReg = RegQueryValueExA(hKey, lpValName, NULL, NULL, (LPBYTE)lpComNum, &dwValSize);
+			if (lReg != ERROR_SUCCESS)
+			{
+				LOG4C((LOG_WARN, "Can not get the name of the port"));
+				continue;
+			}
+
+			vtports.push_back(lpComNum);
+			VirtualFree(lpValName, 0, MEM_RELEASE);
+			VirtualFree(lpComNum, 0, MEM_RELEASE);
+		}
+
+		return TRUE;
+	}
+
+	INT GetMacAddress()
+	{
+		HDEVINFO hDevInfo;
+		DWORD MemberIndex, RequiredSize;
+		SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
+		PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData;
+		INT nTotal = 0;
+		INT nNICKind = 0;
+
+		// 获取设备信息集;
+		hDevInfo = SetupDiGetClassDevs(&MacClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);
+		if (hDevInfo == INVALID_HANDLE_VALUE)
+		{
+			return -1;
+		}
+
+		g_vtMac.clear();
+		// 枚举设备信息集中所有设备;
+		DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
+		for (MemberIndex = 0; SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &MacClassGuid, MemberIndex, &DeviceInterfaceData); MemberIndex++)
+		{
+			// 获取接收缓冲区大小,函数返回值为FALSE,GetLastError()=ERROR_INSUFFICIENT_BUFFER;
+			SetupDiGetDeviceInterfaceDetail(hDevInfo, &DeviceInterfaceData, NULL, 0, &RequiredSize, NULL);
+
+			// 申请接收缓冲区;
+			DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(RequiredSize);
+			DeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
+
+			// 获取设备细节信息;
+			if (SetupDiGetDeviceInterfaceDetail(hDevInfo, &DeviceInterfaceData, DeviceInterfaceDetailData, RequiredSize, NULL, NULL))
+			{
+				HANDLE hDeviceFile;
+				BOOL isOK = FALSE;
+				if (_tcsnicmp(DeviceInterfaceDetailData->DevicePath + 4, TEXT("pci"), 3) != 0)
+					continue;
+
+				MacAddress tagMacAddress;
+				tagMacAddress.nNICKind = NIC_PCI;
+				_stprintf_s(tagMacAddress.szNICKind, _T("%s"), _T("NIC_PCI"));
+
+				// 获取设备句柄;
+				hDeviceFile = CreateFile(DeviceInterfaceDetailData->DevicePath,
+					0,
+					FILE_SHARE_READ | FILE_SHARE_WRITE,
+					NULL,
+					OPEN_EXISTING,
+					0,
+					NULL);
+
+				if (hDeviceFile != INVALID_HANDLE_VALUE)
+				{
+					ULONG dwID;
+					BYTE ucData[8];
+					DWORD dwByteRet;
+
+					// 获取原生MAC地址;
+					dwID = OID_802_3_PERMANENT_ADDRESS;
+					isOK = DeviceIoControl(hDeviceFile, IOCTL_NDIS_QUERY_GLOBAL_STATS, &dwID, sizeof(dwID), ucData, sizeof(ucData), &dwByteRet, NULL);
+					if (isOK)
+					{
+						++nTotal;
+						_stprintf_s(tagMacAddress.szDevicePath, _T("%s"), DeviceInterfaceDetailData->DevicePath);
+						memset(tagMacAddress.szMacAddress, 0, sizeof(TCHAR) * MAX_PATH);
+						// 将字节数组转换成16进制字符串;
+						for (DWORD i = 0; i < dwByteRet; i++)
+						{
+							_stprintf_s(&tagMacAddress.szMacAddress[i * 3], MAX_PATH - (i * 3), (i != dwByteRet - 1) ? _T("%02X-") : _T("%02X"), ucData[i]);
+						}
+
+						g_vtMac.push_back(tagMacAddress);
+					}
+					CloseHandle(hDeviceFile);
+				}
+			}
+
+			free(DeviceInterfaceDetailData);
+		}
+
+		SetupDiDestroyDeviceInfoList(hDevInfo);
+
+#if 1
+		g_strMacs.clear();
+		std::vector<MacAddress>::iterator it = g_vtMac.begin();
+		for (; it != g_vtMac.end(); it++)
+		{
+			g_strMacs.append(it->szMacAddress);
+			g_strMacs.append("&");
+		}
+#endif
+
+		return nTotal;
+	}
+
+	BOOL IsValidString(LPCTSTR lpszString)
+	{
+		if (lpszString == NULL)
+			return FALSE;
+
+		do
+		{
+			// ASCII可显示的字符;
+			if (*lpszString < 32 || *lpszString > 126)
+			{
+				return FALSE;
+			}
+		} while (*++lpszString);
+
+		return TRUE;
+	}
+} // namespace Global

+ 300 - 0
scbc.tools/scbc.tools/Global.h

@@ -0,0 +1,300 @@
+
+#pragma once
+#include <stdio.h>
+#include <locale.h>
+#include <stdlib.h>
+#include <time.h> //或者 #include <ctime>
+#include <io.h>
+#pragma comment(lib, "version.lib")
+#include "../cJson/cJSON.h"
+#include "tinyxml2.h"
+#include "Log4c.h"
+#include <vector>
+#include <string>
+
+namespace Global
+{
+	//////////////////////////////////////////////////////////////////////////
+	// 升级包请求体;
+	typedef struct
+	{
+		std::string appid;
+		std::string devicemodel;
+		std::string dnum;
+		std::string ver;
+		std::string type;
+	} __update_post__;
+
+	// 升级包返回体;
+	typedef struct
+	{
+		std::string servertime;
+		std::string callid;
+		std::string status;
+		std::string note;
+		std::string language;
+		std::string apiversion;
+		typedef struct
+		{
+			std::string now;
+			std::string type;
+			std::string appid;
+			std::string apptype;
+			std::string version;
+			std::string verid;
+			std::string md5;
+			std::string size;
+			std::string minicon;
+			std::string midicon;
+			std::string fileurl;
+			std::string increment;
+			std::string appendver;
+			std::string updatetime;
+		} __upcontent__;
+		__upcontent__ upcontent;
+	} __update_result__;
+
+	// 烧录数据请求体;
+	typedef struct
+	{
+		std::string clienttype;
+		//std::string	projectid;
+		std::string version;
+		std::string bid; //批次号;
+		std::string mac; // mac地址;
+	} __burndata_post__;
+
+	typedef struct
+	{
+		std::string name;
+		std::string type;
+	} __burndata__;
+
+	typedef struct
+	{
+		std::string message;
+		std::string code;
+		std::string factoryname;
+		std::string factoryip;
+		std::string factoryNum;
+		std::string version;
+		std::string projectid;
+		std::string clienttype;
+		std::string host;
+		std::vector<__burndata__> obj;
+	} __burndata_result__;
+
+	typedef struct CHASSIS
+	{
+		bool IsCopyDID;
+		bool IsCopyMAC;
+		bool IsCopyKEY;
+		bool IsCopyESN;
+		bool IsCopyWiDi;
+		bool IsCopyWidevine;
+		bool IsCopyKEY2_2;
+		bool IsCopyKEY2_3;
+		bool IsCopyCikey;
+		bool IsCopyChannel;
+		bool IsCopyWB;
+		bool IsDisplayClientType;
+		bool IsWritePID;
+		bool IsWBInit;
+		bool IsMTKInit;
+		bool IsOsdLanguage;
+		bool IsShopLanguage;
+		bool IsCopyClientType;
+		bool IsMGKKeyEnb;
+		bool IsNovaTakHDCPEnb;
+
+		int Delay;
+		unsigned int ProjectID;
+		std::string Channel;
+		std::string WBFile;
+		std::string CheckString;
+		std::string ClientType;
+		std::string MACType;
+		std::string HDCPKeyType;
+		std::string HDCPKey22Type;
+		std::string HDCPKey23Type;
+		std::string ESNType;
+		std::string WiDiType;
+		std::string WidevineType;
+		std::string CIKeyType;
+		std::string OsdLanguage;
+		std::string ShopLanguage;
+		std::string MGKKeyType;
+		std::string NovaTakHDCPType;
+		std::string url;	// 在线服务器;
+		std::string name;	// chassis name;
+
+		CHASSIS& operator=(const CHASSIS& that)
+		{
+			if (this != &that)
+			{
+				url = that.url;
+				name = that.name;
+				IsCopyDID = that.IsCopyDID;
+				IsCopyMAC = that.IsCopyMAC;
+				IsCopyKEY = that.IsCopyKEY;
+				IsCopyESN = that.IsCopyESN;
+				IsCopyWiDi = that.IsCopyWiDi;
+				IsCopyWidevine = that.IsCopyWidevine;
+				IsCopyKEY2_2 = that.IsCopyKEY2_2;
+				IsCopyKEY2_3 = that.IsCopyKEY2_3;
+				IsCopyCikey = that.IsCopyCikey;
+				IsCopyChannel = that.IsCopyChannel;
+				IsCopyWB = that.IsCopyWB;
+				IsDisplayClientType = that.IsDisplayClientType;
+				IsWritePID = that.IsWritePID;
+				IsWBInit = that.IsWBInit;
+				IsMTKInit = that.IsMTKInit;
+				IsOsdLanguage = that.IsOsdLanguage;
+				IsShopLanguage = that.IsShopLanguage;
+				IsCopyClientType = that.IsCopyClientType;
+				IsMGKKeyEnb = that.IsMGKKeyEnb;
+				IsNovaTakHDCPEnb = that.IsNovaTakHDCPEnb;
+
+				Delay = that.Delay;
+				ProjectID = that.ProjectID;
+
+				Channel = that.Channel;
+				WBFile = that.WBFile;
+				CheckString = that.CheckString;
+				ClientType = that.ClientType;
+				MACType = that.MACType;
+				HDCPKeyType = that.HDCPKeyType;
+				HDCPKey22Type = that.HDCPKey22Type;
+				HDCPKey23Type = that.HDCPKey23Type;
+				ESNType = that.ESNType;
+				WiDiType = that.WiDiType;
+				WidevineType = that.WidevineType;
+				CIKeyType = that.CIKeyType;
+				OsdLanguage = that.OsdLanguage;
+				ShopLanguage = that.ShopLanguage;
+				MGKKeyType = that.MGKKeyType;
+				NovaTakHDCPType = that.NovaTakHDCPType;
+			}
+			return *this;
+		}
+	} TChassis, * pTChassis;
+
+	typedef struct __READCHECK__
+	{
+		bool IsPID = true;
+		bool IsCHANNEL = true;
+		bool IsOSD = true;
+		bool IsSHOP = true;
+		bool IsDID = true;
+		bool IsMAC = true;
+		bool IsHDCP = true;
+		bool IsHDCP22 = true;
+		bool IsWIDI = true;
+		bool IsWIDEVINE = true;
+		bool IsESN = true;
+		bool IsCI = true;
+	}TReadCheck, * pTReadCheck;
+
+	typedef struct __WRITECHECK__
+	{
+		//bool IsPID = true;
+		//bool IsCHANNEL = true;
+		//bool IsOSD = true;
+		//bool IsSHOP = true;
+		bool IsDID = true;
+		bool IsMAC = true;
+		bool IsHDCP = true;
+		bool IsHDCP22 = true;
+		bool IsWIDI = true;
+		bool IsWIDEVINE = true;
+		bool IsESN = true;
+		bool IsCI = true;
+	}TWriteCheck, * pWriteCheck;
+
+	typedef struct __WRITEDONE__
+	{
+		bool IsPID = true;
+		bool IsCHANNEL = true;
+		bool IsOSD = true;
+		bool IsSHOP = true;
+		bool IsDID = true;
+		bool IsMAC = true;
+		bool IsHDCP = true;
+		bool IsHDCP22 = true;
+		bool IsWIDI = true;
+		bool IsWIDEVINE = true;
+		bool IsESN = true;
+		bool IsCI = true;
+	}TWriteDone, * pTWriteDone;
+
+	extern Global::TChassis g_AutoOnlineChassis;
+	// 配置文件;
+	typedef struct TCONFIG
+	{
+		std::string com;
+		std::string baudrate;
+		std::string chassis;
+		int mode;
+		int warncount = 200;
+		int waitboot = 5000;
+		std::string siacpcmdfile;
+		std::string serverurl;
+		std::map<std::string, std::string> channel;
+		std::map<std::string, std::string> language;
+		std::map<std::string, std::string> keyfolder;
+		std::map<std::string, TChassis> chassislist;
+		TReadCheck readcheck;
+		TWriteCheck writecheck;
+		TWriteDone writedone;
+	} TConfig, * pTConfig;
+
+	// 网卡类型;
+	enum NICKIND
+	{
+		// pci网卡;
+		NIC_PCI,
+		// usb网卡;
+		NIC_USB,
+		// 虚拟网卡;
+		NIC_ROOT,
+		// 仿真网卡;
+		NIC_SWD,
+		// 未知类型;
+		NIC_UNK
+	};
+
+	typedef struct __MAC_ADDRESS__
+	{
+		INT nNICKind;
+		TCHAR szNICKind[16];
+		TCHAR szMacAddress[MAX_PATH];
+		TCHAR szDevicePath[MAX_PATH];
+	} MacAddress, * pMacAddress;
+	//////////////////////////////////////////////////////////////////////////
+	// 全局变量;
+	extern BOOL g_bTestHost;
+	extern TCHAR g_szCurModuleDir[MAX_PATH];
+	extern TCHAR g_szCurModulePath[MAX_PATH];
+	extern TCHAR g_szFna[MAX_PATH];
+	extern TCHAR g_szConfig[MAX_PATH];
+	extern std::string g_strMacs;
+	extern std::vector<MacAddress> g_vtMac;
+	extern TConfig g_tConfig;
+
+	//////////////////////////////////////////////////////////////////////////
+	// 全局函数;
+	void GetConfig();
+	void SetConfig();
+	bool GetVersion(IN const TCHAR* fname, OUT WORD* pdwFileVersion, OUT WORD* pdwProductVerion);
+	BOOL GetVersion(IN HMODULE hModule, OUT DWORD(&dwFVArray)[4], OUT DWORD(&dwPVArray)[4]);
+	void WriteTextLog(const TCHAR* format, ...);
+	std::string EnCode_UTF8URL(IN const CHAR* pText);
+	std::string& trim(std::string& str);
+	// 获取网卡地址;
+	INT GetMacAddress();
+	// 字符串是否由数字、字母、符号组成;
+	BOOL IsValidString(LPCTSTR lpszString);
+
+	// 获取系统当前串口数量;
+	BOOL GetSysSerialPort(std::vector<std::string>& vtports);
+}; // namespace Global

+ 48 - 0
scbc.tools/scbc.tools/ReadMe.txt

@@ -0,0 +1,48 @@
+========================================================================
+    动态链接库:scbc.tools 项目概述
+========================================================================
+
+应用程序向导已为您创建了此 scbc.tools DLL。
+
+本文件概要介绍组成 scbc.tools 应用程序的
+的每个文件的内容。
+
+
+scbc.tools.vcproj
+    这是使用应用程序向导生成的 VC++ 项目的主项目文件,
+    其中包含生成该文件的 Visual C++ 的版本信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。
+
+scbc.tools.cpp
+    这是主 DLL 源文件。
+
+	此 DLL 在创建时不导出任何符号。因此,在生成此 DLL 时
+	将不会产生 .lib 文件。如果希望此项目
+	成为其他某个项目的项目依赖项,则需要
+	添加代码以从 DLL 导出某些符号,
+	以便产生一个导出库,或者,也可以在项目“属性页”对话框中的
+	“链接器”文件夹中,将“常规”属性页上的
+	“忽略输入库”属性设置为“是”。
+
+/////////////////////////////////////////////////////////////////////////////
+应用程序向导创建了下列资源:
+
+scbc.tools.rc
+这是程序使用的所有 Microsoft Windows 资源的列表。它包括 RES 子目录中存储的图标、位图和光标。
+此文件可以直接在 Microsoft Visual C++ 中进行编辑。
+
+Resource.h
+    这是标准头文件,可用于定义新的资源 ID。
+    Microsoft Visual C++ 将读取并更新此文件。
+
+/////////////////////////////////////////////////////////////////////////////
+其他标准文件:
+
+StdAfx.h, StdAfx.cpp
+    这些文件用于生成名为 scbc.tools.pch 的预编译头 (PCH) 文件和名为 StdAfx.obj 的预编译类型文件。
+
+/////////////////////////////////////////////////////////////////////////////
+其他注释:
+
+应用程序向导使用“TODO:”注释来指示应添加或自定义的源代码部分。
+
+/////////////////////////////////////////////////////////////////////////////

+ 17 - 0
scbc.tools/scbc.tools/Resource.h

@@ -0,0 +1,17 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by scbc.tools.rc
+//
+
+#define IDS_APP_TITLE			103
+
+// жÔÏóµÄÏÂÒ»×éĬÈÏÖµ
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE	101
+#define _APS_NEXT_COMMAND_VALUE		40001
+#define _APS_NEXT_CONTROL_VALUE		1000
+#define _APS_NEXT_SYMED_VALUE		101
+#endif
+#endif

+ 27 - 0
scbc.tools/scbc.tools/log4c.h

@@ -0,0 +1,27 @@
+/* $Id$
+ *
+ * log4c.h
+ *
+ * Copyright 2001-2002, Meiosys (www.meiosys.com). All rights reserved.
+ *
+ * See the COPYING file for the terms of usage and distribution.
+ */
+
+#ifndef log4c_log4c_h
+#define log4c_log4c_h
+
+#define IMPLEMENT_LOG4C
+
+#include <log4c/version.h>
+#include <log4c/init.h>
+#include <log4c/rc.h>
+#include <log4c/appender.h>
+#include <log4c/rollingpolicy.h>
+#include <log4c/category.h>
+#include <log4c/layout.h>
+#include <log4c/logging_event.h>
+#include <log4c/priority.h>
+#include <log4c/log.h>
+
+#endif
+

+ 45 - 0
scbc.tools/scbc.tools/scbc.tools.cpp

@@ -0,0 +1,45 @@
+// scbc.tools.cpp : 定义 DLL 应用程序的导出函数。
+//
+
+#include "stdafx.h"
+#include "scbc.tools.h"
+#include "CurlClient.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#endif
+
+
+// 唯一的应用程序对象
+
+CWinApp theApp;
+
+using namespace std;
+
+int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
+{
+	int nRetCode = 0;
+
+	// 初始化 MFC 并在失败时显示错误
+	if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
+	{
+		// TODO: 更改错误代码以符合您的需要
+		_tprintf(_T("错误: MFC 初始化失败\n"));
+		nRetCode = 1;
+	}
+	else
+	{
+		// TODO: 在此处为应用程序的行为编写代码。
+		std::string data;
+		CCurlClient curl;
+		curl.Initialize();
+		if ( curl.DownloadEx("https://dldir1.qq.com/weixin/Windows/WeChatSetup.exe", "D:\\WeChatSetup.exe", 5000) )
+			printf("下载成功\n");
+		else
+			printf("下载失败\n");
+
+		system("pause");
+	}
+
+	return nRetCode;
+}

+ 27 - 0
scbc.tools/scbc.tools/scbc.tools.h

@@ -0,0 +1,27 @@
+// 下列 ifdef 块是创建使从 DLL 导出更简单的
+// 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 SCBCTOOLS_EXPORTS
+// 符号编译的。在使用此 DLL 的
+// 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将
+// SCBCTOOLS_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的
+// 符号视为是被导出的。
+#ifdef SCBCTOOLS_EXPORTS
+#define SCBCTOOLS_API __declspec(dllexport)
+#else
+#define SCBCTOOLS_API __declspec(dllimport)
+#endif
+
+// 此类是从 scbc.tools.dll 导出的
+class SCBCTOOLS_API Cscbctools {
+public:
+	Cscbctools(void);
+	// TODO: 在此添加您的方法。
+};
+
+extern SCBCTOOLS_API int nscbctools;
+
+SCBCTOOLS_API int fnscbctools(void);
+
+// 判断mid数据是否已下载;
+extern "C" bool is_data_down();
+// 下载批次MID数据;
+extern "C" int get_mid_data(const char* lpOrder);

+ 69 - 0
scbc.tools/scbc.tools/scbc.tools.rc

@@ -0,0 +1,69 @@
+//Microsoft Visual C++ 生成的资源脚本。
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// 从 TEXTINCLUDE 2 资源生成。
+//
+#include "afxres.h"
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
+LANGUAGE 4, 2
+#pragma code_page(936)
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+    "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+    "#include ""afxres.h""\r\n"
+    "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+    "\r\n"
+    "\0"
+END
+
+#endif    // APSTUDIO_INVOKED
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// 字符串表
+//
+
+STRINGTABLE
+BEGIN
+   IDS_APP_TITLE       "scbc.tools"
+END
+
+#endif
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// 从 TEXTINCLUDE 3 资源生成。
+//
+#ifndef _AFXDLL
+#include "l.CHS\\afxres.rc"
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // 不是 APSTUDIO_INVOKED

+ 408 - 0
scbc.tools/scbc.tools/scbc.tools.vcproj

@@ -0,0 +1,408 @@
+<?xml version="1.0" encoding="gb2312"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9.00"
+	Name="scbc.tools"
+	ProjectGUID="{95CA9F08-85F6-4FD6-A80D-15EEC854B118}"
+	RootNamespace="scbctools"
+	Keyword="Win32Proj"
+	TargetFrameworkVersion="196613"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="..\..\bin\$(ProjectName)"
+			IntermediateDirectory="$(OutDir)\$(ConfigurationName)"
+			ConfigurationType="2"
+			UseOfMFC="2"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\cJson;..\filehelper;..\Include;..\Log4C"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;SCBCTOOLS_EXPORTS;LOG4C_ENABLE;CURL_STATICLIB"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="crypt32.lib ws2_32.lib winmm.lib wldap32.lib log4C.lib libcurld.lib libeay32.lib ssleay32.lib"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="..\lib"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="..\..\bin\$(ProjectName)"
+			IntermediateDirectory="$(OutDir)\$(ConfigurationName)"
+			ConfigurationType="2"
+			UseOfMFC="2"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				EnableIntrinsicFunctions="true"
+				AdditionalIncludeDirectories="..\cJson;..\filehelper;..\Include;..\Log4C"
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;SCBCTOOLS_EXPORTS;LOG4C_ENABLE;CURL_STATICLIB"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="crypt32.lib ws2_32.lib winmm.lib wldap32.lib log4C.lib libcurl.lib libeay32.lib ssleay32.lib"
+				LinkIncremental="1"
+				AdditionalLibraryDirectories="..\lib"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="DebugExe|Win32"
+			OutputDirectory="..\..\bin\$(ProjectName)"
+			IntermediateDirectory="$(OutDir)\$(ConfigurationName)"
+			ConfigurationType="1"
+			UseOfMFC="2"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\cJson;..\filehelper;..\Include;..\Log4C"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;SCBCTOOLS_EXPORTS;LOG4C_ENABLE;CURL_STATICLIB"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="crypt32.lib ws2_32.lib winmm.lib wldap32.lib log4C.lib libcurld.lib libeay32.lib ssleay32.lib"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="..\lib"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Ô´Îļþ"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath=".\scbc.tools.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\stdafx.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="DebugExe|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
+			</File>
+		</Filter>
+		<Filter
+			Name="Í·Îļþ"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath=".\log4c.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Resource.h"
+				>
+			</File>
+			<File
+				RelativePath=".\scbc.tools.h"
+				>
+			</File>
+			<File
+				RelativePath=".\stdafx.h"
+				>
+			</File>
+			<File
+				RelativePath=".\targetver.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="×ÊÔ´Îļþ"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+			<File
+				RelativePath=".\scbc.tools.rc"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="curlib"
+			>
+			<File
+				RelativePath=".\Base64.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\Base64.h"
+				>
+			</File>
+			<File
+				RelativePath=".\CharConvert.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\CharConvert.h"
+				>
+			</File>
+			<File
+				RelativePath=".\CharEncoding.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\CharEncoding.h"
+				>
+			</File>
+			<File
+				RelativePath=".\CritSection.h"
+				>
+			</File>
+			<File
+				RelativePath=".\CurlClient.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\CurlClient.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="tinyxml2"
+			>
+			<File
+				RelativePath=".\tinyxml2.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="0"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="0"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="DebugExe|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="0"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\tinyxml2.h"
+				>
+			</File>
+		</Filter>
+		<File
+			RelativePath=".\ReadMe.txt"
+			>
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>

+ 8 - 0
scbc.tools/scbc.tools/stdafx.cpp

@@ -0,0 +1,8 @@
+// stdafx.cpp : 只包括标准包含文件的源文件
+// scbc.tools.pch 将作为预编译头
+// stdafx.obj 将包含预编译类型信息
+
+#include "stdafx.h"
+
+// TODO: 在 STDAFX.H 中
+// 引用任何所需的附加头文件,而不是在此文件中引用

+ 34 - 0
scbc.tools/scbc.tools/stdafx.h

@@ -0,0 +1,34 @@
+// stdafx.h : 标准系统包含文件的包含文件,
+// 或是经常使用但不常更改的
+// 特定于项目的包含文件
+//
+
+#pragma once
+
+#include "targetver.h"
+
+#define WIN32_LEAN_AND_MEAN             // 从 Windows 头中排除极少使用的资料
+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS      // 某些 CString 构造函数将是显式的
+
+#ifndef VC_EXTRALEAN
+#define VC_EXTRALEAN            // 从 Windows 头中排除极少使用的资料
+#endif
+
+#include <afx.h>
+#include <afxwin.h>         // MFC 核心组件和标准组件
+#include <afxext.h>         // MFC 扩展
+#ifndef _AFX_NO_OLE_SUPPORT
+#include <afxdtctl.h>           // MFC 对 Internet Explorer 4 公共控件的支持
+#endif
+#ifndef _AFX_NO_AFXCMN_SUPPORT
+#include <afxcmn.h>                     // MFC 对 Windows 公共控件的支持
+#endif // _AFX_NO_AFXCMN_SUPPORT
+
+#include <iostream>
+// Windows 头文件:
+#include <windows.h>
+
+// log4c头文件;
+#include "log4c.h"
+
+// TODO: 在此处引用程序需要的其他头文件

+ 259 - 0
scbc.tools/scbc.tools/stdint.h

@@ -0,0 +1,259 @@
+// ISO C9x  compliant stdint.h for Microsoft Visual Studio
+// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 
+// 
+//  Copyright (c) 2006-2013 Alexander Chemeris
+// 
+// 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. Neither the name of the product nor the names of its contributors may
+//      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.
+// 
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _MSC_VER // [
+#error "Use this header only with Microsoft Visual C++ compilers!"
+#endif // _MSC_VER ]
+
+#ifndef _MSC_STDINT_H_ // [
+#define _MSC_STDINT_H_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+#if _MSC_VER >= 2000 // [
+#include <stdint.h>
+#else // ] _MSC_VER >= 1600 [
+
+#include <limits.h>
+
+// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
+// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
+// or compiler give many errors like this:
+//   error C2733: second C linkage of overloaded function 'wmemchr' not allowed
+#ifdef __cplusplus
+extern "C" {
+#endif
+#  include <wchar.h>
+#ifdef __cplusplus
+}
+#endif
+
+// Define _W64 macros to mark types changing their size, like intptr_t.
+#ifndef _W64
+#  if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
+#     define _W64 __w64
+#  else
+#     define _W64
+#  endif
+#endif
+
+
+// 7.18.1 Integer types
+
+// 7.18.1.1 Exact-width integer types
+
+// Visual Studio 6 and Embedded Visual C++ 4 doesn't
+// realize that, e.g. char has the same size as __int8
+// so we give up on __intX for them.
+#if (_MSC_VER < 1300)
+   typedef signed char       int8_t;
+   typedef signed short      int16_t;
+   typedef signed int        int32_t;
+   typedef unsigned char     uint8_t;
+   typedef unsigned short    uint16_t;
+   typedef unsigned int      uint32_t;
+#else
+   typedef signed __int8     int8_t;
+   typedef signed __int16    int16_t;
+   typedef signed __int32    int32_t;
+   typedef unsigned __int8   uint8_t;
+   typedef unsigned __int16  uint16_t;
+   typedef unsigned __int32  uint32_t;
+#endif
+typedef signed __int64       int64_t;
+typedef unsigned __int64     uint64_t;
+
+
+// 7.18.1.2 Minimum-width integer types
+typedef int8_t    int_least8_t;
+typedef int16_t   int_least16_t;
+typedef int32_t   int_least32_t;
+typedef int64_t   int_least64_t;
+typedef uint8_t   uint_least8_t;
+typedef uint16_t  uint_least16_t;
+typedef uint32_t  uint_least32_t;
+typedef uint64_t  uint_least64_t;
+
+// 7.18.1.3 Fastest minimum-width integer types
+typedef int8_t    int_fast8_t;
+typedef int16_t   int_fast16_t;
+typedef int32_t   int_fast32_t;
+typedef int64_t   int_fast64_t;
+typedef uint8_t   uint_fast8_t;
+typedef uint16_t  uint_fast16_t;
+typedef uint32_t  uint_fast32_t;
+typedef uint64_t  uint_fast64_t;
+
+// 7.18.1.4 Integer types capable of holding object pointers
+#ifdef _WIN64 // [
+   typedef signed __int64    intptr_t;
+   typedef unsigned __int64  uintptr_t;
+#else // _WIN64 ][
+   typedef _W64 signed int   intptr_t;
+   typedef _W64 unsigned int uintptr_t;
+#endif // _WIN64 ]
+
+// 7.18.1.5 Greatest-width integer types
+typedef int64_t   intmax_t;
+typedef uint64_t  uintmax_t;
+
+
+// 7.18.2 Limits of specified-width integer types
+
+#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [   See footnote 220 at page 257 and footnote 221 at page 259
+
+// 7.18.2.1 Limits of exact-width integer types
+#define INT8_MIN     ((int8_t)_I8_MIN)
+#define INT8_MAX     _I8_MAX
+#define INT16_MIN    ((int16_t)_I16_MIN)
+#define INT16_MAX    _I16_MAX
+#define INT32_MIN    ((int32_t)_I32_MIN)
+#define INT32_MAX    _I32_MAX
+#define INT64_MIN    ((int64_t)_I64_MIN)
+#define INT64_MAX    _I64_MAX
+#define UINT8_MAX    _UI8_MAX
+#define UINT16_MAX   _UI16_MAX
+#define UINT32_MAX   _UI32_MAX
+#define UINT64_MAX   _UI64_MAX
+
+// 7.18.2.2 Limits of minimum-width integer types
+#define INT_LEAST8_MIN    INT8_MIN
+#define INT_LEAST8_MAX    INT8_MAX
+#define INT_LEAST16_MIN   INT16_MIN
+#define INT_LEAST16_MAX   INT16_MAX
+#define INT_LEAST32_MIN   INT32_MIN
+#define INT_LEAST32_MAX   INT32_MAX
+#define INT_LEAST64_MIN   INT64_MIN
+#define INT_LEAST64_MAX   INT64_MAX
+#define UINT_LEAST8_MAX   UINT8_MAX
+#define UINT_LEAST16_MAX  UINT16_MAX
+#define UINT_LEAST32_MAX  UINT32_MAX
+#define UINT_LEAST64_MAX  UINT64_MAX
+
+// 7.18.2.3 Limits of fastest minimum-width integer types
+#define INT_FAST8_MIN    INT8_MIN
+#define INT_FAST8_MAX    INT8_MAX
+#define INT_FAST16_MIN   INT16_MIN
+#define INT_FAST16_MAX   INT16_MAX
+#define INT_FAST32_MIN   INT32_MIN
+#define INT_FAST32_MAX   INT32_MAX
+#define INT_FAST64_MIN   INT64_MIN
+#define INT_FAST64_MAX   INT64_MAX
+#define UINT_FAST8_MAX   UINT8_MAX
+#define UINT_FAST16_MAX  UINT16_MAX
+#define UINT_FAST32_MAX  UINT32_MAX
+#define UINT_FAST64_MAX  UINT64_MAX
+
+// 7.18.2.4 Limits of integer types capable of holding object pointers
+#ifdef _WIN64 // [
+#  define INTPTR_MIN   INT64_MIN
+#  define INTPTR_MAX   INT64_MAX
+#  define UINTPTR_MAX  UINT64_MAX
+#else // _WIN64 ][
+#  define INTPTR_MIN   INT32_MIN
+#  define INTPTR_MAX   INT32_MAX
+#  define UINTPTR_MAX  UINT32_MAX
+#endif // _WIN64 ]
+
+// 7.18.2.5 Limits of greatest-width integer types
+#define INTMAX_MIN   INT64_MIN
+#define INTMAX_MAX   INT64_MAX
+#define UINTMAX_MAX  UINT64_MAX
+
+// 7.18.3 Limits of other integer types
+
+#ifdef _WIN64 // [
+#  define PTRDIFF_MIN  _I64_MIN
+#  define PTRDIFF_MAX  _I64_MAX
+#else  // _WIN64 ][
+#  define PTRDIFF_MIN  _I32_MIN
+#  define PTRDIFF_MAX  _I32_MAX
+#endif  // _WIN64 ]
+
+#define SIG_ATOMIC_MIN  INT_MIN
+#define SIG_ATOMIC_MAX  INT_MAX
+
+#ifndef SIZE_MAX // [
+#  ifdef _WIN64 // [
+#     define SIZE_MAX  _UI64_MAX
+#  else // _WIN64 ][
+#     define SIZE_MAX  _UI32_MAX
+#  endif // _WIN64 ]
+#endif // SIZE_MAX ]
+
+// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
+#ifndef WCHAR_MIN // [
+#  define WCHAR_MIN  0
+#endif  // WCHAR_MIN ]
+#ifndef WCHAR_MAX // [
+#  define WCHAR_MAX  _UI16_MAX
+#endif  // WCHAR_MAX ]
+
+#define WINT_MIN  0
+#define WINT_MAX  _UI16_MAX
+
+#endif // __STDC_LIMIT_MACROS ]
+
+
+// 7.18.4 Limits of other integer types
+
+#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [   See footnote 224 at page 260
+
+// 7.18.4.1 Macros for minimum-width integer constants
+
+#define INT8_C(val)  val##i8
+#define INT16_C(val) val##i16
+#define INT32_C(val) val##i32
+#define INT64_C(val) val##i64
+
+#define UINT8_C(val)  val##ui8
+#define UINT16_C(val) val##ui16
+#define UINT32_C(val) val##ui32
+#define UINT64_C(val) val##ui64
+
+// 7.18.4.2 Macros for greatest-width integer constants
+// These #ifndef's are needed to prevent collisions with <boost/cstdint.hpp>.
+// Check out Issue 9 for the details.
+#ifndef INTMAX_C //   [
+#  define INTMAX_C   INT64_C
+#endif // INTMAX_C    ]
+#ifndef UINTMAX_C //  [
+#  define UINTMAX_C  UINT64_C
+#endif // UINTMAX_C   ]
+
+#endif // __STDC_CONSTANT_MACROS ]
+
+#endif // _MSC_VER >= 1600 ]
+
+#endif // _MSC_STDINT_H_ ]

+ 24 - 0
scbc.tools/scbc.tools/targetver.h

@@ -0,0 +1,24 @@
+#pragma once
+
+// 以下宏定义要求的最低平台。要求的最低平台
+// 是具有运行应用程序所需功能的 Windows、Internet Explorer 等产品的
+// 最早版本。通过在指定版本及更低版本的平台上启用所有可用的功能,宏可以
+// 正常工作。
+
+// 如果必须要针对低于以下指定版本的平台,请修改下列定义。
+// 有关不同平台对应值的最新信息,请参考 MSDN。
+#ifndef WINVER                          // 指定要求的最低平台是 Windows Vista。
+#define WINVER 0x0600           // 将此值更改为相应的值,以适用于 Windows 的其他版本。
+#endif
+
+#ifndef _WIN32_WINNT            // 指定要求的最低平台是 Windows Vista。
+#define _WIN32_WINNT 0x0600     // 将此值更改为相应的值,以适用于 Windows 的其他版本。
+#endif
+
+#ifndef _WIN32_WINDOWS          // 指定要求的最低平台是 Windows 98。
+#define _WIN32_WINDOWS 0x0410 // 将此值更改为适当的值,以适用于 Windows Me 或更高版本。
+#endif
+
+#ifndef _WIN32_IE                       // 指定要求的最低平台是 Internet Explorer 7.0。
+#define _WIN32_IE 0x0700        // 将此值更改为相应的值,以适用于 IE 的其他版本。
+#endif

Деякі файли не було показано, через те що забагато файлів було змінено