summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrank Berghaus <berghaus@cern.ch>2022-09-21 16:50:17 (GMT)
committerGitHub <noreply@github.com>2022-09-21 16:50:17 (GMT)
commit100b22e6c23c44a082fd69b8c05a63c7492083f7 (patch)
tree744a5409278b46f62765dfe23345d0b6a3c66dfb
parentd491c33a72c9e6cabe10a7508c1cc76c1d638479 (diff)
downloadhdf5-100b22e6c23c44a082fd69b8c05a63c7492083f7.zip
hdf5-100b22e6c23c44a082fd69b8c05a63c7492083f7.tar.gz
hdf5-100b22e6c23c44a082fd69b8c05a63c7492083f7.tar.bz2
Use case-insensitive comparison for headers fix #2100 (#2101)
* Use case-inseneitive comparison for headers HTTP headers should be case-insensitive. Use case-insensitive string comparisons when working with HTTP header responses to ensure compatibility. * Revert "Use case-inseneitive comparison for headers" This reverts commit a02f591723506b62b7208449be6eef7122120398 * Ignore case when searching HTTP header responses Looking up the Content-Length in the header returned by S3 storage endpoints should ignore case. To guarantee portability implement a function for case-insensitive string search, because it is non-standard. * Add an _ after H5 for the strcasestr implementation It is a private function and should sport that underscore. * Remove author comment from the doc comment * Use search function defined by system if available Check whether the system provides a function implementing case insensitive string searches. Only use the custom implementation if the system does not provide the functionality. * Add tests for case-insensitive search Basic tests: - Search for empty string - Search with exact match - Search with case-insensitive match - search with no match * Enforce clang-format style Some variable definitions in the th5_system tests did not conform to clang-format's expectations. Updated the offending lines. * Correct comment describing test case * Added some spaces to please clang-format * Ignore discarding const Ask the compiler to ignore discarding the const when retunring a match from H5_strcasestr Co-authored-by: Frank Berghaus <frank.berghaus@mpcdf.mpg.de>
-rw-r--r--config/cmake/ConfigureChecks.cmake1
-rw-r--r--config/cmake/H5pubconf.h.in3
-rw-r--r--configure.ac2
-rw-r--r--src/H5FDs3comms.c2
-rw-r--r--src/H5private.h8
-rw-r--r--src/H5system.c39
-rw-r--r--src/H5win32defs.h1
-rw-r--r--test/th5_system.c26
8 files changed, 80 insertions, 2 deletions
diff --git a/config/cmake/ConfigureChecks.cmake b/config/cmake/ConfigureChecks.cmake
index d71ca08..ee90128 100644
--- a/config/cmake/ConfigureChecks.cmake
+++ b/config/cmake/ConfigureChecks.cmake
@@ -455,6 +455,7 @@ CHECK_FUNCTION_EXISTS (sigsetjmp ${HDF_PREFIX}_HAVE_SIGSETJMP)
CHECK_FUNCTION_EXISTS (sigprocmask ${HDF_PREFIX}_HAVE_SIGPROCMASK)
CHECK_FUNCTION_EXISTS (srandom ${HDF_PREFIX}_HAVE_SRANDOM)
+CHECK_FUNCTION_EXISTS (strcasestr ${HDF_PREFIX}_HAVE_STRCASESTR)
CHECK_FUNCTION_EXISTS (strdup ${HDF_PREFIX}_HAVE_STRDUP)
CHECK_FUNCTION_EXISTS (symlink ${HDF_PREFIX}_HAVE_SYMLINK)
diff --git a/config/cmake/H5pubconf.h.in b/config/cmake/H5pubconf.h.in
index a500f46..1f2e1b5 100644
--- a/config/cmake/H5pubconf.h.in
+++ b/config/cmake/H5pubconf.h.in
@@ -313,6 +313,9 @@
/* Define to 1 if you have the <stdlib.h> header file. */
#cmakedefine H5_HAVE_STDLIB_H @H5_HAVE_STDLIB_H@
+/* Define to 1 if you have the `strcasestr' function. */
+#cmakedefine H5_HAVE_STRCASESTR @H5_HAVE_STRCASESTR@
+
/* Define to 1 if you have the `strdup' function. */
#cmakedefine H5_HAVE_STRDUP @H5_HAVE_STRDUP@
diff --git a/configure.ac b/configure.ac
index cdbdadb..ab9897b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2137,7 +2137,7 @@ AC_CHECK_FUNCS([alarm asprintf clock_gettime fcntl flock fork])
AC_CHECK_FUNCS([gethostname getrusage gettimeofday])
AC_CHECK_FUNCS([lstat rand_r random setsysinfo])
AC_CHECK_FUNCS([siglongjmp sigsetjmp sigprocmask])
-AC_CHECK_FUNCS([srandom strdup symlink])
+AC_CHECK_FUNCS([srandom strcasestr strdup symlink])
AC_CHECK_FUNCS([tmpfile vasprintf waitpid])
## ----------------------------------------------------------------------
diff --git a/src/H5FDs3comms.c b/src/H5FDs3comms.c
index 1bf0a2f..628c55a 100644
--- a/src/H5FDs3comms.c
+++ b/src/H5FDs3comms.c
@@ -941,7 +941,7 @@ H5FD_s3comms_s3r_getsize(s3r_t *handle)
* PARSE RESPONSE *
******************/
- start = HDstrstr(headerresponse, "\r\nContent-Length: ");
+ start = HDstrcasestr(headerresponse, "\r\nContent-Length: ");
if (start == NULL)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "could not find \"Content-Length\" in response.");
diff --git a/src/H5private.h b/src/H5private.h
index c2ce4c1..f9ff043 100644
--- a/src/H5private.h
+++ b/src/H5private.h
@@ -593,6 +593,7 @@ H5_DLL herr_t H5_timer_stop(H5_timer_t *timer /*in,out*/);
H5_DLL herr_t H5_timer_get_times(H5_timer_t timer, H5_timevals_t *times /*in,out*/);
H5_DLL herr_t H5_timer_get_total_times(H5_timer_t timer, H5_timevals_t *times /*in,out*/);
H5_DLL char *H5_timer_get_time_string(double seconds);
+H5_DLL char *H5_strcasestr(const char *haystack, const char *needle);
/* Depth of object copy */
typedef enum {
@@ -1385,6 +1386,13 @@ H5_DLL H5_ATTR_CONST int Nflock(int fd, int operation);
#ifndef HDstrcat
#define HDstrcat(X, Y) strcat(X, Y)
#endif
+#ifndef HDstrcasestr
+#if defined(H5_HAVE_STRCASESTR)
+#define HDstrcasestr(X, Y) strcasestr(X, Y)
+#else
+#define HDstrcasestr(X, Y) H5_strcasestr(X, Y)
+#endif
+#endif
#ifndef HDstrchr
#define HDstrchr(S, C) strchr(S, C)
#endif
diff --git a/src/H5system.c b/src/H5system.c
index 9a19860..a7f2edd 100644
--- a/src/H5system.c
+++ b/src/H5system.c
@@ -1350,3 +1350,42 @@ H5_get_option(int argc, const char *const *argv, const char *opts, const struct
/* return the current flag character found */
return optchar;
}
+
+/*-------------------------------------------------------------------------
+ * Function: H5_strcasestr
+ *
+ * Purpose: Find the first occurrence of the substring needle in the
+ * string haystack ignoring case.
+ *
+ * Return: Success: Pointer to the beginning of the located substring
+ *
+ * Failure: NULL
+ *
+ *-------------------------------------------------------------------------
+ */
+char *
+H5_strcasestr(const char *haystack, const char *needle)
+{
+ /* Check arguments. */
+ HDassert(haystack);
+ HDassert(needle);
+
+ /* begin once from each character of haystack, until needle is found */
+ do {
+ const char *h = haystack;
+ const char *n = needle;
+ /* loop while lowercase strings match, or needle ends */
+ while (HDtolower(*h) == HDtolower(*n) && *n) {
+ h++;
+ n++;
+ }
+ /* if all characters in needle matched we found it */
+ if (*n == 0) {
+ /* must discard const qualifier here, so turn off the warning */
+ H5_GCC_CLANG_DIAG_OFF("cast-qual")
+ return (char *)haystack;
+ H5_GCC_CLANG_DIAG_ON("cast-qual")
+ }
+ } while (*haystack++);
+ return 0;
+} /* end H5_strcasestr() */
diff --git a/src/H5win32defs.h b/src/H5win32defs.h
index 1039f23..ea607da 100644
--- a/src/H5win32defs.h
+++ b/src/H5win32defs.h
@@ -82,6 +82,7 @@ struct timezone {
#define HDsleep(S) Sleep(S * 1000)
#define HDstat(S, B) _stati64(S, B)
#define HDstrcasecmp(A, B) _stricmp(A, B)
+#define HDstrcasestr(A, B) StrStrIA(A, B)
#define HDstrndup(S, N) H5_strndup(S, N)
#define HDstrtok_r(X, Y, Z) strtok_s(X, Y, Z)
#define HDtzset() _tzset()
diff --git a/test/th5_system.c b/test/th5_system.c
index 09570cf..784cb3f 100644
--- a/test/th5_system.c
+++ b/test/th5_system.c
@@ -438,6 +438,31 @@ test_h5_basename(void)
}
static void
+test_h5_strcasestr(void)
+{
+ const char *const haystack = "My test string";
+ char *str = NULL;
+
+ MESSAGE(5, ("Testing H5_strcasestr\n"));
+
+ /* check that H5_strcasestr returns target in empty search */
+ str = H5_strcasestr(haystack, "");
+ CHECK_PTR_EQ(str, haystack, "H5_strcasestr search for empty");
+
+ /* Check that H5_strcasestr find a string of same case */
+ str = H5_strcasestr(haystack, "string");
+ CHECK_PTR_EQ(str, &(haystack[8]), "H5_strcasestr search same case");
+
+ /* Check that H5_strcasestr find a string of different case */
+ str = H5_strcasestr(haystack, "sTrInG");
+ CHECK_PTR_EQ(str, &(haystack[8]), "H5_strcasestr search different case");
+
+ /* Check that H5_strcasestr returns NULL if no match is found */
+ str = H5_strcasestr(haystack, "nomatch");
+ CHECK_PTR_NULL(str, "H5_strcasestr search with no match");
+}
+
+static void
test_h5_strndup(void)
{
#ifdef H5_HAVE_WIN32_API
@@ -495,6 +520,7 @@ test_h5_system(void)
test_h5_dirname();
test_h5_basename();
+ test_h5_strcasestr();
test_h5_strndup();
}