]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #1006 in SNORT/snort3 from smb_unicode_fname to master
authorRuss Combs (rucombs) <rucombs@cisco.com>
Fri, 22 Sep 2017 13:41:28 +0000 (09:41 -0400)
committerRuss Combs (rucombs) <rucombs@cisco.com>
Fri, 22 Sep 2017 13:41:28 +0000 (09:41 -0400)
Squashed commit of the following:

commit aec151308a6b538db68baddeec1a09b956849993
Author: snorty <mdagon@cisco.com>
Date:   Wed Sep 20 17:40:48 2017 -0400

    Missed 2 files

commit 31c622a7fba16becbf5f6b24ce490e4a36cecb78
Author: snorty <mdagon@cisco.com>
Date:   Tue Sep 19 15:19:46 2017 -0400

    Additional changes from Michael's branch - cmake changes for iconv + additional improvements

commit 3758b4d8604c1b1fafce1138942b8f8f20c58ec3
Author: Michael Altizer <mialtize@cisco.com>
Date:   Fri Sep 15 14:47:57 2017 -0400

    build: Import iconv autotools logic from gnulib

commit ef23d1dabc7326091010988a6e0aa0cb936bcc5f
Author: mdagon <mdagon@cisco.com>
Date:   Mon Jul 24 10:29:15 2017 -0400

    SMB unicode filename support

    1. iconv is used for translating UTF16-LE file names to UTF8.
    2. Smb will add BOM to file name in case it is Unicode.
    3. Translation will be done in file_api during logging.
    4. Active response was updated to keep the same format of the original file name.
    5. File api was updated to use pipe-delimited hex for file names:
       printable text will show up as plain text and any 8-bit chars as hex
    6. Full file name, including path, will be logged, instead of only the file name
    7. NHI will send raw uri instead of normalized uri to file api

29 files changed:
build-aux/config.rpath [new file with mode: 0755]
cmake/FindICONV.cmake [new file with mode: 0644]
cmake/create_pkg_config.cmake
cmake/include_libraries.cmake
cmake/sanity_checks.cmake
config.cmake.h.in
configure.ac
doc/building.txt
doc/tutorial.txt
extra/configure.ac
m4/iconv.m4 [new file with mode: 0644]
m4/lib-ld.m4 [new file with mode: 0644]
m4/lib-link.m4 [new file with mode: 0644]
m4/lib-prefix.m4 [new file with mode: 0644]
src/CMakeLists.txt
src/file_api/file_api.h
src/file_api/file_lib.cc
src/file_api/file_lib.h
src/file_api/file_log.cc
src/service_inspectors/dce_rpc/dce_smb.h
src/service_inspectors/dce_rpc/dce_smb2.cc
src/service_inspectors/dce_rpc/dce_smb_commands.cc
src/service_inspectors/dce_rpc/dce_smb_transaction.cc
src/service_inspectors/dce_rpc/dce_smb_utils.cc
src/service_inspectors/dce_rpc/dce_smb_utils.h
src/service_inspectors/http_inspect/http_msg_body.cc
src/utils/util.cc
src/utils/util_utf.cc
src/utils/util_utf.h

diff --git a/build-aux/config.rpath b/build-aux/config.rpath
new file mode 100755 (executable)
index 0000000..af3c415
--- /dev/null
@@ -0,0 +1,684 @@
+#! /bin/sh
+# Output a system dependent set of variables, describing how to set the
+# run time search path of shared libraries in an executable.
+#
+#   Copyright 1996-2017 Free Software Foundation, Inc.
+#   Taken from GNU libtool, 2001
+#   Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+#   This file 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.
+#
+# The first argument passed to this file is the canonical host specification,
+#    CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or
+#    CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# The environment variables CC, GCC, LDFLAGS, LD, with_gnu_ld
+# should be set by the caller.
+#
+# The set of defined variables is at the end of this script.
+
+# Known limitations:
+# - On IRIX 6.5 with CC="cc", the run time search patch must not be longer
+#   than 256 bytes, otherwise the compiler driver will dump core. The only
+#   known workaround is to choose shorter directory names for the build
+#   directory and/or the installation directory.
+
+# All known linkers require a '.a' archive for static linking (except MSVC,
+# which needs '.lib').
+libext=a
+shrext=.so
+
+host="$1"
+host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+# Code taken from libtool.m4's _LT_CC_BASENAME.
+
+for cc_temp in $CC""; do
+  case $cc_temp in
+    compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+    distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+    \-*) ;;
+    *) break;;
+  esac
+done
+cc_basename=`echo "$cc_temp" | sed -e 's%^.*/%%'`
+
+# Code taken from libtool.m4's _LT_COMPILER_PIC.
+
+wl=
+if test "$GCC" = yes; then
+  wl='-Wl,'
+else
+  case "$host_os" in
+    aix*)
+      wl='-Wl,'
+      ;;
+    mingw* | cygwin* | pw32* | os2* | cegcc*)
+      ;;
+    hpux9* | hpux10* | hpux11*)
+      wl='-Wl,'
+      ;;
+    irix5* | irix6* | nonstopux*)
+      wl='-Wl,'
+      ;;
+    linux* | k*bsd*-gnu | kopensolaris*-gnu)
+      case $cc_basename in
+        ecc*)
+          wl='-Wl,'
+          ;;
+        icc* | ifort*)
+          wl='-Wl,'
+          ;;
+        lf95*)
+          wl='-Wl,'
+          ;;
+        nagfor*)
+          wl='-Wl,-Wl,,'
+          ;;
+        pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
+          wl='-Wl,'
+          ;;
+        ccc*)
+          wl='-Wl,'
+          ;;
+        xl* | bgxl* | bgf* | mpixl*)
+          wl='-Wl,'
+          ;;
+        como)
+          wl='-lopt='
+          ;;
+        *)
+          case `$CC -V 2>&1 | sed 5q` in
+            *Sun\ F* | *Sun*Fortran*)
+              wl=
+              ;;
+            *Sun\ C*)
+              wl='-Wl,'
+              ;;
+          esac
+          ;;
+      esac
+      ;;
+    newsos6)
+      ;;
+    *nto* | *qnx*)
+      ;;
+    osf3* | osf4* | osf5*)
+      wl='-Wl,'
+      ;;
+    rdos*)
+      ;;
+    solaris*)
+      case $cc_basename in
+        f77* | f90* | f95* | sunf77* | sunf90* | sunf95*)
+          wl='-Qoption ld '
+          ;;
+        *)
+          wl='-Wl,'
+          ;;
+      esac
+      ;;
+    sunos4*)
+      wl='-Qoption ld '
+      ;;
+    sysv4 | sysv4.2uw2* | sysv4.3*)
+      wl='-Wl,'
+      ;;
+    sysv4*MP*)
+      ;;
+    sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+      wl='-Wl,'
+      ;;
+    unicos*)
+      wl='-Wl,'
+      ;;
+    uts4*)
+      ;;
+  esac
+fi
+
+# Code taken from libtool.m4's _LT_LINKER_SHLIBS.
+
+hardcode_libdir_flag_spec=
+hardcode_libdir_separator=
+hardcode_direct=no
+hardcode_minus_L=no
+
+case "$host_os" in
+  cygwin* | mingw* | pw32* | cegcc*)
+    # FIXME: the MSVC++ port hasn't been tested in a loooong time
+    # When not using gcc, we currently assume that we are using
+    # Microsoft Visual C++.
+    if test "$GCC" != yes; then
+      with_gnu_ld=no
+    fi
+    ;;
+  interix*)
+    # we just hope/assume this is gcc and not c89 (= MSVC++)
+    with_gnu_ld=yes
+    ;;
+  openbsd*)
+    with_gnu_ld=no
+    ;;
+esac
+
+ld_shlibs=yes
+if test "$with_gnu_ld" = yes; then
+  # Set some defaults for GNU ld with shared library support. These
+  # are reset later if shared libraries are not supported. Putting them
+  # here allows them to be overridden if necessary.
+  # Unlike libtool, we use -rpath here, not --rpath, since the documented
+  # option of GNU ld is called -rpath, not --rpath.
+  hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+  case "$host_os" in
+    aix[3-9]*)
+      # On AIX/PPC, the GNU linker is very broken
+      if test "$host_cpu" != ia64; then
+        ld_shlibs=no
+      fi
+      ;;
+    amigaos*)
+      case "$host_cpu" in
+        powerpc)
+          ;;
+        m68k)
+          hardcode_libdir_flag_spec='-L$libdir'
+          hardcode_minus_L=yes
+          ;;
+      esac
+      ;;
+    beos*)
+      if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+        :
+      else
+        ld_shlibs=no
+      fi
+      ;;
+    cygwin* | mingw* | pw32* | cegcc*)
+      # hardcode_libdir_flag_spec is actually meaningless, as there is
+      # no search path for DLLs.
+      hardcode_libdir_flag_spec='-L$libdir'
+      if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+        :
+      else
+        ld_shlibs=no
+      fi
+      ;;
+    haiku*)
+      ;;
+    interix[3-9]*)
+      hardcode_direct=no
+      hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+      ;;
+    gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
+      if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+        :
+      else
+        ld_shlibs=no
+      fi
+      ;;
+    netbsd*)
+      ;;
+    solaris*)
+      if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
+        ld_shlibs=no
+      elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+        :
+      else
+        ld_shlibs=no
+      fi
+      ;;
+    sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+      case `$LD -v 2>&1` in
+        *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
+          ld_shlibs=no
+          ;;
+        *)
+          if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+            hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
+          else
+            ld_shlibs=no
+          fi
+          ;;
+      esac
+      ;;
+    sunos4*)
+      hardcode_direct=yes
+      ;;
+    *)
+      if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+        :
+      else
+        ld_shlibs=no
+      fi
+      ;;
+  esac
+  if test "$ld_shlibs" = no; then
+    hardcode_libdir_flag_spec=
+  fi
+else
+  case "$host_os" in
+    aix3*)
+      # Note: this linker hardcodes the directories in LIBPATH if there
+      # are no directories specified by -L.
+      hardcode_minus_L=yes
+      if test "$GCC" = yes; then
+        # Neither direct hardcoding nor static linking is supported with a
+        # broken collect2.
+        hardcode_direct=unsupported
+      fi
+      ;;
+    aix[4-9]*)
+      if test "$host_cpu" = ia64; then
+        # On IA64, the linker does run time linking by default, so we don't
+        # have to do anything special.
+        aix_use_runtimelinking=no
+      else
+        aix_use_runtimelinking=no
+        # Test if we are trying to use run time linking or normal
+        # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+        # need to do runtime linking.
+        case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*)
+          for ld_flag in $LDFLAGS; do
+            if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+              aix_use_runtimelinking=yes
+              break
+            fi
+          done
+          ;;
+        esac
+      fi
+      hardcode_direct=yes
+      hardcode_libdir_separator=':'
+      if test "$GCC" = yes; then
+        case $host_os in aix4.[012]|aix4.[012].*)
+          collect2name=`${CC} -print-prog-name=collect2`
+          if test -f "$collect2name" && \
+            strings "$collect2name" | grep resolve_lib_name >/dev/null
+          then
+            # We have reworked collect2
+            :
+          else
+            # We have old collect2
+            hardcode_direct=unsupported
+            hardcode_minus_L=yes
+            hardcode_libdir_flag_spec='-L$libdir'
+            hardcode_libdir_separator=
+          fi
+          ;;
+        esac
+      fi
+      # Begin _LT_AC_SYS_LIBPATH_AIX.
+      echo 'int main () { return 0; }' > conftest.c
+      ${CC} ${LDFLAGS} conftest.c -o conftest
+      aix_libpath=`dump -H conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0  *\(.*\)$/\1/; p; }
+}'`
+      if test -z "$aix_libpath"; then
+        aix_libpath=`dump -HX64 conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0  *\(.*\)$/\1/; p; }
+}'`
+      fi
+      if test -z "$aix_libpath"; then
+        aix_libpath="/usr/lib:/lib"
+      fi
+      rm -f conftest.c conftest
+      # End _LT_AC_SYS_LIBPATH_AIX.
+      if test "$aix_use_runtimelinking" = yes; then
+        hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+      else
+        if test "$host_cpu" = ia64; then
+          hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
+        else
+          hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+        fi
+      fi
+      ;;
+    amigaos*)
+      case "$host_cpu" in
+        powerpc)
+          ;;
+        m68k)
+          hardcode_libdir_flag_spec='-L$libdir'
+          hardcode_minus_L=yes
+          ;;
+      esac
+      ;;
+    bsdi[45]*)
+      ;;
+    cygwin* | mingw* | pw32* | cegcc*)
+      # When not using gcc, we currently assume that we are using
+      # Microsoft Visual C++.
+      # hardcode_libdir_flag_spec is actually meaningless, as there is
+      # no search path for DLLs.
+      hardcode_libdir_flag_spec=' '
+      libext=lib
+      ;;
+    darwin* | rhapsody*)
+      hardcode_direct=no
+      if { case $cc_basename in ifort*) true;; *) test "$GCC" = yes;; esac; }; then
+        :
+      else
+        ld_shlibs=no
+      fi
+      ;;
+    dgux*)
+      hardcode_libdir_flag_spec='-L$libdir'
+      ;;
+    freebsd2.[01]*)
+      hardcode_direct=yes
+      hardcode_minus_L=yes
+      ;;
+    freebsd* | dragonfly*)
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      ;;
+    hpux9*)
+      hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+      hardcode_libdir_separator=:
+      hardcode_direct=yes
+      # hardcode_minus_L: Not really in the search PATH,
+      # but as the default location of the library.
+      hardcode_minus_L=yes
+      ;;
+    hpux10*)
+      if test "$with_gnu_ld" = no; then
+        hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+        hardcode_libdir_separator=:
+        hardcode_direct=yes
+        # hardcode_minus_L: Not really in the search PATH,
+        # but as the default location of the library.
+        hardcode_minus_L=yes
+      fi
+      ;;
+    hpux11*)
+      if test "$with_gnu_ld" = no; then
+        hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+        hardcode_libdir_separator=:
+        case $host_cpu in
+          hppa*64*|ia64*)
+            hardcode_direct=no
+            ;;
+          *)
+            hardcode_direct=yes
+            # hardcode_minus_L: Not really in the search PATH,
+            # but as the default location of the library.
+            hardcode_minus_L=yes
+            ;;
+        esac
+      fi
+      ;;
+    irix5* | irix6* | nonstopux*)
+      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator=:
+      ;;
+    netbsd*)
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      ;;
+    newsos6)
+      hardcode_direct=yes
+      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator=:
+      ;;
+    *nto* | *qnx*)
+      ;;
+    openbsd*)
+      if test -f /usr/libexec/ld.so; then
+        hardcode_direct=yes
+        if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+          hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+        else
+          case "$host_os" in
+            openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+              hardcode_libdir_flag_spec='-R$libdir'
+              ;;
+            *)
+              hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+              ;;
+          esac
+        fi
+      else
+        ld_shlibs=no
+      fi
+      ;;
+    os2*)
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_minus_L=yes
+      ;;
+    osf3*)
+      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator=:
+      ;;
+    osf4* | osf5*)
+      if test "$GCC" = yes; then
+        hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      else
+        # Both cc and cxx compiler support -rpath directly
+        hardcode_libdir_flag_spec='-rpath $libdir'
+      fi
+      hardcode_libdir_separator=:
+      ;;
+    solaris*)
+      hardcode_libdir_flag_spec='-R$libdir'
+      ;;
+    sunos4*)
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_direct=yes
+      hardcode_minus_L=yes
+      ;;
+    sysv4)
+      case $host_vendor in
+        sni)
+          hardcode_direct=yes # is this really true???
+          ;;
+        siemens)
+          hardcode_direct=no
+          ;;
+        motorola)
+          hardcode_direct=no #Motorola manual says yes, but my tests say they lie
+          ;;
+      esac
+      ;;
+    sysv4.3*)
+      ;;
+    sysv4*MP*)
+      if test -d /usr/nec; then
+        ld_shlibs=yes
+      fi
+      ;;
+    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
+      ;;
+    sysv5* | sco3.2v5* | sco5v6*)
+      hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+      hardcode_libdir_separator=':'
+      ;;
+    uts4*)
+      hardcode_libdir_flag_spec='-L$libdir'
+      ;;
+    *)
+      ld_shlibs=no
+      ;;
+  esac
+fi
+
+# Check dynamic linker characteristics
+# Code taken from libtool.m4's _LT_SYS_DYNAMIC_LINKER.
+# Unlike libtool.m4, here we don't care about _all_ names of the library, but
+# only about the one the linker finds when passed -lNAME. This is the last
+# element of library_names_spec in libtool.m4, or possibly two of them if the
+# linker has special search rules.
+library_names_spec=      # the last element of library_names_spec in libtool.m4
+libname_spec='lib$name'
+case "$host_os" in
+  aix3*)
+    library_names_spec='$libname.a'
+    ;;
+  aix[4-9]*)
+    library_names_spec='$libname$shrext'
+    ;;
+  amigaos*)
+    case "$host_cpu" in
+      powerpc*)
+        library_names_spec='$libname$shrext' ;;
+      m68k)
+        library_names_spec='$libname.a' ;;
+    esac
+    ;;
+  beos*)
+    library_names_spec='$libname$shrext'
+    ;;
+  bsdi[45]*)
+    library_names_spec='$libname$shrext'
+    ;;
+  cygwin* | mingw* | pw32* | cegcc*)
+    shrext=.dll
+    library_names_spec='$libname.dll.a $libname.lib'
+    ;;
+  darwin* | rhapsody*)
+    shrext=.dylib
+    library_names_spec='$libname$shrext'
+    ;;
+  dgux*)
+    library_names_spec='$libname$shrext'
+    ;;
+  freebsd[23].*)
+    library_names_spec='$libname$shrext$versuffix'
+    ;;
+  freebsd* | dragonfly*)
+    library_names_spec='$libname$shrext'
+    ;;
+  gnu*)
+    library_names_spec='$libname$shrext'
+    ;;
+  haiku*)
+    library_names_spec='$libname$shrext'
+    ;;
+  hpux9* | hpux10* | hpux11*)
+    case $host_cpu in
+      ia64*)
+        shrext=.so
+        ;;
+      hppa*64*)
+        shrext=.sl
+        ;;
+      *)
+        shrext=.sl
+        ;;
+    esac
+    library_names_spec='$libname$shrext'
+    ;;
+  interix[3-9]*)
+    library_names_spec='$libname$shrext'
+    ;;
+  irix5* | irix6* | nonstopux*)
+    library_names_spec='$libname$shrext'
+    case "$host_os" in
+      irix5* | nonstopux*)
+        libsuff= shlibsuff=
+        ;;
+      *)
+        case $LD in
+          *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= ;;
+          *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 ;;
+          *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 ;;
+          *) libsuff= shlibsuff= ;;
+        esac
+        ;;
+    esac
+    ;;
+  linux*oldld* | linux*aout* | linux*coff*)
+    ;;
+  linux* | k*bsd*-gnu | kopensolaris*-gnu)
+    library_names_spec='$libname$shrext'
+    ;;
+  knetbsd*-gnu)
+    library_names_spec='$libname$shrext'
+    ;;
+  netbsd*)
+    library_names_spec='$libname$shrext'
+    ;;
+  newsos6)
+    library_names_spec='$libname$shrext'
+    ;;
+  *nto* | *qnx*)
+    library_names_spec='$libname$shrext'
+    ;;
+  openbsd*)
+    library_names_spec='$libname$shrext$versuffix'
+    ;;
+  os2*)
+    libname_spec='$name'
+    shrext=.dll
+    library_names_spec='$libname.a'
+    ;;
+  osf3* | osf4* | osf5*)
+    library_names_spec='$libname$shrext'
+    ;;
+  rdos*)
+    ;;
+  solaris*)
+    library_names_spec='$libname$shrext'
+    ;;
+  sunos4*)
+    library_names_spec='$libname$shrext$versuffix'
+    ;;
+  sysv4 | sysv4.3*)
+    library_names_spec='$libname$shrext'
+    ;;
+  sysv4*MP*)
+    library_names_spec='$libname$shrext'
+    ;;
+  sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+    library_names_spec='$libname$shrext'
+    ;;
+  tpf*)
+    library_names_spec='$libname$shrext'
+    ;;
+  uts4*)
+    library_names_spec='$libname$shrext'
+    ;;
+esac
+
+sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
+escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"`
+shlibext=`echo "$shrext" | sed -e 's,^\.,,'`
+escaped_libname_spec=`echo "X$libname_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
+escaped_library_names_spec=`echo "X$library_names_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
+escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
+
+LC_ALL=C sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' <<EOF
+
+# How to pass a linker flag through the compiler.
+wl="$escaped_wl"
+
+# Static library suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally "so").
+shlibext="$shlibext"
+
+# Format of library name prefix.
+libname_spec="$escaped_libname_spec"
+
+# Library names that the linker finds when passed -lNAME.
+library_names_spec="$escaped_library_names_spec"
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec="$escaped_hardcode_libdir_flag_spec"
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator="$hardcode_libdir_separator"
+
+# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct="$hardcode_direct"
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L="$hardcode_minus_L"
+
+EOF
diff --git a/cmake/FindICONV.cmake b/cmake/FindICONV.cmake
new file mode 100644 (file)
index 0000000..a30f1fd
--- /dev/null
@@ -0,0 +1,135 @@
+# vim:ts=4:sw=4:expandtab:autoindent:
+#
+# The MIT License
+#
+# Copyright (c) 2008, 2009 Flusspferd contributors (see "CONTRIBUTORS" or
+#                                      http://flusspferd.org/contributors.txt)
+#
+# 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.
+#
+
+Include(CheckFunctionExists)
+include(CheckCXXSourceCompiles)
+
+if(ICONV_INCLUDE_DIR)
+  set(ICONV_FIND_QUIETLY TRUE)
+endif()
+
+find_path(ICONV_INCLUDE_DIR iconv.h
+    HINTS
+    ${CMAKE_PREFIX_PATH}
+    ${ICONV_DIR}
+    $ENV{ICONV_DIR}
+    PATH_SUFFIXES include
+)
+
+if(NOT ICONV_INCLUDE_DIR STREQUAL "ICONV_INCLUDE_DIR-NOTFOUND")
+    set(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR})
+    check_function_exists(iconv_open ICONV_IN_GLIBC)
+endif()
+
+if(NOT ICONV_IN_GLIBC)
+    if (CMAKE_CL_64)
+        find_library(ICONV_LIBRARY
+            NAMES iconv64
+            HINTS
+            ${CMAKE_PREFIX_PATH}
+            ${ICONV_DIR}
+            $ENV{ICONV_DIR}
+            PATH_SUFFIXES lib64 lib
+            )
+    else()
+        find_library(ICONV_LIBRARY
+            NAMES iconv
+            HINTS
+            ${CMAKE_PREFIX_PATH}
+            ${ICONV_DIR}
+            $ENV{ICONV_DIR}
+            PATH_SUFFIXES lib64 lib
+            )
+    endif()
+    set(ICONV_TEST ${ICONV_LIBRARY})
+else()
+    set(ICONV_TEST "In glibc")
+endif()
+
+set(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR})
+set(CMAKE_REQUIRED_LIBRARIES ${ICONV_LIBRARY})
+
+if(MSVC_VERSION GREATER 1800)
+    set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} legacy_stdio_definitions.lib)
+endif()
+
+check_cxx_source_compiles(
+    "#include <iconv.h>
+     int main() {
+        iconv(iconv_t(-1), 0, 0, 0, 0);
+     }"
+    ICONV_COMPILES)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(ICONV DEFAULT_MSG ICONV_TEST ICONV_INCLUDE_DIR ICONV_COMPILES)
+
+if(ICONV_FOUND)
+  set(ICONV_LIBRARIES ${ICONV_LIBRARY})
+else(ICONV_FOUND)
+  set(ICONV_LIBRARIES)
+endif(ICONV_FOUND)
+
+if(ICONV_FOUND)
+    set(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR})
+    set(CMAKE_REQUIRED_LIBRARIES ${ICONV_LIBRARIES})
+
+    if(MSVC_VERSION GREATER 1800)
+        set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} legacy_stdio_definitions.lib)
+    endif()
+
+    if (NOT DEFINED ICONV_ACCEPTS_NONCONST_INPUT)
+        # Display a useful message first time we come through here
+        message(STATUS "One (and only one) of the ICONV_ACCEPTS_... tests must pass")
+    endif()
+    check_cxx_source_compiles(
+        "#include <iconv.h>
+         int main() {
+            char *p = 0;
+            iconv(iconv_t(-1), &p, 0, 0, 0);
+         }"
+        ICONV_ACCEPTS_NONCONST_INPUT)
+
+    check_cxx_source_compiles(
+        "#include <iconv.h>
+         int main() {
+            char const *p = 0;
+            iconv(iconv_t(-1), &p, 0, 0, 0);
+         }"
+        ICONV_ACCEPTS_CONST_INPUT)
+
+    if (ICONV_LIBRARY)
+        list(REMOVE_ITEM CMAKE_REQUIRED_LIBRARIES ${ICONV_LIBRARY})
+        list(REMOVE_DUPLICATES CMAKE_REQUIRED_LIBRARIES)
+    endif()
+endif()
+
+if(NOT ICONV_ACCEPTS_CONST_INPUT AND NOT ICONV_ACCEPTS_NONCONST_INPUT)
+  MESSAGE(FATAL_ERROR "Unable to determine iconv() signature")
+elseif(ICONV_ACCEPTS_CONST_INPUT AND ICONV_ACCEPTS_NONCONST_INPUT)
+  MESSAGE(FATAL_ERROR "Unable to determine iconv() signature - both test cases passed!")
+endif()
+
+mark_as_advanced(ICONV_LIBRARY ICONV_INCLUDE_DIR)
index cef8a3d7b33973031e8f742a81503bf87a4835e0..6f2333bcc7ea03dd83ad5b5bc295bfe089bdd961 100644 (file)
@@ -32,6 +32,10 @@ if(HWLOC_INCLUDE_DIR)
     set(HWLOC_CPPFLAGS "-I${HWLOC_INCLUDE_DIR}")
 endif()
 
