From ee50d5d85795c4f2990459b50d67c64f6e7564a9 Mon Sep 17 00:00:00 2001
From: Marco Bettini <marco.bettini@open-xchange.com>
Date: Mon, 21 Mar 2022 10:07:33 +0000
Subject: [PATCH] global: Replace strncasecmp() with str_begins_icase*()

---
 src/lib-sieve/cmp-i-ascii-casemap.c           | 22 ++----------
 src/lib-sieve/plugins/mime/tag-mime.c         |  4 +--
 .../plugins/notify/ext-notify-common.c        | 17 +++------
 src/lib-sieve/sieve-ast.h                     |  6 ++--
 src/lib-sieve/sieve-lexer.c                   |  5 +--
 src/lib-sieve/sieve-storage.c                 | 35 +++++++++----------
 .../storage/dict/sieve-dict-storage.c         |  5 +--
 .../storage/file/sieve-file-storage.c         |  7 ++--
 .../storage/ldap/sieve-ldap-storage.c         |  7 ++--
 src/managesieve-login/client.c                | 23 ++++++------
 src/managesieve-login/managesieve-proxy.c     | 27 +++++++-------
 src/plugins/imapsieve/imap-sieve-plugin.c     |  2 +-
 12 files changed, 69 insertions(+), 91 deletions(-)

diff --git a/src/lib-sieve/cmp-i-ascii-casemap.c b/src/lib-sieve/cmp-i-ascii-casemap.c
index 4f0dab456..10670e57d 100644
--- a/src/lib-sieve/cmp-i-ascii-casemap.c
+++ b/src/lib-sieve/cmp-i-ascii-casemap.c
@@ -50,25 +50,9 @@ static int cmp_i_ascii_casemap_compare(
 	const struct sieve_comparator *cmp ATTR_UNUSED,
 	const char *val1, size_t val1_size, const char *val2, size_t val2_size)
 {
-	int result;
-
-	if ( val1_size == val2_size ) {
-		return strncasecmp(val1, val2, val1_size);
-	}
-
-	if ( val1_size > val2_size ) {
-		result = strncasecmp(val1, val2, val2_size);
-
-		if ( result == 0 ) return 1;
-
-		return result;
-	}
-
-	result = strncasecmp(val1, val2, val1_size);
-
-	if ( result == 0 ) return -1;
-
-	return result;
+	size_t size = I_MIN(val1_size, val2_size);
+	int ret = strncasecmp(val1, val2, size);
+	return ret != 0 ? ret : (int)val1_size - (int)val2_size;
 }
 
 static bool cmp_i_ascii_casemap_char_match
diff --git a/src/lib-sieve/plugins/mime/tag-mime.c b/src/lib-sieve/plugins/mime/tag-mime.c
index 8897a3ad3..bf4741f9d 100644
--- a/src/lib-sieve/plugins/mime/tag-mime.c
+++ b/src/lib-sieve/plugins/mime/tag-mime.c
@@ -361,7 +361,7 @@ content_type_param_next(struct content_header_stringlist *strlist)
 
 		/* Iterate over all interesting parameter names */
 		for ( ; *params != NULL; params++ ) {
-			size_t plen = strlen(*params);
+			const size_t plen = strlen(*params);
 
 			if ( plen != nlen &&
 				(nlen != plen + 1 || name[nlen-1] != '*') )
@@ -386,7 +386,7 @@ content_type_param_next(struct content_header_stringlist *strlist)
 						*params);
 				}
 
