Ver código fonte

Use only US-ASCII charset when comparing stings as caseless as required by standard.
Comparisons for HTTP headers must not be affected by locale settings.

Evgeny Grin (Karlson2k) 10 anos atrás
pai
commit
ad9b3c3814

+ 5 - 0
ChangeLog

@@ -1,3 +1,8 @@
+Sat Jan 16 19:14:39 CET 2016
+	Use US-ASCII only (instead of user locale settings) when
+	performing caseless string comparison as required by
+	standard. -EG
+
 Tue Jan 12 16:10:09 CET 2016
 	Fixed declaraion of MHD_get_reason_phrase_for(). -EG
 

+ 54 - 0
configure.ac

@@ -86,6 +86,60 @@ MHD_LIBDEPS=""
 MHD_REQ_PRIVATE=''
 MHD_LIBDEPS_PKGCFG=''
 
+AC_CHECK_TYPE([_Bool],
+  [ AC_DEFINE([_MHD_bool],[_Bool],[Define to type which will be used as boolean type.]) ],
+  [
+    AC_CHECK_HEADER([stdbool.h], [ AC_DEFINE([HAVE_STDBOOL_H],[1],[Define to 1 if you have the <stdbool.h> header file and it's required for _MHD_bool.]) ])
+    AC_CHECK_TYPE([bool],
+      [ AC_DEFINE([_MHD_bool],[bool]) ],
+      [ AC_DEFINE([_MHD_bool],[int]) ],
+      [[
+        #ifdef HAVE_STDBOOL_H
+        #include <stdbool.h>
+        #endif
+      ]])
+  ])
+
+AC_MSG_CHECKING([[for function inline keywords suppoted by $CC]])
+save_CFLAGS="$CFLAGS"
+AX_APPEND_FLAG([[-Werror=attributes]])
+inln_prfx="none"
+# Prefer always inline functions
+for inln_prfx_chk in "inline __attribute__((always_inline))" __forceinline inline __inline__ __inline _inline _Inline; do
+  # Try to link to avoid "symbol undefined" problems at build time
+  AC_LINK_IFELSE(
+    [
+     AC_LANG_PROGRAM(
+       [[
+         #ifdef __cplusplus
+         choke me
+         #endif
+         #ifdef HAVE_STDBOOL_H
+         #include <stdbool.h>
+         #endif
+         static $inln_prfx_chk _MHD_bool cmpfn(int x, int y)
+         { return x > y; }
+         static $inln_prfx_chk int sumfn(int x, int y)
+         { return x + y; }
+       ]],[[
+       int a = 1, b = 100, c;
+       if (cmpfn(a, b))
+         c = sumfn(a, b);
+       else
+         c = 0 - sumfn(a, b);
+       ]])
+    ],
+    [[ inln_prfx="$inln_prfx_chk" ]])
+  test "x$inln_prfx" != "xnone" && break
+done
+AS_IF([[test "x$ac_cv_c_inline" != "xnone"]],
+      [
+       AC_DEFINE([INLINE_FUNC],[1],[Define to 1 if your C compiler supports inline functions.])
+       AC_DEFINE_UNQUOTED([_MHD_inline],[static $inln_prfx],[Define to prefix which will be used with MHD inline functions.])
+      ])
+AC_MSG_RESULT([[$inln_prfx]])
+CFLAGS="$save_CFLAGS"
+
 # Check system type
 AC_MSG_CHECKING([[for target host OS]])
 case "$host_os" in

+ 0 - 37
src/include/platform_interface.h

@@ -34,43 +34,6 @@
 /* *****************************
      General function mapping
    *****************************/
-#if !defined(_WIN32) || defined(__CYGWIN__)
-/**
- * Check two strings case-insensitive equality
- * @param a first string to check
- * @param b second string to check
- * @return boolean true if strings are equal, boolean false if strings are unequal
- */
-#define MHD_str_equal_caseless_(a,b) (0==strcasecmp((a),(b)))
-#else
-/**
- * Check two strings case-insensitive equality
- * @param a first string to check
- * @param b second string to check
- * @return boolean true if strings are equal, boolean false if strings are unequal
- */
-#define MHD_str_equal_caseless_(a,b) (0==_stricmp((a),(b)))
-#endif
-
-#if !defined(_WIN32) || defined(__CYGWIN__)
-/**
- * Check not more than n chars in two strings case-insensitive equality
- * @param a first string to check
- * @param b second string to check
- * @param n maximum number of chars to check
- * @return boolean true if strings are equal, boolean false if strings are unequal
- */
-#define MHD_str_equal_caseless_n_(a,b,n) (0==strncasecmp((a),(b),(n)))
-#else
-/**
- * Check not more than n chars in two strings case-insensitive equality
- * @param a first string to check
- * @param b second string to check
- * @param n maximum number of chars to check
- * @return boolean true if strings are equal, boolean false if strings are unequal
- */
-#define MHD_str_equal_caseless_n_(a,b,n) (0==_strnicmp((a),(b),(n)))
-#endif
 
 /* Platform-independent snprintf name */
 #if defined(HAVE_SNPRINTF)

+ 1 - 0
src/microhttpd/Makefile.am

@@ -65,6 +65,7 @@ libmicrohttpd_la_SOURCES = \
   mhd_mono_clock.c mhd_mono_clock.h \
   mhd_limits.h mhd_byteorder.h \
   sysfdsetsize.c sysfdsetsize.h \
+  mhd_str.c mhd_str.h \
   response.c response.h
 libmicrohttpd_la_CPPFLAGS = \
   $(AM_CPPFLAGS) $(MHD_LIB_CPPFLAGS) \

+ 1 - 0
src/microhttpd/connection.c

@@ -30,6 +30,7 @@
 #include "memorypool.h"
 #include "response.h"
 #include "mhd_mono_clock.h"
+#include "mhd_str.h"
 
 #if HAVE_NETINET_TCP_H
 /* for TCP_CORK */

+ 1 - 0
src/microhttpd/digestauth.c

@@ -27,6 +27,7 @@
 #include "internal.h"
 #include "md5.h"
 #include "mhd_mono_clock.h"
+#include "mhd_str.h"
 
 #if defined(_WIN32) && defined(MHD_W32_MUTEX_)
 #ifndef WIN32_LEAN_AND_MEAN

+ 231 - 0
src/microhttpd/mhd_str.c

@@ -0,0 +1,231 @@
+/*
+  This file is part of libmicrohttpd
+  Copyright (C) 2015 Karlson2k (Evgeny Grin)
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/**
+ * @file microhttpd/mhd_str.c
+ * @brief  Functions implementations for string manipulating
+ * @author Karlson2k (Evgeny Grin)
+ */
+
+#include "mhd_str.h"
+
+#include "MHD_config.h"
+
+#ifdef HAVE_STDBOOL_H
+#include <stdbool.h>
+#endif
+
+/*
+ * Block of functions/macros that use US-ASCII charset as required by HTTP
+ * standards. Not affected by current locale settings.
+ */
+
+#ifdef INLINE_FUNC
+ /**
+ * Check whether character is lower case letter in US-ASCII
+ * @param c character to check
+ * @return non-zero if character is lower case letter, zero otherwise
+ */
+_MHD_inline _MHD_bool
+isasciilower (char c)
+{
+  return c >= 'a' && c <= 'z';
+}
+
+/**
+ * Check whether character is upper case letter in US-ASCII
+ * @param c character to check
+ * @return non-zero if character is upper case letter, zero otherwise
+ */
+_MHD_inline _MHD_bool
+isasciiupper (char c)
+{
+  return c >= 'A' && c <= 'Z';
+}
+
+/**
+ * Check whether character is letter in US-ASCII
+ * @param c character to check
+ * @return non-zero if character is letter in US-ASCII, zero otherwise
+ */
+_MHD_inline _MHD_bool
+isasciialpha (char c)
+{
+  return isasciilower (c) || isasciiupper (c);
+}
+
+/**
+ * Check whether character is decimal digit in US-ASCII
+ * @param c character to check
+ * @return non-zero if character is decimal digit, zero otherwise
+ */
+_MHD_inline _MHD_bool
+isasciidigit (char c)
+{
+  return c >= '0' && c <= '9';
+}
+
+/**
+ * Check whether character is decimal digit or letter in US-ASCII
+ * @param c character to check
+ * @return non-zero if character is decimal digit or letter, zero otherwise
+ */
+_MHD_inline _MHD_bool
+isasciialmun (char c)
+{
+  return isasciialpha (c) || isasciidigit (c);
+}
+
+/**
+ * Convert US-ASCII character to lower case.
+ * If character is upper case letter in US-ASCII than it's converted to lower
+ * case analog. If character is NOT upper case letter than it's returned
+ * unmodified.
+ * @param c character to check
+ * @return converted to lower case character
+ */
+_MHD_inline char
+toasciilower (char c)
+{
+  return isasciiupper (c) ? (c - 'A' + 'a') : c;
+}
+
+ /**
+ * Convert US-ASCII character to upper case.
+ * If character is lower case letter in US-ASCII than it's converted to upper
+ * case analog. If character is NOT lower case letter than it's returned
+ * unmodified.
+ * @param c character to check
+ * @return converted to upper case character
+ */
+_MHD_inline char
+toasciiupper (char c)
+{
+  return isasciilower (c) ? (c - 'a' + 'A') : c;
+}
+
+#else  /* !INLINE_FUNC */
+
+/**
+ * Checks whether character is lower case letter in US-ASCII
+ * @param c character to check
+ * @return boolean true if character is lower case letter,
+ *         boolean false otherwise
+ */
+#define isasciilower(c) (((char)(c)) >= 'a' && ((char)(c)) <= 'z')
+
+/**
+ * Checks whether character is upper case letter in US-ASCII
+ * @param c character to check
+ * @return boolean true if character is upper case letter,
+ *         boolean false otherwise
+ */
+#define isasciiupper(c) (((char)(c)) >= 'A' && ((char)(c)) <= 'Z')
+
+/**
+ * Checks whether character is letter in US-ASCII
+ * @param c character to check
+ * @return boolean true if character is letter, boolean false
+ *         otherwise
+ */
+#define isasciialpha(c) (isasciilower(c) || isasciiupper(c))
+
+/**
+ * Check whether character is decimal digit in US-ASCII
+ * @param c character to check
+ * @return boolean true if character is decimal digit, boolean false
+ *         otherwise
+ */
+#define isasciidigit(c) (((char)(c)) >= '0' && ((char)(c)) <= '9')
+
+ /**
+ * Check whether character is decimal digit or letter in US-ASCII
+ * @param c character to check
+ * @return boolean true if character is decimal digit or letter,
+ *         boolean false otherwise
+ */
+#define isasciialmun(c) (isasciialpha(c) || isasciidigit(c))
+
+/**
+ * Convert US-ASCII character to lower case.
+ * If character is upper case letter in US-ASCII than it's converted to lower
+ * case analog. If character is NOT upper case letter than it's returned
+ * unmodified.
+ * @param c character to check
+ * @return converted to lower case character
+ */
+#define toasciilower(c) ((isasciiupper(c)) ? (((char)(c)) - 'A' + 'a') : ((char)(c)))
+
+/**
+ * Convert US-ASCII character to upper case.
+ * If character is lower case letter in US-ASCII than it's converted to upper
+ * case analog. If character is NOT lower case letter than it's returned
+ * unmodified.
+ * @param c character to check
+ * @return converted to upper case character
+ */
+#define toasciiupper(c) ((isasciilower(c)) ? (((char)(c)) - 'a' + 'A') : ((char)(c)))
+#endif /* !INLINE_FUNC */
+
+/**
+ * Check two string for equality, ignoring case of US-ASCII letters.
+ * @param str1 first string to compare
+ * @param str2 second string to compare
+ * @return non-zero if two strings are equal, zero otherwise.
+ */
+int
+MHD_str_equal_caseless_ (const char * str1, const char * str2)
+{
+  while (0 != (*str1))
+    {
+      const char c1 = *str1;
+      const char c2 = *str2;
+      if (c1 != c2 && toasciilower (c1) != toasciilower (c2))
+        return 0;
+      str1++;
+      str2++;
+    }
+  return 0 == (*str2);
+}
+
+
+/**
+ * Check two string for equality, ignoring case of US-ASCII letters and
+ * checking not more than @a maxlen characters.
+ * Compares up to first terminating null character, but not more than
+ * first @a maxlen characters.
+ * @param str1 first string to compare
+ * @param str2 second string to compare
+ * @patam maxlen maximum number of characters to compare
+ * @return non-zero if two strings are equal, zero otherwise.
+ */
+int
+MHD_str_equal_caseless_n_ (const char * const str1, const char * const str2, size_t maxlen)
+{
+  for (size_t i = 0; i < maxlen; ++i)
+    {
+      const char c1 = str1[i];
+      const char c2 = str2[i];
+      if (0 == c2)
+        return 0 == c1;
+      if (c1 != c2 && toasciilower (c1) != toasciilower (c2))
+        return 0;
+    }
+  return !0;
+}

+ 62 - 0
src/microhttpd/mhd_str.h

@@ -0,0 +1,62 @@
+/*
+  This file is part of libmicrohttpd
+  Copyright (C) 2015 Karlson2k (Evgeny Grin)
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/**
+ * @file microhttpd/mhd_str.h
+ * @brief  Header for string manipulating helpers
+ * @author Karlson2k (Evgeny Grin)
+ */
+
+#ifndef MHD_STR_H
+#define MHD_STR_H 1
+
+#include <stdint.h>
+
+/*
+ * Block of functions/macros that use US-ASCII charset as required by HTTP
+ * standards. Not affected by current locale settings.
+ */
+
+/**
+ * Check two string for equality, ignoring case of US-ASCII letters.
+ * @param str1 first string to compare
+ * @param str2 second string to compare
+ * @return non-zero if two strings are equal, zero otherwise.
+ */
+int
+MHD_str_equal_caseless_ (const char * str1,
+                 const char * str2);
+
+
+/**
+ * Check two string for equality, ignoring case of US-ASCII letters and
+ * checking not more than @a maxlen characters.
+ * Compares up to first terminating null character, but not more than
+ * first @a maxlen characters.
+ * @param str1 first string to compare
+ * @param str2 second string to compare
+ * @patam maxlen maximum number of characters to compare
+ * @return non-zero if two strings are equal, zero otherwise.
+ */
+int
+MHD_str_equal_caseless_n_ (const char * const str1,
+                  const char * const str2,
+                  size_t maxlen);
+
+#endif /* MHD_STR_H */

+ 1 - 0
src/microhttpd/postprocessor.c

@@ -24,6 +24,7 @@
  */
 
 #include "internal.h"
+#include "mhd_str.h"
 
 /**
  * Size of on-stack buffer that we use for un-escaping of the value.

+ 10 - 0
w32/common/MHD_config.h

@@ -9,6 +9,16 @@
 /* Define if MS VC compiler is used */
 #define MSVC 1
 
+/* Define to type which will be used as boolean type. */
+#define _MHD_bool _Bool
+
+/* Define to 1 if your C compiler supports inline functions. */
+#define INLINE_FUNC 1
+
+/* Define to prefix which will be used with MHD inline functions. */
+#define _MHD_inline static __forceinline
+
+
 /* *** MHD configuration *** */
 /* Undef to disable feature */
 

+ 2 - 0
w32/common/libmicrohttpd-files.vcxproj

@@ -15,6 +15,7 @@
     <ClCompile Include="$(MhdSrc)microhttpd\response.c" />
     <ClCompile Include="$(MhdSrc)microhttpd\tsearch.c" />
     <ClCompile Include="$(MhdSrc)microhttpd\sysfdsetsize.c" />
+    <ClCompile Include="$(MhdSrc)microhttpd\mhd_str.c" />
     <ClCompile Include="$(MhdSrc)platform\w32functions.c" />
   </ItemGroup>
   <ItemGroup>
@@ -34,6 +35,7 @@
     <ClInclude Include="$(MhdSrc)microhttpd\response.h" />
     <ClInclude Include="$(MhdSrc)microhttpd\tsearch.h" />
     <ClInclude Include="$(MhdSrc)microhttpd\sysfdsetsize.h" />
+    <ClInclude Include="$(MhdSrc)microhttpd\mhd_str.h" />
     <ClInclude Include="$(MhdW32Common)MHD_config.h" />
   </ItemGroup>
   <ItemGroup>

+ 6 - 0
w32/common/libmicrohttpd-filters.vcxproj

@@ -121,6 +121,12 @@
     <ClCompile Include="$(MhdSrc)microhttpd\sysfdsetsize.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClInclude Include="$(MhdSrc)microhttpd\mhd_str.h">
+      <Filter>Source Files</Filter>
+    </ClInclude>
+    <ClCompile Include="$(MhdSrc)microhttpd\mhd_str.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="$(MhdW32Common)microhttpd_dll_res_vc.rc">