+if(ICONV_INCLUDE_DIR)
+    set(ICONV_CPPFLAGS "-I${ICONV_INCLUDE_DIR}")
+endif()
+
 if(LUAJIT_INCLUDE_DIR)
     set(LUAJIT_CPPFLAGS "-I${LUAJIT_INCLUDE_DIR}")
 endif()
index 30e39deeea6a6b6cfbd0a9389668fedcbf9c5f5a..fd6cfb214d8c13fa425e3b291a72e3c40b2f5a27 100644 (file)
@@ -22,3 +22,4 @@ find_package(Ruby QUIET 1.8.7)
 find_package(HS QUIET 4.4.0)
 find_package(SafeC QUIET)
 find_package(Flatbuffers QUIET)
+find_package(ICONV QUIET)
index ea93ce6ac128b6a261c949dd02d062ac90295014..be515991996f86dd2ca151bfbd2e98cbf7388091 100644 (file)
@@ -183,3 +183,8 @@ endif()
 if (DEFINED LIBLZMA_LIBRARIES)
     check_library_exists (${LIBLZMA_LIBRARIES} lzma_code "" HAVE_LZMA)
 endif()
+
+if (ICONV_FOUND)
+    # Not actually a sanity check at the moment...
+    set (HAVE_ICONV "1")
+endif()
index bf14693cbf80f1d639e49927f8e5636687444884..09f5ce4eb0edd07a73fdbdcdb19a65ceeb68af91 100644 (file)
 
 #cmakedefine HAVE_FLATBUFFERS 1
 
+#cmakedefine HAVE_ICONV 1
+
 /* Library specific functions */
 
 
index 2fbd3285331ff160de657d64b98787893fbf0acc..7ac104eec7dce8aac17702aad7fedf3820dd4ea1 100644 (file)
@@ -12,7 +12,7 @@
 # enables
 # unit tests
 # required libs (daq / sfbpf, dnet, hwloc, luajit, openssl / crypto, pcap, pcre, zlib)
-# optional libs (hyperscan, lzma, safec)
+# optional libs (hyperscan, iconv, lzma, safec)
 # outputs
 #
 # if you add an AC_DEFINE() for a symbol that appears in an exported
@@ -26,6 +26,7 @@
 AC_INIT([snort],[3.0.0],[snort-team@cisco.com])
 AC_PREREQ([2.69])
 
+AC_CONFIG_AUX_DIR([build-aux])
 AC_CONFIG_SRCDIR([src/main.h])
 AC_CONFIG_MACRO_DIR([m4])
 AC_CONFIG_HEADERS([config.h src/framework/api_options.h])
@@ -1015,6 +1016,11 @@ fi
 
 AM_CONDITIONAL([HAVE_HYPERSCAN], [test "x$HS_HEADERS" = "xyes" -a "x$HS_LIB" = "xyes"])
 
+#--------------------------------------------------------------------------
+# iconv (optional)
+#--------------------------------------------------------------------------
+AM_ICONV
+
 #--------------------------------------------------------------------------
 # lzma (optional)
 #--------------------------------------------------------------------------
index b6ffdb8c74591cb49044ba0d7657ce59b4973a98..c694d1c02f1d116bce13fddcb2cff65ed49ad7cb 100644 (file)
@@ -16,6 +16,8 @@ present.  There is no need to explicitly enable.
 * *hyperscan* >= 4.4.0: for the regex and sd_pattern rule options and the hyperscan
   search engine.
 
+* *iconv*: for converting UTF16-LE filenames to UTF8 (usually included in glibc)
+
 * *lzma*: for decompression of SWF and PDF files.
 
 * *safec*: for additional runtime error checking of some memory copy operations.
@@ -29,7 +31,7 @@ can use these options:
 * *--with-pkg-libraries*: specify the directory containing the package
   libraries.
 
-These can be used for pcap, luajit, pcre, dnet, daq, lzma, openssl, flatbuffers,
-and hyperscan packages.  For more information on these libraries see the Getting
-Started section of the manual.
+These can be used for pcap, luajit, pcre, dnet, daq, lzma, openssl,
+flatbuffers, iconv, and hyperscan packages.  For more information on
+these libraries see the Getting Started section of the manual.
 
index e433aafe453939e74743ced6a26ad81c2ee20c33..ca78c3a43d20b6cbe730d20be09c406fabee562f 100644 (file)
@@ -48,6 +48,9 @@ Optional:
 * hyperscan >= 4.4.0 from https://github.com/01org/hyperscan to build new
   the regex and sd_pattern rule options and hyperscan search engine
 
+* iconv from https://ftp.gnu.org/pub/gnu/libiconv/ for converting
+  UTF16-LE filenames to UTF8 (usually included in glibc)
+
 * lzma >= 5.1.2 from http://tukaani.org/xz/ for decompression of SWF and
   PDF files
 
index 2ea26c8340115906c5afa8ff1cc1d9e51282dfdc..e0930e05c93b84074f4c70326560d2090abba991 100644 (file)
@@ -1,5 +1,5 @@
 AC_INIT([snort_extra],[1.0.0-a4],[snort-team@cisco.com])
-AC_CONFIG_AUX_DIR([.])
+AC_CONFIG_AUX_DIR([build-aux])
 AC_PREREQ([2.69])
 AC_CONFIG_MACRO_DIRS([m4])
 