-				if ( strncasecmp(name, *params, plen) == 0 ) {
+				if (str_begins_icase_with(name, *params)) {
 					string_t *result = NULL;
 
 					strlist->param_values = values + 2;
diff --git a/src/lib-sieve/plugins/notify/ext-notify-common.c b/src/lib-sieve/plugins/notify/ext-notify-common.c
index cda0ff9d8..ad344bb0f 100644
--- a/src/lib-sieve/plugins/notify/ext-notify-common.c
+++ b/src/lib-sieve/plugins/notify/ext-notify-common.c
@@ -276,9 +276,7 @@ int ext_notify_construct_message(const struct sieve_runtime_env *renv,
 	while (*p != '\0') {
 		const char *header;
 
-		if (strncasecmp(p, "$from$", 6) == 0) {
-			p += 6;
-
+		if (str_begins_icase(p, "$from$", &p)) {
 			/* Fetch sender from original message */
 			if ((ret = mail_get_first_header_utf8(
 				msgdata->mail, "from", &header)) < 0) {
@@ -288,14 +286,10 @@ int ext_notify_construct_message(const struct sieve_runtime_env *renv,
 			}
 			if (ret > 0)
 				str_append(out_msg, header);
-		} else if (strncasecmp(p, "$env-from$", 10) == 0) {
-			p += 10;
-
+		} else if (str_begins_icase(p, "$env-from$", &p)) {
 			if (return_path != NULL)
 				smtp_address_write(out_msg, return_path);
-		} else if (strncasecmp(p, "$subject$", 9) == 0) {
-			p += 9;
-
+		} else if (str_begins_icase(p, "$subject$", &p)) {
 			/* Fetch sender from oriinal message */
 			if ((ret = mail_get_first_header_utf8(
 				msgdata->mail, "subject", &header)) < 0) {
@@ -305,13 +299,12 @@ int ext_notify_construct_message(const struct sieve_runtime_env *renv,
 			}
 			if (ret > 0)
 				 str_append(out_msg, header);
-		} else if (strncasecmp(p, "$text", 5) == 0 &&
-			   (p[5] == '[' || p[5] == '$')) {
+		} else if (str_begins_icase(p, "$text", &p) &&
+			   (*p == '[' || *p == '$')) {
 			size_t num = 0;
 			const char *begin = p;
 			bool valid = TRUE;
 
-			p += 5;
 			if (*p == '[') {
 				p += 1;
 
diff --git a/src/lib-sieve/sieve-ast.h b/src/lib-sieve/sieve-ast.h
index 00f8a6b64..7ac53092e 100644
--- a/src/lib-sieve/sieve-ast.h
+++ b/src/lib-sieve/sieve-ast.h
@@ -336,9 +336,9 @@ sieve_ast_stringlist_join(struct sieve_ast_argument *list,
 #define sieve_ast_command_next(command) __AST_LIST_NEXT(command)
 
 /* Compare the identifier of the previous command */
-#define sieve_ast_prev_cmd_is(cmd, id) \
-	((cmd)->prev == NULL ? FALSE : \
-	 strncasecmp((cmd)->prev->identifier, id, sizeof(id)-1) == 0)
+#define sieve_ast_prev_cmd_is(cmd, id) 				\
+	((cmd)->prev != NULL && 				\
+	 str_begins_icase_with((cmd)->prev->identifier, id))
 
 /* AST test macros */
 #define sieve_ast_test_count(node) __AST_NODE_LIST_COUNT(node, tests)
diff --git a/src/lib-sieve/sieve-lexer.c b/src/lib-sieve/sieve-lexer.c
index a6968a990..c823efdc9 100644
--- a/src/lib-sieve/sieve-lexer.c
+++ b/src/lib-sieve/sieve-lexer.c
@@ -727,8 +727,9 @@ sieve_lexer_scan_raw_token(struct sieve_lexical_scanner *scanner)
 
 			/* Is this in fact a multiline text string ? */
 			if (sieve_lexer_curchar(scanner) == ':' &&
-			    type == STT_IDENTIFIER && str_len(str) == 4 &&
-			    strncasecmp(str_c(str), "text", 4) == 0) {
+			    type == STT_IDENTIFIER &&
+			    str_len(str) == 4 &&
+			    str_begins_icase_with(str_c(str), "text")) {
 				sieve_lexer_shift(scanner); // discard colon
 
 				/* Discard SP and HTAB whitespace */
diff --git a/src/lib-sieve/sieve-storage.c b/src/lib-sieve/sieve-storage.c
index e52b595c7..9e12d1c45 100644
--- a/src/lib-sieve/sieve-storage.c
+++ b/src/lib-sieve/sieve-storage.c
@@ -176,7 +176,8 @@ sieve_storage_data_parse(struct sieve_storage *storage, const char *data,
 			 const char **location_r, const char *const **options_r)
 {
 	ARRAY_TYPE(const_string) options;
-	const char *const *tmp;
+	const char *const *args;
+	const char *value;
 
 	if (*data == '\0') {
 		*options_r = NULL;
@@ -185,18 +186,18 @@ sieve_storage_data_parse(struct sieve_storage *storage, const char *data,
 	}
 
 	/* <location> */
-	tmp = t_strsplit(data, ";");
-	*location_r = split_next_arg(&tmp);
+	args = t_strsplit(data, ";");
+	*location_r = split_next_arg(&args);
 
 	if (options_r != NULL) {
 		t_array_init(&options, 8);
 
 		/* [<option> *(';' <option>)] */
-		while (*tmp != NULL) {
-			const char *option = split_next_arg(&tmp);
+		while (*args != NULL) {
+			const char *option = split_next_arg(&args);
 
-			if (strncasecmp(option, "name=", 5) == 0) {
-				if (option[5] == '\0') {
+			if (str_begins_icase(option, "name=", &value)) {
+				if (*value == '\0') {
 					e_error(storage->event,
 						"Failed to parse storage location: "
 						"Empty name not allowed");
@@ -204,33 +205,31 @@ sieve_storage_data_parse(struct sieve_storage *storage, const char *data,
 				}
 
 				if (storage->script_name == NULL) {
-					if (!sieve_script_name_is_valid(option+5)) {
+					if (!sieve_script_name_is_valid(value)) {
 						e_error(storage->event,
 							"Failed to parse storage location: "
 							"Invalid script name `%s'.",
-							str_sanitize(option+5, 80));
+							str_sanitize(value, 80));
 						return -1;
 					}
-					storage->script_name = p_strdup(storage->pool, option+5);
+					storage->script_name = p_strdup(storage->pool, value);
 				}
 
-			} else if (strncasecmp(option, "bindir=", 7) == 0) {
-				const char *bin_dir = option+7;
-
-				if (bin_dir[0] == '\0') {
+			} else if (str_begins_icase(option, "bindir=", &value)) {
+				if (value[0] == '\0') {
 					e_error(storage->event,
 						"Failed to parse storage location: "
 						"Empty bindir not allowed");
 					return -1;
 				}
 
-				if (bin_dir[0] == '~') {
+				if (value[0] == '~') {
 					/* home-relative path. change to absolute. */
 					const char *home = sieve_environment_get_homedir(storage->svinst);
 
 					if (home != NULL) {
-						bin_dir = home_expand_tilde(bin_dir, home);
-					} else if (bin_dir[1] == '/' || bin_dir[1] == '\0') {
+						value = home_expand_tilde(value, home);
+					} else if (value[1] == '/' || value[1] == '\0') {
 						e_error(storage->event,
 							"Failed to parse storage location: "
 							"bindir is relative to home directory (~/), "
@@ -239,7 +238,7 @@ sieve_storage_data_parse(struct sieve_storage *storage, const char *data,
 					}
 				}
 
-				storage->bin_dir = p_strdup(storage->pool, bin_dir);
+				storage->bin_dir = p_strdup(storage->pool, value);
 			} else {
 				array_append(&options, &option, 1);
 			}
diff --git a/src/lib-sieve/storage/dict/sieve-dict-storage.c b/src/lib-sieve/storage/dict/sieve-dict-storage.c
index 7f508165d..55d765f6e 100644
--- a/src/lib-sieve/storage/dict/sieve-dict-storage.c
+++ b/src/lib-sieve/storage/dict/sieve-dict-storage.c
@@ -33,13 +33,14 @@ static int sieve_dict_storage_init
 	struct sieve_dict_storage *dstorage =
 		(struct sieve_dict_storage *)storage;
 	struct sieve_instance *svinst = storage->svinst;
-	const char *uri = storage->location, *username = NULL;
+	const char *value, *uri = storage->location, *username = NULL;
 
 	if ( options != NULL ) {
 		while ( *options != NULL ) {
 			const char *option = *options;
 
-			if ( strncasecmp(option, "user=", 5) == 0 && option[5] != '\0' ) {
+			if (str_begins_icase(option, "user=", &value) &&
+			    *value != '\0' ) {
 				username = option+5;
 			} else {
 				sieve_storage_set_critical(storage,
diff --git a/src/lib-sieve/storage/file/sieve-file-storage.c b/src/lib-sieve/storage/file/sieve-file-storage.c
index 2e23ee253..a6a7fe20f 100644
--- a/src/lib-sieve/storage/file/sieve-file-storage.c
+++ b/src/lib-sieve/storage/file/sieve-file-storage.c
@@ -492,15 +492,16 @@ static int sieve_file_storage_init
 	struct sieve_file_storage *fstorage =
 		(struct sieve_file_storage *)storage;
 	const char *storage_path = storage->location;
-	const char *active_path = "";
+	const char *value, *active_path = "";
 	bool exists = FALSE;
 
 	if ( options != NULL ) {
 		while ( *options != NULL ) {
 			const char *option = *options;
 
-			if ( strncasecmp(option, "active=", 7) == 0 && option[7] != '\0' ) {
-				active_path = option+7;
+			if (str_begins_icase(option, "active=", &value) &&
+			    *value != '\0' ) {
+				active_path = value;
 			} else {
 				sieve_storage_set_critical(storage,
 					"Invalid option `%s'", option);
diff --git a/src/lib-sieve/storage/ldap/sieve-ldap-storage.c b/src/lib-sieve/storage/ldap/sieve-ldap-storage.c
index 5f894e06d..eee4f5efa 100644
--- a/src/lib-sieve/storage/ldap/sieve-ldap-storage.c
+++ b/src/lib-sieve/storage/ldap/sieve-ldap-storage.c
@@ -46,14 +46,15 @@ static int sieve_ldap_storage_init
 	struct sieve_ldap_storage *lstorage =
 		(struct sieve_ldap_storage *)storage;
 	struct sieve_instance *svinst = storage->svinst;
-	const char *username = NULL;
+	const char *value, *username = NULL;
 
 	if ( options != NULL ) {
 		while ( *options != NULL ) {
 			const char *option = *options;
 
-			if ( strncasecmp(option, "user=", 5) == 0 && option[5] != '\0' ) {
-				username = option+5;
+			if (str_begins_icase(option, "user=", &value) &&
+			    *value != '\0' ) {
+				username = value;
 			} else {
 				sieve_storage_set_critical(storage,
 					"Invalid option `%s'", option);
diff --git a/src/managesieve-login/client.c b/src/managesieve-login/client.c
index ec4109264..e3ee3e124 100644
--- a/src/managesieve-login/client.c
+++ b/src/managesieve-login/client.c
@@ -182,7 +182,7 @@ static int
 cmd_xclient(struct managesieve_client *client,
 	    const struct managesieve_arg *args)
 {
-	const char *arg;
+	const char *value, *arg;
 	bool args_ok = TRUE;
 
 	if (!client->common.trusted) {
@@ -191,25 +191,22 @@ cmd_xclient(struct managesieve_client *client,
 	}
 	while (!MANAGESIEVE_ARG_IS_EOL(&args[0]) &&
 		managesieve_arg_get_atom(&args[0], &arg)) {
-		if (strncasecmp(arg, "ADDR=", 5) == 0) {
-			if (net_addr2ip(arg + 5, &client->common.ip) < 0)
+		if (str_begins_icase(arg, "ADDR=", &value)) {
+			if (net_addr2ip(value, &client->common.ip) < 0)
 				args_ok = FALSE;
-		} else if (strncasecmp(arg, "FORWARD=", 8)  == 0) {
-			if (cmd_xclient_parse_forward(client, arg + 8) < 0)
+		} else if (str_begins_icase(arg, "FORWARD=", &value)) {
+			if (cmd_xclient_parse_forward(client, value) < 0)
 				args_ok = FALSE;
-		} else if (strncasecmp(arg, "PORT=", 5) == 0) {
-			if (net_str2port(arg + 5,
-					 &client->common.remote_port) < 0)
+		} else if (str_begins_icase(arg, "PORT=", &value)) {
+			if (net_str2port(value, &client->common.remote_port) < 0)
 				args_ok = FALSE;
-		} else if (strncasecmp(arg, "SESSION=", 8) == 0) {
-			const char *value = arg + 8;
-
+		} else if (str_begins_icase(arg, "SESSION=", &value)) {
 			if (strlen(value) <= LOGIN_MAX_SESSION_ID_LEN) {
 				client->common.session_id =
 					p_strdup(client->common.pool, value);
 			}
-		} else if (strncasecmp(arg, "TTL=", 4)  == 0) {
-			if (str_to_uint(arg + 4, &client->common.proxy_ttl) < 0)
+		} else if (str_begins_icase(arg, "TTL=", &value)) {
+			if (str_to_uint(value, &client->common.proxy_ttl) < 0)
 				args_ok = FALSE;
 		}
 		args++;
diff --git a/src/managesieve-login/managesieve-proxy.c b/src/managesieve-login/managesieve-proxy.c
index e29e97d14..cd339dfef 100644
--- a/src/managesieve-login/managesieve-proxy.c
+++ b/src/managesieve-login/managesieve-proxy.c
@@ -44,7 +44,7 @@ proxy_compose_xclient_forward(struct managesieve_client *client)
 
 	str = t_str_new(128);
 	for (arg = client->common.auth_passdb_args; *arg != NULL; arg++) {
-		if (strncasecmp(*arg, "forward_", 8) == 0) {
+		if (str_begins_icase_with(*arg, "forward_")) {
 			if (str_len(str) > 0)
 				str_append_c(str, '\t');
 			str_append_tabescaped(str, (*arg)+8);
@@ -412,7 +412,7 @@ managesieve_proxy_parse_auth_reply(const char *line,
 
 	*resp_code_r = NULL;
 
-	if (strncasecmp(line, "NO ", 3) != 0) {
+	if (!str_begins_icase_with(line, "NO ")) {
 		*reason_r = line;
 		return;
 	}
@@ -449,17 +449,17 @@ auth_resp_code_parse_referral(struct client *client, const char *resp_code,
 			      const char **userhostport_r)
 {
 	struct managesieve_url *url;
-	const char *referral, *error;
+	const char *error;
 
-	if (resp_code == NULL || strncasecmp(resp_code, "REFERRAL ", 9) != 0)
+	if (resp_code == NULL ||
+	    !str_begins_icase(resp_code, "REFERRAL ", &resp_code))
 		return FALSE;
-	referral = resp_code + 9;
 
-	if (managesieve_url_parse(referral, MANAGESIEVE_URL_ALLOW_USERINFO_PART,
+	if (managesieve_url_parse(resp_code, MANAGESIEVE_URL_ALLOW_USERINFO_PART,
 				  pool_datastack_create(), &url, &error) < 0) {
 		e_debug(login_proxy_get_event(client->login_proxy),
 			"Couldn't parse REFERRAL '%s': %s",
-			str_sanitize(referral, 160), error);
+			str_sanitize(resp_code, 160), error);
 		return FALSE;
 	}
 
@@ -481,6 +481,7 @@ int managesieve_proxy_parse_line(struct client *client, const char *line)
 	enum auth_proxy_ssl_flags ssl_flags;
 	managesieve_response_t response = MANAGESIEVE_RESPONSE_NONE;
 	string_t *command;
+	const char *suffix;
 	int ret = 0;
 
 	i_assert(!client->destroyed);
@@ -527,8 +528,8 @@ int managesieve_proxy_parse_line(struct client *client, const char *line)
 		}
 		return 0;
 	case MSIEVE_PROXY_STATE_TLS_START:
-		if (strncasecmp(line, "OK", 2) == 0 &&
-		    (strlen(line) == 2 || line[2] == ' ')) {
+		if (str_begins_icase(line, "OK", &suffix) &&
+		    (*suffix == '\0' || *suffix == ' ')) {
 			/* STARTTLS successful, begin TLS negotiation. */
 			if (login_proxy_starttls(client->login_proxy) < 0)
 				return -1;
@@ -573,8 +574,8 @@ int managesieve_proxy_parse_line(struct client *client, const char *line)
 		}
 		return 0;
 	case MSIEVE_PROXY_STATE_XCLIENT:
-		if (strncasecmp(line, "OK", 2) == 0 &&
-		    (strlen(line) == 2 || line[2] == ' ')) {
+		if (str_begins_icase(line, "OK", &suffix) &&
+		    (*suffix == '\0' || *suffix == ' ')) {
 			command = t_str_new(128);
 			if (proxy_write_auth(msieve_client, command) < 0)
 				return -1;
@@ -608,8 +609,8 @@ int managesieve_proxy_parse_line(struct client *client, const char *line)
 		}
 
 		/* Check login status */
-		if (strncasecmp(line, "OK", 2) == 0 &&
-		    (strlen(line) == 2 || line[2] == ' ')) {
+		if (str_begins_icase(line, "OK", &suffix) &&
+		    (*suffix == '\0' || *suffix == ' ')) {
 			string_t *str = t_str_new(128);
 
 			/* Login successful */
diff --git a/src/plugins/imapsieve/imap-sieve-plugin.c b/src/plugins/imapsieve/imap-sieve-plugin.c
index 0c9b52ef4..9389b8de3 100644
--- a/src/plugins/imapsieve/imap-sieve-plugin.c
+++ b/src/plugins/imapsieve/imap-sieve-plugin.c
@@ -24,7 +24,7 @@ static void imap_sieve_client_created(struct client **clientp)
 	if (mail_user_is_plugin_loaded(user, imap_sieve_module)) {
 		url = mail_user_plugin_getenv(user, "imapsieve_url");
 		// FIXME: parse the URL and report error if it is bad
-		if (url != NULL && strncasecmp(url, "sieve:", 6) == 0) {
+		if (url != NULL && str_begins_icase_with(url, "sieve:")) {
 			client_add_capability(client, t_strconcat(
 				"IMAPSIEVE=", url, NULL));
 		} else {
-- 
GitLab