libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

commit ad9b3c3814e92a2bb1ce1cd114328d5de741c33d
parent 56810e175c26cb40f8b7df2fdcf7a7defd6bbabe
Author: Evgeny Grin (Karlson2k) <k2k@narod.ru>
Date:   Sat, 16 Jan 2016 19:23:00 +0000

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.

Diffstat:
MChangeLog | 5+++++
Mconfigure.ac | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/include/platform_interface.h | 37-------------------------------------
Msrc/microhttpd/Makefile.am | 1+
Msrc/microhttpd/connection.c | 1+
Msrc/microhttpd/digestauth.c | 1+
Asrc/microhttpd/mhd_str.c | 231+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/microhttpd/mhd_str.h | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/microhttpd/postprocessor.c | 1+
Mw32/common/MHD_config.h | 10++++++++++
Mw32/common/libmicrohttpd-files.vcxproj | 2++
Mw32/common/libmicrohttpd-filters.vcxproj | 6++++++
12 files changed, 374 insertions(+), 37 deletions(-)

diff --git a/ChangeLog b/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 diff --git a/configure.ac b/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 diff --git a/src/include/platform_interface.h b/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) diff --git a/src/microhttpd/Makefile.am b/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) \ diff --git a/src/microhttpd/connection.c b/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 */ diff --git a/src/microhttpd/digestauth.c b/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 diff --git a/src/microhttpd/mhd_str.c b/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; +} diff --git a/src/microhttpd/mhd_str.h b/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 */ diff --git a/src/microhttpd/postprocessor.c b/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. diff --git a/w32/common/MHD_config.h b/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 */ diff --git a/w32/common/libmicrohttpd-files.vcxproj b/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> diff --git a/w32/common/libmicrohttpd-filters.vcxproj b/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">