diff --git a/m4/iconv.m4 b/m4/iconv.m4
new file mode 100644 (file)
index 0000000..b33ecd0
--- /dev/null
@@ -0,0 +1,287 @@
+# iconv.m4 serial 21
+dnl Copyright (C) 2000-2002, 2007-2014, 2016-2017 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+
+AC_DEFUN([AM_ICONV_LINKFLAGS_BODY],
+[
+  dnl Prerequisites of AC_LIB_LINKFLAGS_BODY.
+  AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+  AC_REQUIRE([AC_LIB_RPATH])
+
+  dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV
+  dnl accordingly.
+  AC_LIB_LINKFLAGS_BODY([iconv])
+])
+
+AC_DEFUN([AM_ICONV_LINK],
+[
+  dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and
+  dnl those with the standalone portable GNU libiconv installed).
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+
+  dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV
+  dnl accordingly.
+  AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY])
+
+  dnl Add $INCICONV to CPPFLAGS before performing the following checks,
+  dnl because if the user has installed libiconv and not disabled its use
+  dnl via --without-libiconv-prefix, he wants to use it. The first
+  dnl AC_LINK_IFELSE will then fail, the second AC_LINK_IFELSE will succeed.
+  am_save_CPPFLAGS="$CPPFLAGS"
+  AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCICONV])
+
+  AC_CACHE_CHECK([for iconv], [am_cv_func_iconv], [
+    am_cv_func_iconv="no, consider installing GNU libiconv"
+    am_cv_lib_iconv=no
+    AC_LINK_IFELSE(
+      [AC_LANG_PROGRAM(
+         [[
+#include <stdlib.h>
+#include <iconv.h>
+         ]],
+         [[iconv_t cd = iconv_open("","");
+           iconv(cd,NULL,NULL,NULL,NULL);
+           iconv_close(cd);]])],
+      [am_cv_func_iconv=yes])
+    if test "$am_cv_func_iconv" != yes; then
+      am_save_LIBS="$LIBS"
+      LIBS="$LIBS $LIBICONV"
+      AC_LINK_IFELSE(
+        [AC_LANG_PROGRAM(
+           [[
+#include <stdlib.h>
+#include <iconv.h>
+           ]],
+           [[iconv_t cd = iconv_open("","");
+             iconv(cd,NULL,NULL,NULL,NULL);
+             iconv_close(cd);]])],
+        [am_cv_lib_iconv=yes]
+        [am_cv_func_iconv=yes])
+      LIBS="$am_save_LIBS"
+    fi
+  ])
+  if test "$am_cv_func_iconv" = yes; then
+    AC_CACHE_CHECK([for working iconv], [am_cv_func_iconv_works], [
+      dnl This tests against bugs in AIX 5.1, AIX 6.1..7.1, HP-UX 11.11,
+      dnl Solaris 10.
+      am_save_LIBS="$LIBS"
+      if test $am_cv_lib_iconv = yes; then
+        LIBS="$LIBS $LIBICONV"
+      fi
+      am_cv_func_iconv_works=no
+      for ac_iconv_const in '' 'const'; do
+        AC_RUN_IFELSE(
+          [AC_LANG_PROGRAM(
+             [[
+#include <iconv.h>
+#include <string.h>
+
+#ifndef ICONV_CONST
+# define ICONV_CONST $ac_iconv_const
+#endif
+             ]],
+             [[int result = 0;
+  /* Test against AIX 5.1 bug: Failures are not distinguishable from successful
+     returns.  */
+  {
+    iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8");
+    if (cd_utf8_to_88591 != (iconv_t)(-1))
+      {
+        static ICONV_CONST char input[] = "\342\202\254"; /* EURO SIGN */
+        char buf[10];
+        ICONV_CONST char *inptr = input;
+        size_t inbytesleft = strlen (input);
+        char *outptr = buf;
+        size_t outbytesleft = sizeof (buf);
+        size_t res = iconv (cd_utf8_to_88591,
+                            &inptr, &inbytesleft,
+                            &outptr, &outbytesleft);
+        if (res == 0)
+          result |= 1;
+        iconv_close (cd_utf8_to_88591);
+      }
+  }
+  /* Test against Solaris 10 bug: Failures are not distinguishable from
+     successful returns.  */
+  {
+    iconv_t cd_ascii_to_88591 = iconv_open ("ISO8859-1", "646");
+    if (cd_ascii_to_88591 != (iconv_t)(-1))
+      {
+        static ICONV_CONST char input[] = "\263";
+        char buf[10];
+        ICONV_CONST char *inptr = input;
+        size_t inbytesleft = strlen (input);
+        char *outptr = buf;
+        size_t outbytesleft = sizeof (buf);
+        size_t res = iconv (cd_ascii_to_88591,
+                            &inptr, &inbytesleft,
+                            &outptr, &outbytesleft);
+        if (res == 0)
+          result |= 2;
+        iconv_close (cd_ascii_to_88591);
+      }
+  }
+  /* Test against AIX 6.1..7.1 bug: Buffer overrun.  */
+  {
+    iconv_t cd_88591_to_utf8 = iconv_open ("UTF-8", "ISO-8859-1");
+    if (cd_88591_to_utf8 != (iconv_t)(-1))
+      {
+        static ICONV_CONST char input[] = "\304";
+        static char buf[2] = { (char)0xDE, (char)0xAD };
+        ICONV_CONST char *inptr = input;
+        size_t inbytesleft = 1;
+        char *outptr = buf;
+        size_t outbytesleft = 1;
+        size_t res = iconv (cd_88591_to_utf8,
+                            &inptr, &inbytesleft,
+                            &outptr, &outbytesleft);
+        if (res != (size_t)(-1) || outptr - buf > 1 || buf[1] != (char)0xAD)
+          result |= 4;
+        iconv_close (cd_88591_to_utf8);
+      }
+  }
+#if 0 /* This bug could be worked around by the caller.  */
+  /* Test against HP-UX 11.11 bug: Positive return value instead of 0.  */
+  {
+    iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591");
+    if (cd_88591_to_utf8 != (iconv_t)(-1))
+      {
+        static ICONV_CONST char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
+        char buf[50];
+        ICONV_CONST char *inptr = input;
+        size_t inbytesleft = strlen (input);
+        char *outptr = buf;
+        size_t outbytesleft = sizeof (buf);
+        size_t res = iconv (cd_88591_to_utf8,
+                            &inptr, &inbytesleft,
+                            &outptr, &outbytesleft);
+        if ((int)res > 0)
+          result |= 8;
+        iconv_close (cd_88591_to_utf8);
+      }
+  }
+#endif
+  /* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is
+     provided.  */
+  {
+    /* Try standardized names.  */
+    iconv_t cd1 = iconv_open ("UTF-8", "EUC-JP");
+    /* Try IRIX, OSF/1 names.  */
+    iconv_t cd2 = iconv_open ("UTF-8", "eucJP");
+    /* Try AIX names.  */
+    iconv_t cd3 = iconv_open ("UTF-8", "IBM-eucJP");
+    /* Try HP-UX names.  */
+    iconv_t cd4 = iconv_open ("utf8", "eucJP");
+    if (cd1 == (iconv_t)(-1) && cd2 == (iconv_t)(-1)
+        && cd3 == (iconv_t)(-1) && cd4 == (iconv_t)(-1))
+      result |= 16;
+    if (cd1 != (iconv_t)(-1))
+      iconv_close (cd1);
+    if (cd2 != (iconv_t)(-1))
+      iconv_close (cd2);
+    if (cd3 != (iconv_t)(-1))
+      iconv_close (cd3);
+    if (cd4 != (iconv_t)(-1))
+      iconv_close (cd4);
+  }
+  return result;
+]])],
+          [am_cv_func_iconv_works=yes], ,
+          [case "$host_os" in
+             aix* | hpux*) am_cv_func_iconv_works="guessing no" ;;
+             *)            am_cv_func_iconv_works="guessing yes" ;;
+           esac])
+        test "$am_cv_func_iconv_works" = no || break
+      done
+      LIBS="$am_save_LIBS"
+    ])
+    case "$am_cv_func_iconv_works" in
+      *no) am_func_iconv=no am_cv_lib_iconv=no ;;
+      *)   am_func_iconv=yes ;;
+    esac
+  else
+    am_func_iconv=no am_cv_lib_iconv=no
+  fi
+  if test "$am_func_iconv" = yes; then
+    AC_DEFINE([HAVE_ICONV], [1],
+      [Define if you have the iconv() function and it works.])
+  fi
+  if test "$am_cv_lib_iconv" = yes; then
+    AC_MSG_CHECKING([how to link with libiconv])
+    AC_MSG_RESULT([$LIBICONV])
+  else
+    dnl If $LIBICONV didn't lead to a usable library, we don't need $INCICONV
+    dnl either.
+    CPPFLAGS="$am_save_CPPFLAGS"
+    LIBICONV=
+    LTLIBICONV=
+  fi
+  AC_SUBST([LIBICONV])
+  AC_SUBST([LTLIBICONV])
+])
+
+dnl Define AM_ICONV using AC_DEFUN_ONCE for Autoconf >= 2.64, in order to
+dnl avoid warnings like
+dnl "warning: AC_REQUIRE: `AM_ICONV' was expanded before it was required".
+dnl This is tricky because of the way 'aclocal' is implemented:
+dnl - It requires defining an auxiliary macro whose name ends in AC_DEFUN.
+dnl   Otherwise aclocal's initial scan pass would miss the macro definition.
+dnl - It requires a line break inside the AC_DEFUN_ONCE and AC_DEFUN expansions.
+dnl   Otherwise aclocal would emit many "Use of uninitialized value $1"
+dnl   warnings.
+m4_define([gl_iconv_AC_DEFUN],
+  m4_version_prereq([2.64],
+    [[AC_DEFUN_ONCE(
+        [$1], [$2])]],
+    [m4_ifdef([gl_00GNULIB],
+       [[AC_DEFUN_ONCE(
+           [$1], [$2])]],
+       [[AC_DEFUN(
+           [$1], [$2])]])]))
+gl_iconv_AC_DEFUN([AM_ICONV],
+[
+  AM_ICONV_LINK
+  if test "$am_cv_func_iconv" = yes; then
+    AC_MSG_CHECKING([for iconv declaration])
+    AC_CACHE_VAL([am_cv_proto_iconv], [
+      AC_COMPILE_IFELSE(
+        [AC_LANG_PROGRAM(
+           [[
+#include <stdlib.h>
+#include <iconv.h>
+extern
+#ifdef __cplusplus
+"C"
+#endif
+#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus)
+size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
+#else
+size_t iconv();
+#endif
+           ]],
+           [[]])],
+        [am_cv_proto_iconv_arg1=""],
+        [am_cv_proto_iconv_arg1="const"])
+      am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"])
+    am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'`
+    AC_MSG_RESULT([
+         $am_cv_proto_iconv])
+  else
+    dnl When compiling GNU libiconv on a system that does not have iconv yet,
+    dnl pick the POSIX compliant declaration without 'const'.
+    am_cv_proto_iconv_arg1=""
+  fi
+  AC_DEFINE_UNQUOTED([ICONV_CONST], [$am_cv_proto_iconv_arg1],
+    [Define as const if the declaration of iconv() needs const.])
+  dnl Also substitute ICONV_CONST in the gnulib generated <iconv.h>.
+  m4_ifdef([gl_ICONV_H_DEFAULTS],
+    [AC_REQUIRE([gl_ICONV_H_DEFAULTS])
+     if test -n "$am_cv_proto_iconv_arg1"; then
+       ICONV_CONST="const"
+     fi
+    ])
+])
diff --git a/m4/lib-ld.m4 b/m4/lib-ld.m4
new file mode 100644 (file)
index 0000000..8b8a26e
--- /dev/null
@@ -0,0 +1,147 @@
+# lib-ld.m4 serial 7
+dnl Copyright (C) 1996-2003, 2009-2017 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl Subroutines of libtool.m4,
+dnl with replacements s/_*LT_PATH/AC_LIB_PROG/ and s/lt_/acl_/ to avoid
+dnl collision with libtool.m4.
+
+dnl From libtool-2.4. Sets the variable with_gnu_ld to yes or no.
+AC_DEFUN([AC_LIB_PROG_LD_GNU],
+[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], [acl_cv_prog_gnu_ld],
+[# I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+  acl_cv_prog_gnu_ld=yes
+  ;;
+*)
+  acl_cv_prog_gnu_ld=no
+  ;;
+esac])
+with_gnu_ld=$acl_cv_prog_gnu_ld
+])
+
+dnl From libtool-2.4. Sets the variable LD.
+AC_DEFUN([AC_LIB_PROG_LD],
+[AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+
+AC_ARG_WITH([gnu-ld],
+    [AS_HELP_STRING([--with-gnu-ld],
+        [assume the C compiler uses GNU ld [default=no]])],
+    [test "$withval" = no || with_gnu_ld=yes],
+    [with_gnu_ld=no])dnl
+
+# Prepare PATH_SEPARATOR.
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  # Determine PATH_SEPARATOR by trying to find /bin/sh in a PATH which
+  # contains only /bin. Note that ksh looks also at the FPATH variable,
+  # so we have to set that as well for the test.
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \
+    && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \
+           || PATH_SEPARATOR=';'
+       }
+fi
+
+if test -n "$LD"; then
+  AC_MSG_CHECKING([for ld])
+elif test "$GCC" = yes; then
+  AC_MSG_CHECKING([for ld used by $CC])
+elif test "$with_gnu_ld" = yes; then
+  AC_MSG_CHECKING([for GNU ld])
+else
+  AC_MSG_CHECKING([for non-GNU ld])
+fi
+if test -n "$LD"; then
+  # Let the user override the test with a path.
+  :
+else
+  AC_CACHE_VAL([acl_cv_path_LD],
+  [
+    acl_cv_path_LD= # Final result of this test
+    ac_prog=ld # Program to search in $PATH
+    if test "$GCC" = yes; then
+      # Check if gcc -print-prog-name=ld gives a path.
+      case $host in
+        *-*-mingw*)
+          # gcc leaves a trailing carriage return which upsets mingw
+          acl_output=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+        *)
+          acl_output=`($CC -print-prog-name=ld) 2>&5` ;;
+      esac
+      case $acl_output in
+        # Accept absolute paths.
+        [[\\/]]* | ?:[[\\/]]*)
+          re_direlt='/[[^/]][[^/]]*/\.\./'
+          # Canonicalize the pathname of ld
+          acl_output=`echo "$acl_output" | sed 's%\\\\%/%g'`
+          while echo "$acl_output" | grep "$re_direlt" > /dev/null 2>&1; do
+            acl_output=`echo $acl_output | sed "s%$re_direlt%/%"`
+          done
+          # Got the pathname. No search in PATH is needed.
+          acl_cv_path_LD="$acl_output"
+          ac_prog=
+          ;;
+        "")
+          # If it fails, then pretend we aren't using GCC.
+          ;;
+        *)
+          # If it is relative, then search for the first ld in PATH.
+          with_gnu_ld=unknown
+          ;;
+      esac
+    fi
+    if test -n "$ac_prog"; then
+      # Search for $ac_prog in $PATH.
+      acl_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+      for ac_dir in $PATH; do
+        IFS="$acl_save_ifs"
+        test -z "$ac_dir" && ac_dir=.
+        if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+          acl_cv_path_LD="$ac_dir/$ac_prog"
+          # Check to see if the program is GNU ld.  I'd rather use --version,
+          # but apparently some variants of GNU ld only accept -v.
+          # Break only if it was the GNU/non-GNU ld that we prefer.
+          case `"$acl_cv_path_LD" -v 2>&1 </dev/null` in
+            *GNU* | *'with BFD'*)
+              test "$with_gnu_ld" != no && break
+              ;;
+            *)
+              test "$with_gnu_ld" != yes && break
+              ;;
+          esac
+        fi
+      done
+      IFS="$acl_save_ifs"
+    fi
+    case $host in
+      *-*-aix*)
+        AC_EGREP_CPP([yes],
+          [#if defined __powerpc64__ || defined _ARCH_PPC64
+           yes
+           #endif
+          ],
+          [# The compiler produces 64-bit code. Add option '-b64' so that the
+           # linker groks 64-bit object files.
+           case "$acl_cv_path_LD " in
+             *" -b64 "*) ;;
+             *) acl_cv_path_LD="$acl_cv_path_LD -b64" ;;
+           esac
+          ], [])
+        ;;
+    esac
+  ])
+  LD="$acl_cv_path_LD"
+fi
+if test -n "$LD"; then
+  AC_MSG_RESULT([$LD])
+else
+  AC_MSG_RESULT([no])
+  AC_MSG_ERROR([no acceptable ld found in \$PATH])
+fi
+AC_LIB_PROG_LD_GNU
+])
diff --git a/m4/lib-link.m4 b/m4/lib-link.m4
new file mode 100644 (file)
index 0000000..1ce9a5a
--- /dev/null
@@ -0,0 +1,777 @@
+# lib-link.m4 serial 26 (gettext-0.18.2)
+dnl Copyright (C) 2001-2017 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+
+AC_PREREQ([2.54])
+
+dnl AC_LIB_LINKFLAGS(name [, dependencies]) searches for libname and
+dnl the libraries corresponding to explicit and implicit dependencies.
+dnl Sets and AC_SUBSTs the LIB${NAME} and LTLIB${NAME} variables and
+dnl augments the CPPFLAGS variable.
+dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname
+dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem.
+AC_DEFUN([AC_LIB_LINKFLAGS],
+[
+  AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+  AC_REQUIRE([AC_LIB_RPATH])
+  pushdef([Name],[m4_translit([$1],[./+-], [____])])
+  pushdef([NAME],[m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./+-],
+                                   [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])])
+  AC_CACHE_CHECK([how to link with lib[]$1], [ac_cv_lib[]Name[]_libs], [
+    AC_LIB_LINKFLAGS_BODY([$1], [$2])
+    ac_cv_lib[]Name[]_libs="$LIB[]NAME"
+    ac_cv_lib[]Name[]_ltlibs="$LTLIB[]NAME"
+    ac_cv_lib[]Name[]_cppflags="$INC[]NAME"
+    ac_cv_lib[]Name[]_prefix="$LIB[]NAME[]_PREFIX"
+  ])
+  LIB[]NAME="$ac_cv_lib[]Name[]_libs"
+  LTLIB[]NAME="$ac_cv_lib[]Name[]_ltlibs"
+  INC[]NAME="$ac_cv_lib[]Name[]_cppflags"
+  LIB[]NAME[]_PREFIX="$ac_cv_lib[]Name[]_prefix"
+  AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME)
+  AC_SUBST([LIB]NAME)
+  AC_SUBST([LTLIB]NAME)
+  AC_SUBST([LIB]NAME[_PREFIX])
+  dnl Also set HAVE_LIB[]NAME so that AC_LIB_HAVE_LINKFLAGS can reuse the
+  dnl results of this search when this library appears as a dependency.
+  HAVE_LIB[]NAME=yes
+  popdef([NAME])
+  popdef([Name])
+])
+
+dnl AC_LIB_HAVE_LINKFLAGS(name, dependencies, includes, testcode, [missing-message])
+dnl searches for libname and the libraries corresponding to explicit and
+dnl implicit dependencies, together with the specified include files and
+dnl the ability to compile and link the specified testcode. The missing-message
+dnl defaults to 'no' and may contain additional hints for the user.
+dnl If found, it sets and AC_SUBSTs HAVE_LIB${NAME}=yes and the LIB${NAME}
+dnl and LTLIB${NAME} variables and augments the CPPFLAGS variable, and
+dnl #defines HAVE_LIB${NAME} to 1. Otherwise, it sets and AC_SUBSTs
+dnl HAVE_LIB${NAME}=no and LIB${NAME} and LTLIB${NAME} to empty.
+dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname
+dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem.
+AC_DEFUN([AC_LIB_HAVE_LINKFLAGS],
+[
+  AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+  AC_REQUIRE([AC_LIB_RPATH])
+  pushdef([Name],[m4_translit([$1],[./+-], [____])])
+  pushdef([NAME],[m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./+-],
+                                   [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])])
+
+  dnl Search for lib[]Name and define LIB[]NAME, LTLIB[]NAME and INC[]NAME
+  dnl accordingly.
+  AC_LIB_LINKFLAGS_BODY([$1], [$2])
+
+  dnl Add $INC[]NAME to CPPFLAGS before performing the following checks,
+  dnl because if the user has installed lib[]Name and not disabled its use
+  dnl via --without-lib[]Name-prefix, he wants to use it.
+  ac_save_CPPFLAGS="$CPPFLAGS"
+  AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME)
+
+  AC_CACHE_CHECK([for lib[]$1], [ac_cv_lib[]Name], [
+    ac_save_LIBS="$LIBS"
+    dnl If $LIB[]NAME contains some -l options, add it to the end of LIBS,
+    dnl because these -l options might require -L options that are present in
+    dnl LIBS. -l options benefit only from the -L options listed before it.
+    dnl Otherwise, add it to the front of LIBS, because it may be a static
+    dnl library that depends on another static library that is present in LIBS.
+    dnl Static libraries benefit only from the static libraries listed after
+    dnl it.
+    case " $LIB[]NAME" in
+      *" -l"*) LIBS="$LIBS $LIB[]NAME" ;;
+      *)       LIBS="$LIB[]NAME $LIBS" ;;
+    esac
+    AC_LINK_IFELSE(
+      [AC_LANG_PROGRAM([[$3]], [[$4]])],
+      [ac_cv_lib[]Name=yes],
+      [ac_cv_lib[]Name='m4_if([$5], [], [no], [[$5]])'])
+    LIBS="$ac_save_LIBS"
+  ])
+  if test "$ac_cv_lib[]Name" = yes; then
+    HAVE_LIB[]NAME=yes
+    AC_DEFINE([HAVE_LIB]NAME, 1, [Define if you have the lib][$1 library.])
+    AC_MSG_CHECKING([how to link with lib[]$1])
+    AC_MSG_RESULT([$LIB[]NAME])
+  else
+    HAVE_LIB[]NAME=no
+    dnl If $LIB[]NAME didn't lead to a usable library, we don't need
+    dnl $INC[]NAME either.
+    CPPFLAGS="$ac_save_CPPFLAGS"
+    LIB[]NAME=
+    LTLIB[]NAME=
+    LIB[]NAME[]_PREFIX=
+  fi
+  AC_SUBST([HAVE_LIB]NAME)
+  AC_SUBST([LIB]NAME)
+  AC_SUBST([LTLIB]NAME)
+  AC_SUBST([LIB]NAME[_PREFIX])
+  popdef([NAME])
+  popdef([Name])
+])
+
+dnl Determine the platform dependent parameters needed to use rpath:
+dnl   acl_libext,
+dnl   acl_shlibext,
+dnl   acl_libname_spec,
+dnl   acl_library_names_spec,
+dnl   acl_hardcode_libdir_flag_spec,
+dnl   acl_hardcode_libdir_separator,
+dnl   acl_hardcode_direct,
+dnl   acl_hardcode_minus_L.
+AC_DEFUN([AC_LIB_RPATH],
+[
+  dnl Tell automake >= 1.10 to complain if config.rpath is missing.
+  m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([config.rpath])])
+  AC_REQUIRE([AC_PROG_CC])                dnl we use $CC, $GCC, $LDFLAGS
+  AC_REQUIRE([AC_LIB_PROG_LD])            dnl we use $LD, $with_gnu_ld
+  AC_REQUIRE([AC_CANONICAL_HOST])         dnl we use $host
+  AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) dnl we use $ac_aux_dir
+  AC_CACHE_CHECK([for shared library run path origin], [acl_cv_rpath], [
+    CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \
+    ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh
+    . ./conftest.sh
+    rm -f ./conftest.sh
+    acl_cv_rpath=done
+  ])
+  wl="$acl_cv_wl"
+  acl_libext="$acl_cv_libext"
+  acl_shlibext="$acl_cv_shlibext"
+  acl_libname_spec="$acl_cv_libname_spec"
+  acl_library_names_spec="$acl_cv_library_names_spec"
+  acl_hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec"
+  acl_hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator"
+  acl_hardcode_direct="$acl_cv_hardcode_direct"
+  acl_hardcode_minus_L="$acl_cv_hardcode_minus_L"
+  dnl Determine whether the user wants rpath handling at all.
+  AC_ARG_ENABLE([rpath],
+    [  --disable-rpath         do not hardcode runtime library paths],
+    :, enable_rpath=yes)
+])
+
+dnl AC_LIB_FROMPACKAGE(name, package)
+dnl declares that libname comes from the given package. The configure file
+dnl will then not have a --with-libname-prefix option but a
+dnl --with-package-prefix option. Several libraries can come from the same
+dnl package. This declaration must occur before an AC_LIB_LINKFLAGS or similar
+dnl macro call that searches for libname.
+AC_DEFUN([AC_LIB_FROMPACKAGE],
+[
+  pushdef([NAME],[m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./+-],
+                                   [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])])
+  define([acl_frompackage_]NAME, [$2])
+  popdef([NAME])
+  pushdef([PACK],[$2])
+  pushdef([PACKUP],[m4_translit(PACK,[abcdefghijklmnopqrstuvwxyz./+-],
+                                     [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])])
+  define([acl_libsinpackage_]PACKUP,
+    m4_ifdef([acl_libsinpackage_]PACKUP, [m4_defn([acl_libsinpackage_]PACKUP)[, ]],)[lib$1])
+  popdef([PACKUP])
+  popdef([PACK])
+])
+
+dnl AC_LIB_LINKFLAGS_BODY(name [, dependencies]) searches for libname and
+dnl the libraries corresponding to explicit and implicit dependencies.
+dnl Sets the LIB${NAME}, LTLIB${NAME} and INC${NAME} variables.
+dnl Also, sets the LIB${NAME}_PREFIX variable to nonempty if libname was found
+dnl in ${LIB${NAME}_PREFIX}/$acl_libdirstem.
+AC_DEFUN([AC_LIB_LINKFLAGS_BODY],
+[
+  AC_REQUIRE([AC_LIB_PREPARE_MULTILIB])
+  pushdef([NAME],[m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./+-],
+                                   [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])])
+  pushdef([PACK],[m4_ifdef([acl_frompackage_]NAME, [acl_frompackage_]NAME, lib[$1])])
+  pushdef([PACKUP],[m4_translit(PACK,[abcdefghijklmnopqrstuvwxyz./+-],
+                                     [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])])
+  pushdef([PACKLIBS],[m4_ifdef([acl_frompackage_]NAME, [acl_libsinpackage_]PACKUP, lib[$1])])
+  dnl Autoconf >= 2.61 supports dots in --with options.
+  pushdef([P_A_C_K],[m4_if(m4_version_compare(m4_defn([m4_PACKAGE_VERSION]),[2.61]),[-1],[m4_translit(PACK,[.],[_])],PACK)])
+  dnl By default, look in $includedir and $libdir.
+  use_additional=yes
+  AC_LIB_WITH_FINAL_PREFIX([
+    eval additional_includedir=\"$includedir\"
+    eval additional_libdir=\"$libdir\"
+  ])
+  AC_ARG_WITH(P_A_C_K[-prefix],
+[[  --with-]]P_A_C_K[[-prefix[=DIR]  search for ]PACKLIBS[ in DIR/include and DIR/lib
+  --without-]]P_A_C_K[[-prefix     don't search for ]PACKLIBS[ in includedir and libdir]],
+[
+    if test "X$withval" = "Xno"; then
+      use_additional=no
+    else
+      if test "X$withval" = "X"; then
+        AC_LIB_WITH_FINAL_PREFIX([
+          eval additional_includedir=\"$includedir\"
+          eval additional_libdir=\"$libdir\"
+        ])
+      else
+        additional_includedir="$withval/include"
+        additional_libdir="$withval/$acl_libdirstem"
+        if test "$acl_libdirstem2" != "$acl_libdirstem" \
+           && ! test -d "$withval/$acl_libdirstem"; then
+          additional_libdir="$withval/$acl_libdirstem2"
+        fi
+      fi
+    fi
+])
+  dnl Search the library and its dependencies in $additional_libdir and
+  dnl $LDFLAGS. Using breadth-first-seach.
+  LIB[]NAME=
+  LTLIB[]NAME=
+  INC[]NAME=
+  LIB[]NAME[]_PREFIX=
+  dnl HAVE_LIB${NAME} is an indicator that LIB${NAME}, LTLIB${NAME} have been
+  dnl computed. So it has to be reset here.
+  HAVE_LIB[]NAME=
+  rpathdirs=
+  ltrpathdirs=
+  names_already_handled=
+  names_next_round='$1 $2'
+  while test -n "$names_next_round"; do
+    names_this_round="$names_next_round"
+    names_next_round=
+    for name in $names_this_round; do
+      already_handled=
+      for n in $names_already_handled; do
+        if test "$n" = "$name"; then
+          already_handled=yes
+          break
+        fi
+      done
+      if test -z "$already_handled"; then
+        names_already_handled="$names_already_handled $name"
+        dnl See if it was already located by an earlier AC_LIB_LINKFLAGS
+        dnl or AC_LIB_HAVE_LINKFLAGS call.
+        uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./+-|ABCDEFGHIJKLMNOPQRSTUVWXYZ____|'`
+        eval value=\"\$HAVE_LIB$uppername\"
+        if test -n "$value"; then
+          if test "$value" = yes; then
+            eval value=\"\$LIB$uppername\"
+            test -z "$value" || LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$value"
+            eval value=\"\$LTLIB$uppername\"
+            test -z "$value" || LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$value"
+          else
+            dnl An earlier call to AC_LIB_HAVE_LINKFLAGS has determined
+            dnl that this library doesn't exist. So just drop it.
+            :
+          fi
+        else
+          dnl Search the library lib$name in $additional_libdir and $LDFLAGS
+          dnl and the already constructed $LIBNAME/$LTLIBNAME.
+          found_dir=
+          found_la=
+          found_so=
+          found_a=
+          eval libname=\"$acl_libname_spec\"    # typically: libname=lib$name
+          if test -n "$acl_shlibext"; then
+            shrext=".$acl_shlibext"             # typically: shrext=.so
+          else
+            shrext=
+          fi
+          if test $use_additional = yes; then
+            dir="$additional_libdir"
+            dnl The same code as in the loop below:
+            dnl First look for a shared library.
+            if test -n "$acl_shlibext"; then
+              if test -f "$dir/$libname$shrext"; then
+                found_dir="$dir"
+                found_so="$dir/$libname$shrext"
+              else
+                if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then
+                  ver=`(cd "$dir" && \
+                        for f in "$libname$shrext".*; do echo "$f"; done \
+                        | sed -e "s,^$libname$shrext\\\\.,," \
+                        | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \
+                        | sed 1q ) 2>/dev/null`
+                  if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then
+                    found_dir="$dir"
+                    found_so="$dir/$libname$shrext.$ver"
+                  fi
+                else
+                  eval library_names=\"$acl_library_names_spec\"
+                  for f in $library_names; do
+                    if test -f "$dir/$f"; then
+                      found_dir="$dir"
+                      found_so="$dir/$f"
+                      break
+                    fi
+                  done
+                fi
+              fi
+            fi
+            dnl Then look for a static library.
+            if test "X$found_dir" = "X"; then
+              if test -f "$dir/$libname.$acl_libext"; then
+                found_dir="$dir"
+                found_a="$dir/$libname.$acl_libext"
+              fi
+            fi
+            if test "X$found_dir" != "X"; then
+              if test -f "$dir/$libname.la"; then
+                found_la="$dir/$libname.la"
+              fi
+            fi
+          fi
+          if test "X$found_dir" = "X"; then
+            for x in $LDFLAGS $LTLIB[]NAME; do
+              AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+              case "$x" in
+                -L*)
+                  dir=`echo "X$x" | sed -e 's/^X-L//'`
+                  dnl First look for a shared library.
+                  if test -n "$acl_shlibext"; then
+                    if test -f "$dir/$libname$shrext"; then
+                      found_dir="$dir"
+                      found_so="$dir/$libname$shrext"
+                    else
+                      if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then
+                        ver=`(cd "$dir" && \
+                              for f in "$libname$shrext".*; do echo "$f"; done \
+                              | sed -e "s,^$libname$shrext\\\\.,," \
+                              | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \
+                              | sed 1q ) 2>/dev/null`
+                        if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then
+                          found_dir="$dir"
+                          found_so="$dir/$libname$shrext.$ver"
+                        fi
+                      else
+                        eval library_names=\"$acl_library_names_spec\"
+                        for f in $library_names; do
+                          if test -f "$dir/$f"; then
+                            found_dir="$dir"
+                            found_so="$dir/$f"
+                            break
+                          fi
+                        done
+                      fi
+                    fi
+                  fi
+                  dnl Then look for a static library.
+                  if test "X$found_dir" = "X"; then
+                    if test -f "$dir/$libname.$acl_libext"; then
+                      found_dir="$dir"
+                      found_a="$dir/$libname.$acl_libext"
+                    fi
+                  fi
+                  if test "X$found_dir" != "X"; then
+                    if test -f "$dir/$libname.la"; then
+                      found_la="$dir/$libname.la"
+                    fi
+                  fi
+                  ;;
+              esac
+              if test "X$found_dir" != "X"; then
+                break
+              fi
+            done
+          fi
+          if test "X$found_dir" != "X"; then
+            dnl Found the library.
+            LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$found_dir -l$name"
+            if test "X$found_so" != "X"; then
+              dnl Linking with a shared library. We attempt to hardcode its
+              dnl directory into the executable's runpath, unless it's the
+              dnl standard /usr/lib.
+              if test "$enable_rpath" = no \
+                 || test "X$found_dir" = "X/usr/$acl_libdirstem" \
+                 || test "X$found_dir" = "X/usr/$acl_libdirstem2"; then
+                dnl No hardcoding is needed.
+                LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
+              else
+                dnl Use an explicit option to hardcode DIR into the resulting
+                dnl binary.
+                dnl Potentially add DIR to ltrpathdirs.
+                dnl The ltrpathdirs will be appended to $LTLIBNAME at the end.
+                haveit=
+                for x in $ltrpathdirs; do
+                  if test "X$x" = "X$found_dir"; then
+                    haveit=yes
+                    break
+                  fi
+                done
+                if test -z "$haveit"; then
+                  ltrpathdirs="$ltrpathdirs $found_dir"
+                fi
+                dnl The hardcoding into $LIBNAME is system dependent.
+                if test "$acl_hardcode_direct" = yes; then
+                  dnl Using DIR/libNAME.so during linking hardcodes DIR into the
+                  dnl resulting binary.
+                  LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
+                else
+                  if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then
+                    dnl Use an explicit option to hardcode DIR into the resulting
+                    dnl binary.
+                    LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
+                    dnl Potentially add DIR to rpathdirs.
+                    dnl The rpathdirs will be appended to $LIBNAME at the end.
+                    haveit=
+                    for x in $rpathdirs; do
+                      if test "X$x" = "X$found_dir"; then
+                        haveit=yes
+                        break
+                      fi
+                    done
+                    if test -z "$haveit"; then
+                      rpathdirs="$rpathdirs $found_dir"
+                    fi
+                  else
+                    dnl Rely on "-L$found_dir".
+                    dnl But don't add it if it's already contained in the LDFLAGS
+                    dnl or the already constructed $LIBNAME
+                    haveit=
+                    for x in $LDFLAGS $LIB[]NAME; do
+                      AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+                      if test "X$x" = "X-L$found_dir"; then
+                        haveit=yes
+                        break
+                      fi
+                    done
+                    if test -z "$haveit"; then
+                      LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir"
+                    fi
+                    if test "$acl_hardcode_minus_L" != no; then
+                      dnl FIXME: Not sure whether we should use
+                      dnl "-L$found_dir -l$name" or "-L$found_dir $found_so"
+                      dnl here.
+                      LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
+                    else
+                      dnl We cannot use $acl_hardcode_runpath_var and LD_RUN_PATH
+                      dnl here, because this doesn't fit in flags passed to the
+                      dnl compiler. So give up. No hardcoding. This affects only
+                      dnl very old systems.
+                      dnl FIXME: Not sure whether we should use
+                      dnl "-L$found_dir -l$name" or "-L$found_dir $found_so"
+                      dnl here.
+                      LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name"
+                    fi
+                  fi
+                fi
+              fi
+            else
+              if test "X$found_a" != "X"; then
+                dnl Linking with a static library.
+                LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_a"
+              else
+                dnl We shouldn't come here, but anyway it's good to have a
+                dnl fallback.
+                LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir -l$name"
+              fi
+            fi
+            dnl Assume the include files are nearby.
+            additional_includedir=
+            case "$found_dir" in
+              */$acl_libdirstem | */$acl_libdirstem/)
+                basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'`
+                if test "$name" = '$1'; then
+                  LIB[]NAME[]_PREFIX="$basedir"
+                fi
+                additional_includedir="$basedir/include"
+                ;;
+              */$acl_libdirstem2 | */$acl_libdirstem2/)
+                basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem2/"'*$,,'`
+                if test "$name" = '$1'; then
+                  LIB[]NAME[]_PREFIX="$basedir"
+                fi
+                additional_includedir="$basedir/include"
+                ;;
+            esac
+            if test "X$additional_includedir" != "X"; then
+              dnl Potentially add $additional_includedir to $INCNAME.
+              dnl But don't add it
+              dnl   1. if it's the standard /usr/include,
+              dnl   2. if it's /usr/local/include and we are using GCC on Linux,
+              dnl   3. if it's already present in $CPPFLAGS or the already
+              dnl      constructed $INCNAME,
+              dnl   4. if it doesn't exist as a directory.
+              if test "X$additional_includedir" != "X/usr/include"; then
+                haveit=
+                if test "X$additional_includedir" = "X/usr/local/include"; then
+                  if test -n "$GCC"; then
+                    case $host_os in
+                      linux* | gnu* | k*bsd*-gnu) haveit=yes;;
+                    esac
+                  fi
+                fi
+                if test -z "$haveit"; then
+                  for x in $CPPFLAGS $INC[]NAME; do
+                    AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+                    if test "X$x" = "X-I$additional_includedir"; then
+                      haveit=yes
+                      break
+                    fi
+                  done
+                  if test -z "$haveit"; then
+                    if test -d "$additional_includedir"; then
+                      dnl Really add $additional_includedir to $INCNAME.
+                      INC[]NAME="${INC[]NAME}${INC[]NAME:+ }-I$additional_includedir"
+                    fi
+                  fi
+                fi
+              fi
+            fi
+            dnl Look for dependencies.
+            if test -n "$found_la"; then
+              dnl Read the .la file. It defines the variables
+              dnl dlname, library_names, old_library, dependency_libs, current,
+              dnl age, revision, installed, dlopen, dlpreopen, libdir.
+              save_libdir="$libdir"
+              case "$found_la" in
+                */* | *\\*) . "$found_la" ;;
+                *) . "./$found_la" ;;
+              esac
+              libdir="$save_libdir"
+              dnl We use only dependency_libs.
+              for dep in $dependency_libs; do
+                case "$dep" in
+                  -L*)
+                    additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'`
+                    dnl Potentially add $additional_libdir to $LIBNAME and $LTLIBNAME.
+                    dnl But don't add it
+                    dnl   1. if it's the standard /usr/lib,
+                    dnl   2. if it's /usr/local/lib and we are using GCC on Linux,
+                    dnl   3. if it's already present in $LDFLAGS or the already
+                    dnl      constructed $LIBNAME,
+                    dnl   4. if it doesn't exist as a directory.
+                    if test "X$additional_libdir" != "X/usr/$acl_libdirstem" \
+                       && test "X$additional_libdir" != "X/usr/$acl_libdirstem2"; then
+                      haveit=
+                      if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem" \
+                         || test "X$additional_libdir" = "X/usr/local/$acl_libdirstem2"; then
+                        if test -n "$GCC"; then
+                          case $host_os in
+                            linux* | gnu* | k*bsd*-gnu) haveit=yes;;
+                          esac
+                        fi
+                      fi
+                      if test -z "$haveit"; then
+                        haveit=
+                        for x in $LDFLAGS $LIB[]NAME; do
+                          AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+                          if test "X$x" = "X-L$additional_libdir"; then
+                            haveit=yes
+                            break
+                          fi
+                        done
+                        if test -z "$haveit"; then
+                          if test -d "$additional_libdir"; then
+                            dnl Really add $additional_libdir to $LIBNAME.
+                            LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$additional_libdir"
+                          fi
+                        fi
+                        haveit=
+                        for x in $LDFLAGS $LTLIB[]NAME; do
+                          AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+                          if test "X$x" = "X-L$additional_libdir"; then
+                            haveit=yes
+                            break
+                          fi
+                        done
+                        if test -z "$haveit"; then
+                          if test -d "$additional_libdir"; then
+                            dnl Really add $additional_libdir to $LTLIBNAME.
+                            LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$additional_libdir"
+                          fi
+                        fi
+                      fi
+                    fi
+                    ;;
+                  -R*)
+                    dir=`echo "X$dep" | sed -e 's/^X-R//'`
+                    if test "$enable_rpath" != no; then
+                      dnl Potentially add DIR to rpathdirs.
+                      dnl The rpathdirs will be appended to $LIBNAME at the end.
+                      haveit=
+                      for x in $rpathdirs; do
+                        if test "X$x" = "X$dir"; then
+                          haveit=yes
+                          break
+                        fi
+                      done
+                      if test -z "$haveit"; then
+                        rpathdirs="$rpathdirs $dir"
+                      fi
+                      dnl Potentially add DIR to ltrpathdirs.
+                      dnl The ltrpathdirs will be appended to $LTLIBNAME at the end.
+                      haveit=
+                      for x in $ltrpathdirs; do
+                        if test "X$x" = "X$dir"; then
+                          haveit=yes
+                          break
+                        fi
+                      done
+                      if test -z "$haveit"; then
+                        ltrpathdirs="$ltrpathdirs $dir"
+                      fi
+                    fi
+                    ;;
+                  -l*)
+                    dnl Handle this in the next round.
+                    names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'`
+                    ;;
+                  *.la)
+                    dnl Handle this in the next round. Throw away the .la's
+                    dnl directory; it is already contained in a preceding -L
+                    dnl option.
+                    names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'`
+                    ;;
+                  *)
+                    dnl Most likely an immediate library name.
+                    LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$dep"
+                    LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$dep"
+                    ;;
+                esac
+              done
+            fi
+          else
+            dnl Didn't find the library; assume it is in the system directories
+            dnl known to the linker and runtime loader. (All the system
+            dnl directories known to the linker should also be known to the
+            dnl runtime loader, otherwise the system is severely misconfigured.)
+            LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name"
+            LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-l$name"
+          fi
+        fi
+      fi
+    done
+  done
+  if test "X$rpathdirs" != "X"; then
+    if test -n "$acl_hardcode_libdir_separator"; then
+      dnl Weird platform: only the last -rpath option counts, the user must
+      dnl pass all path elements in one option. We can arrange that for a
+      dnl single library, but not when more than one $LIBNAMEs are used.
+      alldirs=
+      for found_dir in $rpathdirs; do
+        alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir"
+      done
+      dnl Note: acl_hardcode_libdir_flag_spec uses $libdir and $wl.
+      acl_save_libdir="$libdir"
+      libdir="$alldirs"
+      eval flag=\"$acl_hardcode_libdir_flag_spec\"
+      libdir="$acl_save_libdir"
+      LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag"
+    else
+      dnl The -rpath options are cumulative.
+      for found_dir in $rpathdirs; do
+        acl_save_libdir="$libdir"
+        libdir="$found_dir"
+        eval flag=\"$acl_hardcode_libdir_flag_spec\"
+        libdir="$acl_save_libdir"
+        LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag"
+      done
+    fi
+  fi
+  if test "X$ltrpathdirs" != "X"; then
+    dnl When using libtool, the option that works for both libraries and
+    dnl executables is -R. The -R options are cumulative.
+    for found_dir in $ltrpathdirs; do
+      LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-R$found_dir"
+    done
+  fi
+  popdef([P_A_C_K])
+  popdef([PACKLIBS])
+  popdef([PACKUP])
+  popdef([PACK])
+  popdef([NAME])
+])
+
+dnl AC_LIB_APPENDTOVAR(VAR, CONTENTS) appends the elements of CONTENTS to VAR,
+dnl unless already present in VAR.
+dnl Works only for CPPFLAGS, not for LIB* variables because that sometimes
+dnl contains two or three consecutive elements that belong together.
+AC_DEFUN([AC_LIB_APPENDTOVAR],
+[
+  for element in [$2]; do
+    haveit=
+    for x in $[$1]; do
+      AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+      if test "X$x" = "X$element"; then
+        haveit=yes
+        break
+      fi
+    done
+    if test -z "$haveit"; then
+      [$1]="${[$1]}${[$1]:+ }$element"
+    fi
+  done
+])
+
+dnl For those cases where a variable contains several -L and -l options
+dnl referring to unknown libraries and directories, this macro determines the
+dnl necessary additional linker options for the runtime path.
+dnl AC_LIB_LINKFLAGS_FROM_LIBS([LDADDVAR], [LIBSVALUE], [USE-LIBTOOL])
+dnl sets LDADDVAR to linker options needed together with LIBSVALUE.
+dnl If USE-LIBTOOL evaluates to non-empty, linking with libtool is assumed,
+dnl otherwise linking without libtool is assumed.
+AC_DEFUN([AC_LIB_LINKFLAGS_FROM_LIBS],
+[
+  AC_REQUIRE([AC_LIB_RPATH])
+  AC_REQUIRE([AC_LIB_PREPARE_MULTILIB])
+  $1=
+  if test "$enable_rpath" != no; then
+    if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then
+      dnl Use an explicit option to hardcode directories into the resulting
+      dnl binary.
+      rpathdirs=
+      next=
+      for opt in $2; do
+        if test -n "$next"; then
+          dir="$next"
+          dnl No need to hardcode the standard /usr/lib.
+          if test "X$dir" != "X/usr/$acl_libdirstem" \
+             && test "X$dir" != "X/usr/$acl_libdirstem2"; then
+            rpathdirs="$rpathdirs $dir"
+          fi
+          next=
+        else
+          case $opt in
+            -L) next=yes ;;
+            -L*) dir=`echo "X$opt" | sed -e 's,^X-L,,'`
+                 dnl No need to hardcode the standard /usr/lib.
+                 if test "X$dir" != "X/usr/$acl_libdirstem" \
+                    && test "X$dir" != "X/usr/$acl_libdirstem2"; then
+                   rpathdirs="$rpathdirs $dir"
+                 fi
+                 next= ;;
+            *) next= ;;
+          esac
+        fi
+      done
+      if test "X$rpathdirs" != "X"; then
+        if test -n ""$3""; then
+          dnl libtool is used for linking. Use -R options.
+          for dir in $rpathdirs; do
+            $1="${$1}${$1:+ }-R$dir"
+          done
+        else
+          dnl The linker is used for linking directly.
+          if test -n "$acl_hardcode_libdir_separator"; then
+            dnl Weird platform: only the last -rpath option counts, the user
+            dnl must pass all path elements in one option.
+            alldirs=
+            for dir in $rpathdirs; do
+              alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$dir"
+            done
+            acl_save_libdir="$libdir"
+            libdir="$alldirs"
+            eval flag=\"$acl_hardcode_libdir_flag_spec\"
+            libdir="$acl_save_libdir"
+            $1="$flag"
+          else
+            dnl The -rpath options are cumulative.
+            for dir in $rpathdirs; do
+              acl_save_libdir="$libdir"
+              libdir="$dir"
+              eval flag=\"$acl_hardcode_libdir_flag_spec\"
+              libdir="$acl_save_libdir"
+              $1="${$1}${$1:+ }$flag"
+            done
+          fi
+        fi
+      fi
+    fi
+  fi
+  AC_SUBST([$1])
+])
diff --git a/m4/lib-prefix.m4 b/m4/lib-prefix.m4
new file mode 100644 (file)
index 0000000..0d03dc2
--- /dev/null
@@ -0,0 +1,241 @@
+# lib-prefix.m4 serial 8
+dnl Copyright (C) 2001-2005, 2008-2017 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+
+dnl AC_LIB_ARG_WITH is synonymous to AC_ARG_WITH in autoconf-2.13, and
+dnl similar to AC_ARG_WITH in autoconf 2.52...2.57 except that is doesn't
+dnl require excessive bracketing.
+ifdef([AC_HELP_STRING],
+[AC_DEFUN([AC_LIB_ARG_WITH], [AC_ARG_WITH([$1],[[$2]],[$3],[$4])])],
+[AC_DEFUN([AC_][LIB_ARG_WITH], [AC_ARG_WITH([$1],[$2],[$3],[$4])])])
+
+dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed
+dnl to access previously installed libraries. The basic assumption is that
+dnl a user will want packages to use other packages he previously installed
+dnl with the same --prefix option.
+dnl This macro is not needed if only AC_LIB_LINKFLAGS is used to locate
+dnl libraries, but is otherwise very convenient.
+AC_DEFUN([AC_LIB_PREFIX],
+[
+  AC_BEFORE([$0], [AC_LIB_LINKFLAGS])
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([AC_CANONICAL_HOST])
+  AC_REQUIRE([AC_LIB_PREPARE_MULTILIB])
+  AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+  dnl By default, look in $includedir and $libdir.
+  use_additional=yes
+  AC_LIB_WITH_FINAL_PREFIX([
+    eval additional_includedir=\"$includedir\"
+    eval additional_libdir=\"$libdir\"
+  ])
+  AC_LIB_ARG_WITH([lib-prefix],
+[  --with-lib-prefix[=DIR] search for libraries in DIR/include and DIR/lib
+  --without-lib-prefix    don't search for libraries in includedir and libdir],
+[
+    if test "X$withval" = "Xno"; then
+      use_additional=no
+    else
+      if test "X$withval" = "X"; then
+        AC_LIB_WITH_FINAL_PREFIX([
+          eval additional_includedir=\"$includedir\"
+          eval additional_libdir=\"$libdir\"
+        ])
+      else
+        additional_includedir="$withval/include"
+        additional_libdir="$withval/$acl_libdirstem"
+      fi
+    fi
+])
+  if test $use_additional = yes; then
+    dnl Potentially add $additional_includedir to $CPPFLAGS.
+    dnl But don't add it
+    dnl   1. if it's the standard /usr/include,
+    dnl   2. if it's already present in $CPPFLAGS,
+    dnl   3. if it's /usr/local/include and we are using GCC on Linux,
+    dnl   4. if it doesn't exist as a directory.
+    if test "X$additional_includedir" != "X/usr/include"; then
+      haveit=
+      for x in $CPPFLAGS; do
+        AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+        if test "X$x" = "X-I$additional_includedir"; then
+          haveit=yes
+          break
+        fi
+      done
+      if test -z "$haveit"; then
+        if test "X$additional_includedir" = "X/usr/local/include"; then
+          if test -n "$GCC"; then
+            case $host_os in
+              linux* | gnu* | k*bsd*-gnu) haveit=yes;;
+            esac
+          fi
+        fi
+        if test -z "$haveit"; then
+          if test -d "$additional_includedir"; then
+            dnl Really add $additional_includedir to $CPPFLAGS.
+            CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-I$additional_includedir"
+          fi
+        fi
+      fi
+    fi
+    dnl Potentially add $additional_libdir to $LDFLAGS.
+    dnl But don't add it
+    dnl   1. if it's the standard /usr/lib,
+    dnl   2. if it's already present in $LDFLAGS,
+    dnl   3. if it's /usr/local/lib and we are using GCC on Linux,
+    dnl   4. if it doesn't exist as a directory.
+    if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then
+      haveit=
+      for x in $LDFLAGS; do
+        AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+        if test "X$x" = "X-L$additional_libdir"; then
+          haveit=yes
+          break
+        fi
+      done
+      if test -z "$haveit"; then
+        if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then
+          if test -n "$GCC"; then
+            case $host_os in
+              linux*) haveit=yes;;
+            esac
+          fi
+        fi
+        if test -z "$haveit"; then
+          if test -d "$additional_libdir"; then
+            dnl Really add $additional_libdir to $LDFLAGS.
+            LDFLAGS="${LDFLAGS}${LDFLAGS:+ }-L$additional_libdir"
+          fi
+        fi
+      fi
+    fi
+  fi
+])
+
+dnl AC_LIB_PREPARE_PREFIX creates variables acl_final_prefix,
+dnl acl_final_exec_prefix, containing the values to which $prefix and
+dnl $exec_prefix will expand at the end of the configure script.
+AC_DEFUN([AC_LIB_PREPARE_PREFIX],
+[
+  dnl Unfortunately, prefix and exec_prefix get only finally determined
+  dnl at the end of configure.
+  if test "X$prefix" = "XNONE"; then
+    acl_final_prefix="$ac_default_prefix"
+  else
+    acl_final_prefix="$prefix"
+  fi
+  if test "X$exec_prefix" = "XNONE"; then
+    acl_final_exec_prefix='${prefix}'
+  else
+    acl_final_exec_prefix="$exec_prefix"
+  fi
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  eval acl_final_exec_prefix=\"$acl_final_exec_prefix\"
+  prefix="$acl_save_prefix"
+])
+
+dnl AC_LIB_WITH_FINAL_PREFIX([statement]) evaluates statement, with the
+dnl variables prefix and exec_prefix bound to the values they will have
+dnl at the end of the configure script.
+AC_DEFUN([AC_LIB_WITH_FINAL_PREFIX],
+[
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+  $1
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+])
+
+dnl AC_LIB_PREPARE_MULTILIB creates
+dnl - a variable acl_libdirstem, containing the basename of the libdir, either
+dnl   "lib" or "lib64" or "lib/64",
+dnl - a variable acl_libdirstem2, as a secondary possible value for
+dnl   acl_libdirstem, either the same as acl_libdirstem or "lib/sparcv9" or
+dnl   "lib/amd64".
+AC_DEFUN([AC_LIB_PREPARE_MULTILIB],
+[
+  dnl There is no formal standard regarding lib and lib64.
+  dnl On glibc systems, the current practice is that on a system supporting
+  dnl 32-bit and 64-bit instruction sets or ABIs, 64-bit libraries go under
+  dnl $prefix/lib64 and 32-bit libraries go under $prefix/lib. We determine
+  dnl the compiler's default mode by looking at the compiler's library search
+  dnl path. If at least one of its elements ends in /lib64 or points to a
+  dnl directory whose absolute pathname ends in /lib64, we assume a 64-bit ABI.
+  dnl Otherwise we use the default, namely "lib".
+  dnl On Solaris systems, the current practice is that on a system supporting
+  dnl 32-bit and 64-bit instruction sets or ABIs, 64-bit libraries go under
+  dnl $prefix/lib/64 (which is a symlink to either $prefix/lib/sparcv9 or
+  dnl $prefix/lib/amd64) and 32-bit libraries go under $prefix/lib.
+  AC_REQUIRE([AC_CANONICAL_HOST])
+  dnl Allow the user to override the result by setting acl_cv_libdirstems.
+  AC_CACHE_CHECK([for the common suffixes of directories in the library search path],
+    [acl_cv_libdirstems],
+    [acl_libdirstem=lib
+     acl_libdirstem2=
+     case "$host_os" in
+       solaris*)
+         dnl See Solaris 10 Software Developer Collection > Solaris 64-bit Developer's Guide > The Development Environment
+         dnl <https://docs.oracle.com/cd/E19253-01/816-5138/dev-env/index.html>.
+         dnl "Portable Makefiles should refer to any library directories using the 64 symbolic link."
+         dnl But we want to recognize the sparcv9 or amd64 subdirectory also if the
+         dnl symlink is missing, so we set acl_libdirstem2 too.
+         AC_CACHE_CHECK([for 64-bit host], [gl_cv_solaris_64bit],
+           [AC_EGREP_CPP([sixtyfour bits], [
+#ifdef _LP64
+sixtyfour bits
+#endif
+              ], [gl_cv_solaris_64bit=yes], [gl_cv_solaris_64bit=no])
+           ])
+         if test $gl_cv_solaris_64bit = yes; then
+           acl_libdirstem=lib/64
+           case "$host_cpu" in
+             sparc*)        acl_libdirstem2=lib/sparcv9 ;;
+             i*86 | x86_64) acl_libdirstem2=lib/amd64 ;;
+           esac
+         fi
+         ;;
+       *)
+         dnl The result is a property of the system. However, non-system
+         dnl compilers sometimes have odd library search paths. Therefore
+         dnl prefer asking /usr/bin/gcc, if available, rather than $CC.
+         searchpath=`(if test -f /usr/bin/gcc \
+                         && LC_ALL=C /usr/bin/gcc -print-search-dirs >/dev/null 2>/dev/null; then \
+                        LC_ALL=C /usr/bin/gcc -print-search-dirs; \
+                      else \
+                        LC_ALL=C $CC -print-search-dirs; \
+                      fi) 2>/dev/null \
+                     | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'`
+         if test -n "$searchpath"; then
+           acl_save_IFS="${IFS=        }"; IFS=":"
+           for searchdir in $searchpath; do
+             if test -d "$searchdir"; then
+               case "$searchdir" in
+                 */lib64/ | */lib64 ) acl_libdirstem=lib64 ;;
+                 */../ | */.. )
+                   # Better ignore directories of this form. They are misleading.
+                   ;;
+                 *) searchdir=`cd "$searchdir" && pwd`
+                    case "$searchdir" in
+                      */lib64 ) acl_libdirstem=lib64 ;;
+                    esac ;;
+               esac
+             fi
+           done
+           IFS="$acl_save_IFS"
+         fi
+         ;;
+     esac
+     test -n "$acl_libdirstem2" || acl_libdirstem2="$acl_libdirstem"
+     acl_cv_libdirstems="$acl_libdirstem,$acl_libdirstem2"
+    ])
+  # Decompose acl_cv_libdirstems into acl_libdirstem and acl_libdirstem2.
+  acl_libdirstem=`echo "$acl_cv_libdirstems" | sed -e 's/,.*//'`
+  acl_libdirstem2=`echo "$acl_cv_libdirstems" | sed -e '/,/s/.*,//'`
+])
index 925aee3e9d67506ade302aee4ea519b5288c4076..e9ac1b9e3472115c8cc954d7609217b446e5b8ea 100644 (file)
@@ -34,6 +34,11 @@ if ( HS_FOUND )
     LIST(APPEND EXTERNAL_INCLUDES ${HS_INCLUDE_DIRS})
 endif ()
 
