return true;
}
+
+/**
+ * mutt_str_strcasestr - Find a substring within a string without worrying about case
+ * @param haystack String that may or may not contain the substring
+ * @param needle Substring we're looking for
+ * @retval ptr Beginning of substring
+ * @retval NULL Substring is not in substring
+ *
+ * This performs a byte-to-byte check so it will return unspecified
+ * results for multibyte locales.
+ */
+const char *mutt_str_strcasestr(const char *haystack, const char *needle)
+{
+ if (!needle)
+ return NULL;
+
+ size_t haystack_len = mutt_str_strlen(haystack);
+ size_t needle_len = mutt_str_strlen(needle);
+
+ // Empty string exists at the front of a string. Check strstr if you don't believe me.
+ if (needle_len == 0)
+ return haystack;
+
+ // Check size conditions. No point wasting CPU cycles.
+ if ((haystack_len == 0) || (haystack_len < needle_len))
+ return NULL;
+
+ // Only check space that needle could fit in.
+ // Conditional has + 1 to handle when the haystack and needle are the same length.
+ for (size_t i = 0; i < (haystack_len - needle_len) + 1; i++)
+ {
+ for (size_t j = 0; j < needle_len; j++)
+ {
+ if (tolower((unsigned char) haystack[i + j]) != tolower((unsigned char) needle[j]))
+ break;
+
+ // If this statement is true, the needle has been found.
+ if (j == (needle_len - 1))
+ return haystack + i;
+ }
+ }
+
+ return NULL;
+}
char * mutt_str_skip_email_wsp(const char *s);
char * mutt_str_skip_whitespace(char *p);
int mutt_str_strcasecmp(const char *a, const char *b);
+const char *mutt_str_strcasestr(const char *haystack, const char *needle);
char * mutt_str_strcat(char *buf, size_t buflen, const char *s);
const char *mutt_str_strchrnul(const char *s, char c);
int mutt_str_strcmp(const char *a, const char *b);