+if ( ICONV_FOUND )
+    LIST(APPEND EXTERNAL_LIBRARIES ${ICONV_LIBRARY})
+    LIST(APPEND EXTERNAL_INCLUDES ${ICONV_INCLUDE_DIR})
+endif ()
+
 include_directories(BEFORE ${LUAJIT_INCLUDE_DIR})
 include_directories(AFTER ${EXTERNAL_INCLUDES})
 
index f542a632b00ce9a52c9d1032a0c1412825ab227d..217ba26e987c9d0bdf04d29ad91c53b7f5a62407 100644 (file)
@@ -27,6 +27,7 @@
 // and configurations.
 
 #include <string>
+#include <cstring>
 
 #include "main/snort_types.h"
 
 #define     FILE_ALL_ON                          0xFFFFFFFF
 #define     FILE_ALL_OFF                         0x00000000
 
-
 #define     FILE_RESUME_BLOCK                    0x01
 #define     FILE_RESUME_LOG                      0x02
 
+#define UTF_16_LE_BOM "\xFF\xFE"
+#define UTF_16_LE_BOM_LEN 2
+
 enum FileVerdict
 {
     FILE_VERDICT_UNKNOWN = 0,
@@ -90,8 +93,14 @@ enum FileProcessType
 
 enum FileDirection
 {
-   FILE_DOWNLOAD,
-   FILE_UPLOAD
+    FILE_DOWNLOAD,
+    FILE_UPLOAD
+};
+
+enum FileCharEncoding
+{
+    SNORT_CHAR_ENCODING_ASCII,
+    SNORT_CHAR_ENCODING_UTF_16LE
 };
 
 struct FileState
@@ -138,6 +147,18 @@ inline bool isFileEnd(FilePosition position)
     return ((position == SNORT_FILE_END) || (position == SNORT_FILE_FULL));
 }
 
+inline FileCharEncoding get_character_encoding(const char* file_name, size_t length)
+{
+    FileCharEncoding encoding = SNORT_CHAR_ENCODING_ASCII;
+    if (length >= UTF_16_LE_BOM_LEN)
+    {
+        if (memcmp(file_name, UTF_16_LE_BOM, UTF_16_LE_BOM_LEN) == 0)
+            encoding = SNORT_CHAR_ENCODING_UTF_16LE;
+    }
+
+    return encoding;
+}
+
 SO_PUBLIC uint64_t get_file_processed_size(class Flow* flow);
 FilePosition get_file_position(struct Packet* pkt);
 
index 2550fee161b65ec5554c155adb465b9407384c31..aa8c4073c69f0e386e51c40a9ac7fe76a9a43be6 100644 (file)
@@ -39,7 +39,9 @@
 #include "main/snort_config.h"
 #include "managers/inspector_manager.h"
 #include "utils/util.h"
+#include "utils/util_utf.h"
 
+#include "file_api.h"
 #include "file_capture.h"
 #include "file_config.h"
 #include "file_enforcer.h"
 #include "file_segment.h"
 #include "file_stats.h"
 
+// Convert UTF16-LE file name to UTF-8.
+// Returns allocated name. Caller responsible for freeing the buffer.
+char* FileContext::get_UTF8_fname(size_t* converted_len)
+{
+    FileCharEncoding encoding = get_character_encoding(file_name.c_str(), file_name.length());
+    char* outbuf = nullptr;
+    if (encoding == SNORT_CHAR_ENCODING_UTF_16LE)
+    {
+#ifdef HAVE_ICONV
+        // UTF-16LE takes 2 or 4 bytes per charecter, UTF-8 can take max 4
+        const size_t outbytesleft = (file_name.length() - UTF_16_LE_BOM_LEN) * 2;
+        char* inbuf = (char*)snort_alloc(file_name.length());
+        memcpy(inbuf, file_name.c_str(), file_name.length());
+        outbuf = (char*)snort_alloc(outbytesleft + 1);
+        char* const buf_start = outbuf;
+        outbuf = UtfDecodeSession::convert_character_encoding("UTF-8", "UTF-16LE", inbuf + UTF_16_LE_BOM_LEN,
+            outbuf, file_name.length() - UTF_16_LE_BOM_LEN, outbytesleft, converted_len);
+        snort_free(inbuf);
+        if (outbuf == nullptr)
+        {
+            snort_free(buf_start);
+            return nullptr;
+        }
+#else
+        *converted_len = (file_name.length()- UTF_16_LE_BOM_LEN) >> 1;
+        outbuf = (char*)snort_alloc(*converted_len + 1);
+        uint32_t i, k= 0;
+        for ( i = UTF_16_LE_BOM_LEN; i < file_name.length(); i+=2, k++)
+            outbuf[k] = (char)file_name[i];
+        outbuf[k] = 0;
+#endif
+    }
+    return outbuf;
+}
+
 FileInfo::~FileInfo ()
 {
     if (sha256)
@@ -430,13 +467,13 @@ void FileContext::process_file_signature_sha256(const uint8_t* file_data, int si
             file_signature_context = snort_calloc(sizeof(SHA256_CTX));
         SHA256_Init((SHA256_CTX*)file_signature_context);
         SHA256_Update((SHA256_CTX*)file_signature_context, file_data, data_size);
-        if(file_state.sig_state == FILE_SIG_FLUSH)
+        if (file_state.sig_state == FILE_SIG_FLUSH)
         {
             static uint8_t file_signature_context_backup[sizeof(SHA256_CTX)];
             sha256 = (uint8_t*)snort_alloc(SHA256_HASH_SIZE);
             memcpy(file_signature_context_backup, file_signature_context, sizeof(SHA256_CTX));
 
-            SHA256_Final(sha256, (SHA256_CTX *)file_signature_context);
+            SHA256_Final(sha256, (SHA256_CTX*)file_signature_context);
             memcpy(file_signature_context, file_signature_context_backup, sizeof(SHA256_CTX));
         }
         break;
@@ -445,14 +482,14 @@ void FileContext::process_file_signature_sha256(const uint8_t* file_data, int si
         if (!file_signature_context)
             return;
         SHA256_Update((SHA256_CTX*)file_signature_context, file_data, data_size);
-        if(file_state.sig_state == FILE_SIG_FLUSH)
+        if (file_state.sig_state == FILE_SIG_FLUSH)
         {
             static uint8_t file_signature_context_backup[sizeof(SHA256_CTX)];
             if ( !sha256 )
                 sha256 = (uint8_t*)snort_alloc(SHA256_HASH_SIZE);
             memcpy(file_signature_context_backup, file_signature_context, sizeof(SHA256_CTX));
 
-            SHA256_Final(sha256, (SHA256_CTX *)file_signature_context);
+            SHA256_Final(sha256, (SHA256_CTX*)file_signature_context);
             memcpy(file_signature_context, file_signature_context_backup, sizeof(SHA256_CTX));
         }
 
@@ -643,9 +680,51 @@ void FileContext::print_file_sha256(std::ostream& log)
     log.flags(f);
 }
 
+void FileContext::print_file_name(std::ostream& log)
+{
+    if (file_name.length() <= 0)
+        return;
+
+    size_t fname_len = file_name.length();
+    char* outbuf = get_UTF8_fname(&fname_len);
+    const char* fname  = (outbuf != nullptr) ? outbuf : file_name.c_str();
+
+    log << "File name: ";
+
+    size_t pos = 0;
+    while (pos < fname_len)
+    {
+        if (isprint((int)fname[pos]))
+        {
+            log << fname[pos];
+            pos++;
+        }
+        else
+        {
+            log << "|";
+            bool add_space = false;
+            while ((pos < fname_len) && !isprint((int)fname[pos]))
+            {
+                int ch = 0xff & fname[pos];
+                if (add_space)
+                    log << " ";
+                else
+                    add_space = true;
+                log << std::uppercase << std::setfill('0') << std::setw(2) << std::hex << ch;
+                pos++;
+            }
+            log << "|" << std::dec;
+        }
+    }
+    log << std::endl;
+
+    if (outbuf)
+        snort_free(outbuf);
+}
+
 void FileContext::print(std::ostream& log)
 {
-    log << "File name: " << file_name << std::endl;
+    print_file_name(log);
     log << "File type: " << file_config->file_type_name(file_type_id)
         << '('<< file_type_id  << ')' << std::endl;
     log << "File size: " << file_size << std::endl;
index 25ab059e5c6231074ba7aacb78a5bbdaef3b805f..dac04f2265967c37edb20a8ce6fc776cd71372e5 100644 (file)
@@ -131,8 +131,10 @@ public:
     uint64_t get_processed_bytes();
 
     void print_file_sha256(std::ostream&);
+    void print_file_name(std::ostream&);
     static void print_file_data(FILE* fp, const uint8_t* data, int len, int max_depth);
     void print(std::ostream&);
+    char* get_UTF8_fname(size_t* converted_len);
 
 private:
     bool file_type_enabled = false;
index 55f7b63bae085de8dfc8e8c298ccadc3498f1c8f..7c4993fa3395cb6a84d3a92833fe837b60d9822e 100644 (file)
@@ -95,28 +95,43 @@ void LogHandler::log_file_name(TextLog* log, FileContext* file)
     if (name.length() <= 0)
         return;
 
-    size_t start = name.rfind('/');
-
-    // Move beyond /
-    if (start)
-        start++;
+    size_t fname_len = name.length();
+    char* outbuf = file->get_UTF8_fname(&fname_len);
+    const char* fname = (outbuf != nullptr) ? outbuf : name.c_str();
 
     TextLog_Puts(log, "[Name: ");
     TextLog_Putc(log, '"');
 
-    for (size_t i = start; i < name.length(); i++)
+    size_t pos = 0;
+    while (pos < fname_len)
     {
-        if ( name[i] > 0x1F && name[i] < 0x7F) /* printable */
+        if (isprint((int)fname[pos]))
         {
-            TextLog_Putc(log, name[i]);
+            TextLog_Putc(log, fname[pos]);
+            pos++;
         }
-        else /* not printable */
+        else
         {
-            TextLog_Putc(log, '.');
+            TextLog_Putc(log, '|');
+            bool add_space = false;
+            while ((pos < fname_len) && !isprint((int)fname[pos]))
+            {
+                if (add_space)
+                    TextLog_Print(log, " %02X", (uint8_t)fname[pos]);
+                else
+                {
+                    TextLog_Print(log, "%02X", (uint8_t)fname[pos]);
+                    add_space = true;
+                }
+                pos++;
+            }
+            TextLog_Putc(log, '|');
         }
     }
 
     TextLog_Puts(log, "\"] ");
+    if (outbuf)
+        snort_free(outbuf);
 }
 
 void LogHandler::handle(DataEvent&, Flow* f)
@@ -291,7 +306,7 @@ static const InspectApi fl_api
         mod_dtor
     },
     IT_PASSIVE,
-    (uint16_t) PktType::NONE,
+    (uint16_t)PktType::NONE,
     nullptr, // buffers
     nullptr, // service
     nullptr, // pinit
index 68da3c09a25d49565327a1c51f358ef736616053..93ecca43a92eeafb2bee5a38f68821d207127177 100644 (file)
@@ -394,6 +394,7 @@ struct DCE2_SmbRequestTracker
     // Used for requests to cache data that will ultimately end up in
     // the file tracker upon response.
     char* file_name;
+    uint16_t file_name_size;
     uint64_t file_size;
     uint64_t file_offset;
     bool sequential_only;
index 45dd6f40f0b25b7bde401f059f926a8fcf6b3d6c..b3d9b1158b115d74d49e13fc5fb47e87478250f7 100644 (file)
 static void DCE2_Smb2Inspect(DCE2_SmbSsnData* ssd, const Smb2Hdr* smb_hdr,
     const uint8_t* end);
 
-static char* DCE2_Smb2GetFileName(const uint8_t* data,
-    uint32_t data_len, bool unicode, bool file_name_only)
-{
-    char* str;
-    uint32_t path_end, name_start, str_len = unicode ? data_len - 1 : data_len;
-    const uint8_t inc = unicode ? 2 : 1;
-
-    if (data_len < inc)
-        return nullptr;
-
-    // Move forward.  Don't know if the end of data is actually
-    // the end of the string.
-    for (path_end = 0, name_start = 0; path_end < str_len; path_end += inc)
-    {
-        uint16_t uchar = unicode ? alignedNtohs((uint16_t*)(data + path_end)) : data[path_end];
-
-        if (uchar == 0)
-            break;
-        else if (file_name_only && ((uchar == 0x002F) || (uchar == 0x005C)))  // slash and
-                                                                              // back-slash
-            name_start = path_end + inc;
-    }
-
-    // Only got a NULL byte or nothing after slash/back-slash or too big.
-    if ((path_end == 0) || (name_start == path_end)
-        || (file_name_only && (path_end > DCE2_SMB_MAX_COMP_LEN))
-        || (path_end > DCE2_SMB_MAX_PATH_LEN))
-        return nullptr;
-
-    str = (char*)snort_calloc(((path_end-name_start)>>(inc-1))+1);
-
-    uint32_t ind;
-    for (ind = 0; name_start < path_end; name_start += inc, ind++)
-    {
-        if ((int)data[name_start])
-            str[ind] = (char)data[name_start];
-        else
-            str[ind] = '.';
-    }
-
-    str[ind] = 0;
-
-    return str;
-}
-
 static inline uint32_t Smb2Tid(const Smb2Hdr* hdr)
 {
     return alignedNtohl(&(((Smb2SyncHdr*)hdr)->tree_id));
@@ -360,10 +315,10 @@ static void DCE2_Smb2CreateRequest(DCE2_SmbSsnData* ssd, const Smb2Hdr*,
         if (ssd->ftracker.file_name)
         {
             snort_free((void*)ssd->ftracker.file_name);
+            ssd->ftracker.file_name_size = 0;
         }
-        ssd->ftracker.file_name = DCE2_Smb2GetFileName(file_data, size, true, false);
-        if (ssd->ftracker.file_name)
-            ssd->ftracker.file_name_size = strlen(ssd->ftracker.file_name);
+        ssd->ftracker.file_name = DCE2_SmbGetFileName(file_data, size, true,
+            &ssd->ftracker.file_name_size);
     }
 }
 
@@ -843,7 +798,7 @@ DCE2_SmbVersion DCE2_Smb2Version(const Packet* p)
 {
     /* Only check reassembled SMB2 packet*/
     if ( p->has_paf_payload() and
-        (p->dsize > sizeof(NbssHdr) + 4) )  // DCE2_SMB_ID is u32
+        (p->dsize > sizeof(NbssHdr) + 4) ) // DCE2_SMB_ID is u32
     {
         Smb2Hdr* smb_hdr = (Smb2Hdr*)(p->data + sizeof(NbssHdr));
         uint32_t smb_version_id = SmbId((SmbNtHdr*)smb_hdr);
index dc68211243a33a9c663034492887827ef237a599..39fff889f5de2ca2b5cd71cc582da01705721358 100644 (file)
@@ -542,8 +542,7 @@ DCE2_Ret DCE2_SmbOpen(DCE2_SmbSsnData* ssd, const SmbNtHdr* smb_hdr,
         if (ftracker == nullptr)
             return DCE2_RET__ERROR;
 
-        ftracker->file_name = ssd->cur_rtracker->file_name;
-        ssd->cur_rtracker->file_name = nullptr;
+        DCE2_Update_Ftracker_from_ReqTracker(ftracker, ssd->cur_rtracker);
 
         if (!ftracker->is_ipc)
         {
@@ -566,7 +565,8 @@ DCE2_Ret DCE2_SmbOpen(DCE2_SmbSsnData* ssd, const SmbNtHdr* smb_hdr,
         DCE2_MOVE(nb_ptr, nb_len, 1);
 
         ssd->cur_rtracker->file_name =
-            DCE2_SmbGetString(nb_ptr, nb_len, SmbUnicode(smb_hdr), false);
+            DCE2_SmbGetFileName(nb_ptr, nb_len, SmbUnicode(smb_hdr),
+            &ssd->cur_rtracker->file_name_size);
     }
 
     return DCE2_RET__SUCCESS;
@@ -588,8 +588,7 @@ DCE2_Ret DCE2_SmbCreate(DCE2_SmbSsnData* ssd, const SmbNtHdr* smb_hdr,
         if (ftracker == nullptr)
             return DCE2_RET__ERROR;
 
-        ftracker->file_name = ssd->cur_rtracker->file_name;
-        ssd->cur_rtracker->file_name = nullptr;
+        DCE2_Update_Ftracker_from_ReqTracker(ftracker, ssd->cur_rtracker);
 
         // Command creates or opens and truncates file to 0 so assume
         // upload.
@@ -623,7 +622,8 @@ DCE2_Ret DCE2_SmbCreate(DCE2_SmbSsnData* ssd, const SmbNtHdr* smb_hdr,
         DCE2_MOVE(nb_ptr, nb_len, 1);
 
         ssd->cur_rtracker->file_name =
-            DCE2_SmbGetString(nb_ptr, nb_len, SmbUnicode(smb_hdr), false);
+            DCE2_SmbGetFileName(nb_ptr, nb_len, SmbUnicode(smb_hdr),
+            &ssd->cur_rtracker->file_name_size);
     }
 
     return DCE2_RET__SUCCESS;
@@ -816,8 +816,7 @@ DCE2_Ret DCE2_SmbCreateNew(DCE2_SmbSsnData* ssd, const SmbNtHdr* smb_hdr,
         if (ftracker == nullptr)
             return DCE2_RET__ERROR;
 
-        ftracker->file_name = ssd->cur_rtracker->file_name;
-        ssd->cur_rtracker->file_name = nullptr;
+        DCE2_Update_Ftracker_from_ReqTracker(ftracker, ssd->cur_rtracker);
 
         // Command creates a new file so assume upload.
         if (!ftracker->is_ipc)
@@ -850,7 +849,8 @@ DCE2_Ret DCE2_SmbCreateNew(DCE2_SmbSsnData* ssd, const SmbNtHdr* smb_hdr,
         DCE2_MOVE(nb_ptr, nb_len, 1);
 
         ssd->cur_rtracker->file_name =
-            DCE2_SmbGetString(nb_ptr, nb_len, SmbUnicode(smb_hdr), false);
+            DCE2_SmbGetFileName(nb_ptr, nb_len, SmbUnicode(smb_hdr),
+            &ssd->cur_rtracker->file_name_size);
     }
 
     return DCE2_RET__SUCCESS;
@@ -1010,8 +1010,7 @@ DCE2_Ret DCE2_SmbOpenAndX(DCE2_SmbSsnData* ssd, const SmbNtHdr* smb_hdr,
                 return DCE2_RET__ERROR;
         }
 
-        ftracker->file_name = ssd->cur_rtracker->file_name;
-        ssd->cur_rtracker->file_name = nullptr;
+        DCE2_Update_Ftracker_from_ReqTracker(ftracker, ssd->cur_rtracker);
 
         if (!ftracker->is_ipc)
         {
@@ -1061,7 +1060,7 @@ DCE2_Ret DCE2_SmbOpenAndX(DCE2_SmbSsnData* ssd, const SmbNtHdr* smb_hdr,
         if (ssd->cur_rtracker->file_name == nullptr)
         {
             ssd->cur_rtracker->file_name =
-                DCE2_SmbGetString(nb_ptr, nb_len, unicode, false);
+                DCE2_SmbGetFileName(nb_ptr, nb_len, unicode, &ssd->cur_rtracker->file_name_size);
         }
     }
 
@@ -1946,11 +1945,7 @@ DCE2_Ret DCE2_SmbNtCreateAndX(DCE2_SmbSsnData* ssd, const SmbNtHdr* smb_hdr,
                 return DCE2_RET__ERROR;
         }
 
-        ftracker->file_name = ssd->cur_rtracker->file_name;
-        ssd->cur_rtracker->file_name = nullptr;
-
-        DebugFormat(DEBUG_DCE_SMB, "File name: %s\n",
-            (ftracker->file_name == nullptr) ? "nullptr" : ftracker->file_name);
+        DCE2_Update_Ftracker_from_ReqTracker(ftracker, ssd->cur_rtracker);
 
         if (!ftracker->is_ipc)
         {
@@ -2016,7 +2011,8 @@ DCE2_Ret DCE2_SmbNtCreateAndX(DCE2_SmbSsnData* ssd, const SmbNtHdr* smb_hdr,
         if (ssd->cur_rtracker->file_name == nullptr)
         {
             ssd->cur_rtracker->file_name =
-                DCE2_SmbGetString(nb_ptr, file_name_length, unicode, false);
+                DCE2_SmbGetFileName(nb_ptr, file_name_length, unicode,
+                &ssd->cur_rtracker->file_name_size);
         }
 
         if (is_ipc)
index a02129d9cf8faf4d9b7a9cdbd637e6599f316a6e..2073fa5053a5fdf0f6ff731f82cb56b489b7f823 100644 (file)
@@ -291,7 +291,7 @@ static DCE2_Ret DCE2_SmbNtTransactCreateReq(DCE2_SmbSsnData* ssd,
     DCE2_MOVE(param_ptr, param_len, pad);
 
     ssd->cur_rtracker->file_name =
-        DCE2_SmbGetString(param_ptr, file_name_length, unicode, false);
+      DCE2_SmbGetFileName(param_ptr, file_name_length, unicode, &ssd->cur_rtracker->file_name_size);
 
     return DCE2_RET__SUCCESS;
 }
@@ -1000,7 +1000,7 @@ static DCE2_Ret DCE2_SmbTrans2Open2Req(DCE2_SmbSsnData* ssd,
     DCE2_MOVE(param_ptr, param_len, sizeof(SmbTrans2Open2ReqParams));
 
     ssd->cur_rtracker->file_name =
-        DCE2_SmbGetString(param_ptr, param_len, unicode, false);
+      DCE2_SmbGetFileName(param_ptr, param_len, unicode, &ssd->cur_rtracker->file_name_size);
 
     return DCE2_RET__SUCCESS;
 }
@@ -1350,8 +1350,7 @@ DCE2_Ret DCE2_SmbTransaction2(DCE2_SmbSsnData* ssd, const SmbNtHdr* smb_hdr,
             if (ftracker == nullptr)
                 return DCE2_RET__ERROR;
 
-            ftracker->file_name = ssd->cur_rtracker->file_name;
-            ssd->cur_rtracker->file_name = nullptr;
+            DCE2_Update_Ftracker_from_ReqTracker(ftracker, ssd->cur_rtracker);
 
             if (!ftracker->is_ipc)
             {
@@ -1599,8 +1598,7 @@ DCE2_Ret DCE2_SmbNtTransact(DCE2_SmbSsnData* ssd, const SmbNtHdr* smb_hdr,
         if (ftracker == nullptr)
             return DCE2_RET__ERROR;
 
-        ftracker->file_name = ssd->cur_rtracker->file_name;
-        ssd->cur_rtracker->file_name = nullptr;
+               DCE2_Update_Ftracker_from_ReqTracker(ftracker, ssd->cur_rtracker);
 
         if (!ftracker->is_ipc)
         {
index 2c16089e166b63a637f11a89c226340414ca3ccb..b8f4871442b5e9a9a73e98d753eb595c07809a75 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "detection/detection_engine.h"
 #include "detection/detection_util.h"
+#include "file_api/file_api.h"
 #include "main/snort.h"
 #include "packet_io/active.h"
 #include "utils/util.h"
@@ -95,67 +96,45 @@ bool DCE2_SmbIsTidIPC(DCE2_SmbSsnData* ssd, const uint16_t tid)
     return false;
 }
 
-/********************************************************************
- * Function: DCE2_SmbGetString()
- *
- * Purpose:
- *  Parses data passed in and returns an ASCII string.  True
- *  unicode characters are replaced with a '.'
- *
- * Arguments:
- *  const uint8_t *  - pointer to data
- *  uint32_t         - data length
- *  bool             - true if the data is unicode (UTF-16LE)
- *  bool             - true if the function should only return the
- *                     file name instead of the entire path
- *
- * Returns:
- *  char *  - NULL terminated ASCII string
- *
- ********************************************************************/
-char* DCE2_SmbGetString(const uint8_t* data,
-    uint32_t data_len, bool unicode, bool get_file)
+// Extract file name from data. Supports ASCII and UTF-16LE.
+// Returns byte stream (ASCII or UTF-16LE with BOM)
+char* DCE2_SmbGetFileName(const uint8_t* data, uint32_t data_len, bool unicode,
+    uint16_t* file_name_len)
 {
-    char* str;
-    uint32_t i, j, k = unicode ? data_len - 1 : data_len;
-    uint8_t inc = unicode ? 2 : 1;
-
+    const uint8_t inc = unicode ? 2 : 1;
     if (data_len < inc)
         return nullptr;
 
+    const uint32_t max_len =  unicode ? data_len - 1 : data_len;
     // Move forward.  Don't know if the end of data is actually
     // the end of the string.
-    for (i = 0, j = 0; i < k; i += inc)
+    uint32_t i;
+    for (i = 0; i < max_len; i += inc)
     {
         uint16_t uchar = unicode ? extract_16bits(data + i) : data[i];
-
         if (uchar == 0)
             break;
-        else if (get_file && ((uchar == 0x002F) || (uchar == 0x005C)))  // slash and back-slash
-            j = i + inc;
     }
 
-    // Only got a NULL byte or nothing after slash/back-slash or too big.
-    if ((i == 0) || (j == i)
-        || (get_file && (i > DCE2_SMB_MAX_COMP_LEN))
-        || (i > DCE2_SMB_MAX_PATH_LEN))
-        return nullptr;
+    char* fname = nullptr;
+    const uint32_t real_len = i;
 
-    str = (char*)snort_calloc(((i-j)>>(inc-1))+1);
-    if (str == nullptr)
-        return nullptr;
-
-    for (k = 0; j < i; j += inc, k++)
+    if (unicode)
     {
-        if (isprint((int)data[j]))
-            str[k] = (char)data[j];
-        else
-            str[k] = '.';
+        fname = (char*)snort_calloc(real_len + UTF_16_LE_BOM_LEN + 2);
+        memcpy(fname, UTF_16_LE_BOM, UTF_16_LE_BOM_LEN);//Prepend with BOM
+        memcpy(fname + UTF_16_LE_BOM_LEN, data, real_len);
+        *file_name_len = real_len + UTF_16_LE_BOM_LEN;
+    }
+    else
+    {
+        fname = (char*)snort_alloc(real_len + 1);
+        memcpy(fname, data, real_len);
+        fname[real_len] = 0;
+        *file_name_len = real_len;
     }
 
-    str[k] = 0;
-
-    return str;
+    return fname;
 }
 
 int DCE2_SmbUidTidFidCompare(const void* a, const void* b)
@@ -737,6 +716,7 @@ void DCE2_SmbCleanRequestTracker(DCE2_SmbRequestTracker* rtracker)
     {
         snort_free((void*)rtracker->file_name);
         rtracker->file_name = nullptr;
+        rtracker->file_name_size = 0;
     }
 }
 
@@ -1480,10 +1460,10 @@ FileVerdict DCE2_get_file_verdict(DCE2_SmbSsnData* ssd)
 
 void DCE2_SmbInitDeletePdu(void)
 {
-    NbssHdr *nb_hdr = (NbssHdr *)dce2_smb_delete_pdu;
-    SmbNtHdr *smb_hdr = (SmbNtHdr *)((uint8_t *)nb_hdr + sizeof(*nb_hdr));
-    SmbDeleteReq *del_req = (SmbDeleteReq *)((uint8_t *)smb_hdr + sizeof(*smb_hdr));
-    uint8_t *del_req_fmt = (uint8_t *)del_req + sizeof(*del_req);
+    NbssHdr* nb_hdr = (NbssHdr*)dce2_smb_delete_pdu;
+    SmbNtHdr* smb_hdr = (SmbNtHdr*)((uint8_t*)nb_hdr + sizeof(*nb_hdr));
+    SmbDeleteReq* del_req = (SmbDeleteReq*)((uint8_t*)smb_hdr + sizeof(*smb_hdr));
+    uint8_t* del_req_fmt = (uint8_t*)del_req + sizeof(*del_req);
     uint16_t smb_flg2 = 0x4001;
     uint16_t search_attrs = 0x0006;
 
@@ -1492,7 +1472,7 @@ void DCE2_SmbInitDeletePdu(void)
     nb_hdr->type = 0;
     nb_hdr->flags = 0;
 
-    memcpy((void *)smb_hdr->smb_idf, (void *)"\xffSMB", sizeof(smb_hdr->smb_idf));
+    memcpy((void*)smb_hdr->smb_idf, (void*)"\xffSMB", sizeof(smb_hdr->smb_idf));
     smb_hdr->smb_com = SMB_COM_DELETE;
     smb_hdr->smb_status.nt_status = 0;
     //smb_hdr->smb_flg = 0x18;
@@ -1508,26 +1488,39 @@ void DCE2_SmbInitDeletePdu(void)
     *del_req_fmt = SMB_FMT__ASCII;
 }
 
-static void DCE2_SmbInjectDeletePdu(DCE2_SmbSsnData *ssd, DCE2_SmbFileTracker *ftracker)
+static void DCE2_SmbInjectDeletePdu(DCE2_SmbSsnData* ssd, DCE2_SmbFileTracker* ftracker)
 {
     Packet* inject_pkt = Snort::get_packet();
-    if( inject_pkt->flow != ssd->sd.wire_pkt->flow )
+    if ( inject_pkt->flow != ssd->sd.wire_pkt->flow )
         return;
 
-    NbssHdr *nb_hdr = (NbssHdr *)dce2_smb_delete_pdu;
-    SmbNtHdr *smb_hdr = (SmbNtHdr *)((uint8_t *)nb_hdr + sizeof(*nb_hdr));
-    SmbDeleteReq *del_req = (SmbDeleteReq *)((uint8_t *)smb_hdr + sizeof(*smb_hdr));
-    char *del_filename = (char *)((uint8_t *)del_req + sizeof(*del_req) + 1);
-    uint16_t file_name_len = strlen(ftracker->file_name) + 1;
+    NbssHdr* nb_hdr = (NbssHdr*)dce2_smb_delete_pdu;
+    SmbNtHdr* smb_hdr = (SmbNtHdr*)((uint8_t*)nb_hdr + sizeof(*nb_hdr));
+    SmbDeleteReq* del_req = (SmbDeleteReq*)((uint8_t*)smb_hdr + sizeof(*smb_hdr));
+    char* del_filename = (char*)((uint8_t*)del_req + sizeof(*del_req) + 1);
+    FileCharEncoding encoding = get_character_encoding(ftracker->file_name,
+        ftracker->file_name_size);
+    uint16_t file_name_len;
+
+    if (encoding == SNORT_CHAR_ENCODING_UTF_16LE)
+    {
+        file_name_len = ftracker->file_name_size - UTF_16_LE_BOM_LEN + 2;
+        uint16_t smb_flg2 = 0xC001;
+        smb_hdr->smb_flg2 = SmbHtons(&smb_flg2);
+    }
+    else
+    {
+        file_name_len = ftracker->file_name_size + 1;
+    }
 
     nb_hdr->length = htons(sizeof(*smb_hdr) + sizeof(*del_req) + 1 + file_name_len);
     uint32_t len = ntohs(nb_hdr->length) + sizeof(*nb_hdr);
     smb_hdr->smb_tid = SmbHtons(&ftracker->tid_v1);
     smb_hdr->smb_uid = SmbHtons(&ftracker->uid_v1);
     del_req->smb_bcc = 1 + file_name_len;
-    memcpy(del_filename, ftracker->file_name, file_name_len);
+    memcpy(del_filename, ftracker->file_name + UTF_16_LE_BOM_LEN, file_name_len);
 
-    Active::inject_data(inject_pkt, 0, (uint8_t *)nb_hdr, len);
+    Active::inject_data(inject_pkt, 0, (uint8_t*)nb_hdr, len);
 }
 
 static FileVerdict DCE2_SmbLookupFileVerdict(DCE2_SmbSsnData* ssd)
@@ -1559,7 +1552,6 @@ static void DCE2_SmbFinishFileBlockVerdict(DCE2_SmbSsnData* ssd)
 
     ssd->fb_ftracker = nullptr;
     ssd->block_pdus = false;
-
 }
 
 static void DCE2_SmbFinishFileAPI(DCE2_SmbSsnData* ssd)
@@ -1651,8 +1643,7 @@ static DCE2_Ret DCE2_SmbFileAPIProcess(DCE2_SmbSsnData* ssd,
         DCE2_SmbIsVerdictSuspend(upload, position)))
     {
         DebugFormat(DEBUG_DCE_SMB, "File API returned FAILURE "
-            "for \"%s\" (0x%02X) %s\n", ftracker->file_name,
-            ftracker->fid_v1, upload ? "UPLOAD" : "DOWNLOAD");
+            "for (0x%02X) %s\n", ftracker->fid_v1, upload ? "UPLOAD" : "DOWNLOAD");
 
         // Failure.  Abort tracking this file under file API
         return DCE2_RET__ERROR;
@@ -1660,13 +1651,12 @@ static DCE2_Ret DCE2_SmbFileAPIProcess(DCE2_SmbSsnData* ssd,
     else
     {
         DebugFormat(DEBUG_DCE_SMB, "File API returned SUCCESS "
-            "for \"%s\" (0x%02X) %s\n", ftracker->file_name,
-            ftracker->fid_v1, upload ? "UPLOAD" : "DOWNLOAD");
+            "for (0x%02X) %s\n", ftracker->fid_v1, upload ? "UPLOAD" : "DOWNLOAD");
 
         if (((position == SNORT_FILE_START) || (position == SNORT_FILE_FULL))
-            && (strlen(ftracker->file_name) != 0))
+            && (ftracker->file_name_size != 0))
         {
-            file_flows->set_file_name((uint8_t*)ftracker->file_name, strlen(ftracker->file_name));
+            file_flows->set_file_name((uint8_t*)ftracker->file_name, ftracker->file_name_size);
         }
 
         if ((position == SNORT_FILE_FULL) || (position == SNORT_FILE_END))
@@ -1676,7 +1666,7 @@ static DCE2_Ret DCE2_SmbFileAPIProcess(DCE2_SmbSsnData* ssd,
                 FileVerdict verdict = DCE2_get_file_verdict(ssd);
 
                 if ((verdict == FILE_VERDICT_BLOCK) || (verdict == FILE_VERDICT_REJECT)
-                        || (verdict == FILE_VERDICT_PENDING))
+                    || (verdict == FILE_VERDICT_PENDING))
                 {
                     ssd->fb_ftracker = ftracker;
                 }
@@ -2011,3 +2001,12 @@ static void DCE2_SmbSetNewFileAPIFileTracker(DCE2_SmbSsnData* ssd)
     ssd->fapi_ftracker = ftracker;
 }
 
+void DCE2_Update_Ftracker_from_ReqTracker(DCE2_SmbFileTracker* ftracker,
+    DCE2_SmbRequestTracker* cur_rtracker)
+{
+    ftracker->file_name = cur_rtracker->file_name;
+    ftracker->file_name_size = cur_rtracker->file_name_size;
+    cur_rtracker->file_name = nullptr;
+    cur_rtracker->file_name_size = 0;
+}
+
index b019b401ac6b3ef8ff6c78840c04f6888deb6293..7a9e459ce15dd6c1a9723a306d6b5197d8b1d702 100644 (file)
@@ -125,7 +125,7 @@ inline bool DCE2_ComInfoCanProcessCommand(const DCE2_SmbComInfo* com_info)
  * Function prototypes
  ********************************************************************/
 bool DCE2_SmbIsTidIPC(DCE2_SmbSsnData*, const uint16_t);
-char* DCE2_SmbGetString(const uint8_t*, uint32_t, bool, bool);
+char* DCE2_SmbGetFileName(const uint8_t *data, uint32_t data_len, bool unicode, uint16_t *file_name_len);
 int DCE2_SmbUidTidFidCompare(const void*, const void*);
 DCE2_Ret DCE2_SmbFindUid(DCE2_SmbSsnData*, const uint16_t);
 void DCE2_SmbInsertUid(DCE2_SmbSsnData*, const uint16_t);
@@ -179,6 +179,7 @@ void DCE2_SmbProcessFileData(DCE2_SmbSsnData* ssd,
 void DCE2_FileDetect();
 FileVerdict DCE2_get_file_verdict(DCE2_SmbSsnData* );
 void DCE2_SmbInitDeletePdu(void);
+void DCE2_Update_Ftracker_from_ReqTracker(DCE2_SmbFileTracker*, DCE2_SmbRequestTracker*);
 
 /********************************************************************
  * Inline functions
index 26f1915275915001129ec3525e662809fd5ce395..aed603f872d23bc49b1363b1378922c993d6c53c 100644 (file)
@@ -241,7 +241,7 @@ void HttpMsgBody::do_file_processing(Field& file_data)
             {
                 if (request != nullptr)
                 {
-                    const Field& transaction_uri = request->get_uri_norm_classic();
+                    const Field& transaction_uri = request->get_uri();
                     if (transaction_uri.length() > 0)
                     {
                         file_flows->set_file_name(transaction_uri.start(),
index 2f17b0edd604ade1e3a98886206fd806e7d7282a..416d57e16d79017ac3afcd0fcacdc913a3d449f3 100644 (file)
@@ -120,19 +120,19 @@ int DisplayBanner()
                            " All rights reserved.\n");
     LogMessage("           Copyright (C) 1998-2013 Sourcefire, Inc., et al.\n");
     LogMessage("           Using DAQ version %s\n", daq_version_string());
-    LogMessage("           Using %s\n", pcap_lib_version());
     LogMessage("           Using LuaJIT version %s\n", ljv);
+    LogMessage("           Using %s\n", SSLeay_version(SSLEAY_VERSION));
+    LogMessage("           Using %s\n", pcap_lib_version());
     LogMessage("           Using PCRE version %s\n", pcre_version());
     LogMessage("           Using ZLIB version %s\n", zlib_version);
-#ifdef HAVE_LZMA
-    LogMessage("           Using LZMA version %s\n", lzma_version_string());
+#ifdef HAVE_FLATBUFFERS
+    LogMessage("           Using %s\n", flatbuffers::flatbuffer_version_string);
 #endif
-    LogMessage("           Using %s\n", SSLeay_version(SSLEAY_VERSION));
 #ifdef HAVE_HYPERSCAN
     LogMessage("           Using Hyperscan version %s\n", hs_version());
 #endif
-#ifdef HAVE_FLATBUFFERS
-    LogMessage("           Using %s\n", flatbuffers::flatbuffer_version_string);
+#ifdef HAVE_LZMA
+    LogMessage("           Using LZMA version %s\n", lzma_version_string());
 #endif
     LogMessage("\n");
 
index 791ac619e12879a6b1e5b46ee7843b5373aa52f5..c8b4698f6db1c9440c18c94d08061f4dd721e326 100644 (file)
 #include <cassert>
 #include <cstring>
 
+#ifdef HAVE_ICONV
+#include <iconv.h>
+#endif
+
 #define DSTATE_FIRST 0
 #define DSTATE_SECOND 1
 #define DSTATE_THIRD 2
@@ -78,8 +82,8 @@ bool UtfDecodeSession::is_utf_encoding_present()
  * returns: true or false
  */
 
-bool UtfDecodeSession::DecodeUTF16LE(const uint8_t* src, unsigned int src_len, uint8_t* dst, unsigned int dst_len,
-    int* bytes_copied)
+bool UtfDecodeSession::DecodeUTF16LE(const uint8_t* src, unsigned int src_len, uint8_t* dst,
+    unsigned int dst_len, int* bytes_copied)
 {
     const uint8_t* src_index = src;
     uint8_t* dst_index = dst;
@@ -121,8 +125,8 @@ bool UtfDecodeSession::DecodeUTF16LE(const uint8_t* src, unsigned int src_len, u
  * returns: true or false
  */
 
-bool UtfDecodeSession::DecodeUTF16BE(const uint8_t* src, unsigned int src_len, uint8_t* dst, unsigned int dst_len,
-    int* bytes_copied)
+bool UtfDecodeSession::DecodeUTF16BE(const uint8_t* src, unsigned int src_len, uint8_t* dst,
+    unsigned int dst_len, int* bytes_copied)
 {
     const uint8_t* src_index = src;
     uint8_t* dst_index = dst;
@@ -164,8 +168,8 @@ bool UtfDecodeSession::DecodeUTF16BE(const uint8_t* src, unsigned int src_len, u
  * returns: true or false
  */
 
-bool UtfDecodeSession::DecodeUTF32LE(const uint8_t* src, unsigned int src_len, uint8_t* dst, unsigned int dst_len,
-    int* bytes_copied)
+bool UtfDecodeSession::DecodeUTF32LE(const uint8_t* src, unsigned int src_len, uint8_t* dst,
+    unsigned int dst_len, int* bytes_copied)
 {
     const uint8_t* src_index = src;
     uint8_t* dst_index = dst;
@@ -212,8 +216,8 @@ bool UtfDecodeSession::DecodeUTF32LE(const uint8_t* src, unsigned int src_len, u
  * returns: true or false
  */
 
-bool UtfDecodeSession::DecodeUTF32BE(const uint8_t* src, unsigned int src_len, uint8_t* dst, unsigned int dst_len,
-    int* bytes_copied)
+bool UtfDecodeSession::DecodeUTF32BE(const uint8_t* src, unsigned int src_len, uint8_t* dst,
+    unsigned int dst_len, int* bytes_copied)
 {
     const uint8_t* src_index = src;
     uint8_t* dst_index = dst;
@@ -246,7 +250,7 @@ bool UtfDecodeSession::DecodeUTF32BE(const uint8_t* src, unsigned int src_len, u
     return result;
 }
 
-void UtfDecodeSession::determine_charset(const uint8_t** src, unsigned int *src_len)
+void UtfDecodeSession::determine_charset(const uint8_t** src, unsigned intsrc_len)
 {
     CharsetCode charset;
     if (dstate.charset == CHARSET_UNKNOWN)
@@ -277,7 +281,6 @@ void UtfDecodeSession::determine_charset(const uint8_t** src, unsigned int *src_
                 charset = CHARSET_UTF16LE;
                 size = 2;
             }
-
             //  BOM (Byte Order Mark) was missing. Try to guess the encoding.
             else if (((*src)[0] == '\0') && ((*src)[2] == '\0') && ((*src)[3] != '\0'))
             {
@@ -318,13 +321,13 @@ void UtfDecodeSession::determine_charset(const uint8_t** src, unsigned int *src_
             charset = CHARSET_DEFAULT; // ensure we don't try again
         }
         set_decode_utf_state_charset(charset);
-
     }
 }
 
 /* Wrapper function for DecodeUTF{16,32}{LE,BE} */
 bool UtfDecodeSession::decode_utf(
-    const uint8_t* src, unsigned int src_len, uint8_t* dst, unsigned int dst_len, int* bytes_copied)
+    const uint8_t* src, unsigned int src_len, uint8_t* dst, unsigned int dst_len,
+    int* bytes_copied)
 {
     *bytes_copied = 0;
 
@@ -350,3 +353,34 @@ bool UtfDecodeSession::decode_utf(
     return true;
 }
 
+#ifdef HAVE_ICONV
+
+char* UtfDecodeSession::convert_character_encoding(const char* to_code, const char* from_code,
+    char* in_buf, char* out_buf, size_t in_bytes, size_t out_bytes, size_t* out_buf_length)
+{
+    iconv_t convert_encoding = iconv_open(to_code, from_code);
+    if (convert_encoding == (iconv_t)-1)
+        return nullptr;
+
+    char* out = out_buf;
+    size_t iconv_rval = iconv(convert_encoding, &in_buf, &in_bytes, &out, &out_bytes);
+    if (iconv_rval == (size_t)-1)
+        return nullptr;
+
+    *out = '\0';
+    *out_buf_length = (out - out_buf);
+
+    iconv_close(convert_encoding);
+    return out_buf;
+}
+
+#else
+
+char* UtfDecodeSession::convert_character_encoding(const char*, const char*,
+    char*, char*, size_t, size_t, size_t*)
+{
+    return nullptr;
+}
+
+#endif
+
index 1c07813067e6b5ce8d72fc67b4a2b67df776eabf..eade23ee31536be34c2f7970e4da0210a4b07577 100644 (file)
@@ -58,13 +58,17 @@ public:
     void set_decode_utf_state_charset(CharsetCode charset);
     CharsetCode get_decode_utf_state_charset();
     bool is_utf_encoding_present();
-    bool decode_utf(const uint8_t* src, unsigned int src_len, uint8_t* dst, unsigned int dst_len, int* bytes_copied);
+    bool decode_utf(const uint8_t* src, unsigned int src_len, uint8_t* dst, unsigned int dst_len,
+        int* bytes_copied);
+    static char* convert_character_encoding(const char* to_code, const char* from_code,
+        char* in_buf, char* out_buf, size_t in_bytes, size_t out_bytes, size_t* out_buf_length);
+
 private:
     decode_utf_state_t dstate;
     bool DecodeUTF16LE(const uint8_t* src, unsigned int src_len, uint8_t* dst, unsigned int dst_len, int* bytes_copied);
     bool DecodeUTF16BE(const uint8_t* src, unsigned int src_len, uint8_t* dst, unsigned int dst_len, int* bytes_copied);
     bool DecodeUTF32LE(const uint8_t* src, unsigned int src_len, uint8_t* dst, unsigned int dst_len, int* bytes_copied);
     bool DecodeUTF32BE(const uint8_t* src, unsigned int src_len, uint8_t* dst, unsigned int dst_len, int* bytes_copied);
-    void determine_charset(const uint8_t** src, unsigned int *src_len);
+    void determine_charset(const uint8_t** src, unsigned intsrc_len);
 };
 #endif