From: Timo Sirainen Date: Fri, 10 Apr 2020 16:13:07 +0000 (+0300) Subject: global: Rename str_begins_suffix() to str_begins() and use it everywhere X-Git-Tag: 2.4.0~4235 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4d482e629a0fbfbb23edfb95a4464e4922a3c665;p=thirdparty%2Fdovecot%2Fcore.git global: Rename str_begins_suffix() to str_begins() and use it everywhere --- diff --git a/src/auth/auth-cache.c b/src/auth/auth-cache.c index e8aa10573c..46f697cee7 100644 --- a/src/auth/auth-cache.c +++ b/src/auth/auth-cache.c @@ -270,8 +270,7 @@ unsigned int auth_cache_clear(struct auth_cache *cache) static bool auth_cache_node_is_user(struct auth_cache_node *node, const char *username) { - const char *data = node->data; - size_t username_len; + const char *data = node->data, *suffix; /* The cache nodes begin with "P"/"U", passdb/userdb ID, optional "+" master user, "\t" and then usually followed by the username. @@ -294,9 +293,8 @@ static bool auth_cache_node_is_user(struct auth_cache_node *node, return FALSE; data++; - username_len = strlen(username); - return str_begins(data, username) && - (data[username_len] == '\t' || data[username_len] == '\0'); + return str_begins(data, username, &suffix) && + (suffix[0] == '\t' || suffix[0] == '\0'); } static bool auth_cache_node_is_one_of_users(struct auth_cache_node *node, diff --git a/src/auth/auth-client-connection.c b/src/auth/auth-client-connection.c index 961480e0f9..902967d2a8 100644 --- a/src/auth/auth-client-connection.c +++ b/src/auth/auth-client-connection.c @@ -212,26 +212,28 @@ auth_client_cancel(struct auth_client_connection *conn, const char *line) static bool auth_client_handle_line(struct auth_client_connection *conn, const char *line) { - if (str_begins(line, "AUTH\t")) { + const char *args; + + if (str_begins(line, "AUTH\t", &args)) { if (conn->auth->set->debug) { e_debug(conn->event, "client in: %s", auth_line_hide_pass(conn, line)); } return auth_request_handler_auth_begin(conn->request_handler, - line + 5); + args); } - if (str_begins(line, "CONT\t")) { + if (str_begins(line, "CONT\t", &args)) { if (conn->auth->set->debug) { e_debug(conn->event, "client in: %s", cont_line_hide_pass(conn, line)); } return auth_request_handler_auth_continue(conn->request_handler, - line + 5); + args); } - if (str_begins(line, "CANCEL\t")) { + if (str_begins(line, "CANCEL\t", &args)) { if (conn->auth->set->debug) e_debug(conn->event, "client in: %s", line); - return auth_client_cancel(conn, line + 7); + return auth_client_cancel(conn, args); } e_error(conn->event, "BUG: Authentication client sent unknown command: %s", @@ -241,6 +243,7 @@ auth_client_handle_line(struct auth_client_connection *conn, const char *line) static void auth_client_input(struct auth_client_connection *conn) { + const char *args; char *line; bool ret; @@ -270,8 +273,8 @@ static void auth_client_input(struct auth_client_connection *conn) const char *p; /* split the version line */ - if (!str_begins(line, "VERSION\t") || - str_parse_uint(line + 8, &vmajor, &p) < 0 || + if (!str_begins(line, "VERSION\t", &args) || + str_parse_uint(args, &vmajor, &p) < 0 || *(p++) != '\t' || str_to_uint(p, &vminor) < 0) { e_error(conn->event, "Authentication client " "sent invalid VERSION line: %s", line); @@ -291,8 +294,8 @@ static void auth_client_input(struct auth_client_connection *conn) continue; } - if (str_begins(line, "CPID\t")) { - if (!auth_client_input_cpid(conn, line + 5)) { + if (str_begins(line, "CPID\t", &args)) { + if (!auth_client_input_cpid(conn, args)) { auth_client_connection_destroy(&conn); return; } diff --git a/src/auth/auth-master-connection.c b/src/auth/auth-master-connection.c index 9aa83feeed..1f13362d7d 100644 --- a/src/auth/auth-master-connection.c +++ b/src/auth/auth-master-connection.c @@ -630,21 +630,23 @@ master_input_list(struct auth_master_connection *conn, const char *args) static bool auth_master_input_line(struct auth_master_connection *conn, const char *line) { + const char *args; + e_debug(auth_event, "master in: %s", line); - if (str_begins(line, "USER\t")) - return master_input_user(conn, line + 5); - if (str_begins(line, "LIST\t")) - return master_input_list(conn, line + 5); - if (str_begins(line, "PASS\t")) - return master_input_pass(conn, line + 5); + if (str_begins(line, "USER\t", &args)) + return master_input_user(conn, args); + if (str_begins(line, "LIST\t", &args)) + return master_input_list(conn, args); + if (str_begins(line, "PASS\t", &args)) + return master_input_pass(conn, args); if (!conn->userdb_only) { i_assert(conn->userdb_restricted_uid == 0); - if (str_begins(line, "REQUEST\t")) - return master_input_request(conn, line + 8); - if (str_begins(line, "CACHE-FLUSH\t")) - return master_input_cache_flush(conn, line + 12); + if (str_begins(line, "REQUEST\t", &args)) + return master_input_request(conn, args); + if (str_begins(line, "CACHE-FLUSH\t", &args)) + return master_input_cache_flush(conn, args); if (str_begins_with(line, "CPID\t")) { e_error(conn->event, "Authentication client trying to connect to " @@ -661,6 +663,7 @@ auth_master_input_line(struct auth_master_connection *conn, const char *line) static void master_input(struct auth_master_connection *conn) { + const char *args; char *line; bool ret; @@ -685,8 +688,8 @@ static void master_input(struct auth_master_connection *conn) return; /* make sure the major version matches */ - if (!str_begins(line, "VERSION\t") || - !str_uint_equals(t_strcut(line + 8, '\t'), + if (!str_begins(line, "VERSION\t", &args) || + !str_uint_equals(t_strcut(args, '\t'), AUTH_MASTER_PROTOCOL_MAJOR_VERSION)) { e_error(conn->event, "Master not compatible with this server " diff --git a/src/auth/auth-request-fields.c b/src/auth/auth-request-fields.c index 590e6711b1..9335e90f08 100644 --- a/src/auth/auth-request-fields.c +++ b/src/auth/auth-request-fields.c @@ -273,12 +273,12 @@ bool auth_request_import(struct auth_request *request, } else if (strcmp(key, "mech") == 0) { fields->mech_name = p_strdup(request->pool, value); event_add_str(request->event, "mechanism", value); - } else if (str_begins(key, "passdb_")) - auth_fields_add(fields->extra_fields, key+7, value, 0); - else if (str_begins(key, "userdb_")) { + } else if (str_begins(key, "passdb_", &key)) + auth_fields_add(fields->extra_fields, key, value, 0); + else if (str_begins(key, "userdb_", &key)) { if (fields->userdb_reply == NULL) auth_request_init_userdb_reply(request, FALSE); - auth_fields_add(fields->userdb_reply, key+7, value, 0); + auth_fields_add(fields->userdb_reply, key, value, 0); } else return FALSE; diff --git a/src/auth/auth-request.c b/src/auth/auth-request.c index a9131e6438..cd08b1fa02 100644 --- a/src/auth/auth-request.c +++ b/src/auth/auth-request.c @@ -1725,6 +1725,7 @@ void auth_request_set_field(struct auth_request *request, const char *name, const char *value, const char *default_scheme) { + const char *suffix; size_t name_len = strlen(name); i_assert(*name != '\0'); @@ -1800,7 +1801,7 @@ void auth_request_set_field(struct auth_request *request, } else if (strcmp(name, "allow_real_nets") == 0) { auth_request_validate_networks(request, name, value, &request->fields.real_remote_ip); - } else if (str_begins(name, "userdb_")) { + } else if (str_begins(name, "userdb_", &suffix)) { /* for prefetch userdb */ request->userdb_prefetch_set = TRUE; if (request->fields.userdb_reply == NULL) @@ -1813,7 +1814,7 @@ void auth_request_set_field(struct auth_request *request, "userdb_", default_scheme); return; } - auth_request_set_userdb_field(request, name + 7, value); + auth_request_set_userdb_field(request, suffix, value); } else if (strcmp(name, "noauthenticate") == 0) { /* add "nopassword" also so that passdbs won't try to verify the password. */ diff --git a/src/auth/db-oauth2.c b/src/auth/db-oauth2.c index 3c6ef3acb9..f34060a7d3 100644 --- a/src/auth/db-oauth2.c +++ b/src/auth/db-oauth2.c @@ -389,13 +389,13 @@ db_oauth2_have_all_fields(struct db_oauth2_request *req) while(ptr != NULL) { ptr = strchr(ptr, '%'); if (ptr != NULL) { - const char *field; + const char *field, *suffix; ptr++; var_get_key_range(ptr, &idx, &size); ptr = ptr+idx; field = t_strndup(ptr,size); - if (str_begins(field, "oauth2:") && - !auth_fields_exists(req->fields, ptr+7)) + if (str_begins(field, "oauth2:", &suffix) && + !auth_fields_exists(req->fields, suffix)) return FALSE; ptr = ptr+size; } diff --git a/src/auth/mech-oauth2.c b/src/auth/mech-oauth2.c index 1b145674b3..4348b10aff 100644 --- a/src/auth/mech-oauth2.c +++ b/src/auth/mech-oauth2.c @@ -133,20 +133,19 @@ mech_xoauth2_auth_continue(struct auth_request *request, /* split the data from ^A */ bool user_given = FALSE; - const char *error; + const char *value, *error; const char *token = NULL; const char *const *ptr; const char *username; const char *const *fields = t_strsplit(t_strndup(data, data_size), "\x01"); for(ptr = fields; *ptr != NULL; ptr++) { - if (str_begins(*ptr, "user=")) { + if (str_begins(*ptr, "user=", &value)) { /* xoauth2 does not require unescaping because the data format does not contain anything to escape */ - username = (*ptr)+5; + username = value; user_given = TRUE; - } else if (str_begins(*ptr, "auth=")) { - const char *value = (*ptr)+5; + } else if (str_begins(*ptr, "auth=", &value)) { if (strncasecmp(value, "bearer ", 7) == 0 && oauth2_valid_token(value+7)) { token = value+7; @@ -193,7 +192,7 @@ mech_oauthbearer_auth_continue(struct auth_request *request, } bool user_given = FALSE; - const char *error; + const char *value, *error; const char *username; const char *const *ptr; /* split the data from ^A */ @@ -246,8 +245,7 @@ mech_oauthbearer_auth_continue(struct auth_request *request, } for(ptr = fields; *ptr != NULL; ptr++) { - if (str_begins(*ptr, "auth=")) { - const char *value = (*ptr)+5; + if (str_begins(*ptr, "auth=", &value)) { if (strncasecmp(value, "bearer ", 7) == 0 && oauth2_valid_token(value+7)) { token = value+7; diff --git a/src/auth/mech-otp.c b/src/auth/mech-otp.c index 58f3db15e0..7aa9d7e585 100644 --- a/src/auth/mech-otp.c +++ b/src/auth/mech-otp.c @@ -181,16 +181,16 @@ static void mech_otp_auth_phase2(struct auth_request *auth_request, const unsigned char *data, size_t data_size) { - const char *str = t_strndup(data, data_size); - - if (str_begins(str, "hex:")) { - mech_otp_verify(auth_request, str + 4, TRUE); - } else if (str_begins(str, "word:")) { - mech_otp_verify(auth_request, str + 5, FALSE); - } else if (str_begins(str, "init-hex:")) { - mech_otp_verify_init(auth_request, str + 9, TRUE); - } else if (str_begins(str, "init-word:")) { - mech_otp_verify_init(auth_request, str + 10, FALSE); + const char *value, *str = t_strndup(data, data_size); + + if (str_begins(str, "hex:", &value)) { + mech_otp_verify(auth_request, value, TRUE); + } else if (str_begins(str, "word:", &value)) { + mech_otp_verify(auth_request, value, FALSE); + } else if (str_begins(str, "init-hex:", &value)) { + mech_otp_verify_init(auth_request, value, TRUE); + } else if (str_begins(str, "init-word:", &value)) { + mech_otp_verify_init(auth_request, value, FALSE); } else { e_error(auth_request->mech_event, "unsupported response type"); diff --git a/src/auth/passdb-bsdauth.c b/src/auth/passdb-bsdauth.c index 36469c679b..c8d902a097 100644 --- a/src/auth/passdb-bsdauth.c +++ b/src/auth/passdb-bsdauth.c @@ -60,6 +60,7 @@ static struct passdb_module * bsdauth_preinit(pool_t pool, const char *args) { struct passdb_module *module; + const char *value; module = p_new(pool, struct passdb_module, 1); module->default_pass_scheme = "PLAIN"; /* same reason as PAM */ @@ -67,8 +68,8 @@ bsdauth_preinit(pool_t pool, const char *args) if (strcmp(args, "blocking=no") == 0) module->blocking = FALSE; - else if (str_begins(args, "cache_key=")) - module->default_cache_key = auth_cache_parse_key(pool, args + 10); + else if (str_begins(args, "cache_key=", &value)) + module->default_cache_key = auth_cache_parse_key(pool, value); else if (*args != '\0') i_fatal("passdb bsdauth: Unknown setting: %s", args); return module; diff --git a/src/auth/passdb-checkpassword.c b/src/auth/passdb-checkpassword.c index 101c7f0c57..b351b94d72 100644 --- a/src/auth/passdb-checkpassword.c +++ b/src/auth/passdb-checkpassword.c @@ -33,8 +33,8 @@ auth_checkpassword_callback(struct auth_request *request, break; } for (i = 0; extra_fields[i] != NULL; i++) { - if (str_begins(extra_fields[i], "password=")) - crypted_pass = extra_fields[i]+9; + if (str_begins(extra_fields[i], "password=", &crypted_pass)) + ; else if (extra_fields[i][0] != '\0') { auth_request_set_field_keyvalue(request, extra_fields[i], NULL); @@ -86,8 +86,8 @@ credentials_checkpassword_callback(struct auth_request *request, break; } for (i = 0; extra_fields[i] != NULL; i++) { - if (str_begins(extra_fields[i], "password=")) - crypted_pass = extra_fields[i]+9; + if (str_begins(extra_fields[i], "password=", &crypted_pass)) + ; else if (extra_fields[i][0] != '\0') { auth_request_set_field_keyvalue(request, extra_fields[i], NULL); diff --git a/src/auth/passdb-lua.c b/src/auth/passdb-lua.c index 0ad15a5162..1b39146efc 100644 --- a/src/auth/passdb-lua.c +++ b/src/auth/passdb-lua.c @@ -107,17 +107,16 @@ static struct passdb_module * passdb_lua_preinit(pool_t pool, const char *args) { const char *cache_key = DB_LUA_CACHE_KEY; - const char *scheme = "PLAIN"; + const char *value, *scheme = "PLAIN"; struct dlua_passdb_module *module; bool blocking = TRUE; module = p_new(pool, struct dlua_passdb_module, 1); const char *const *fields = t_strsplit_spaces(args, " "); while(*fields != NULL) { - if (str_begins(*fields, "file=")) { - module->file = p_strdup(pool, (*fields)+5); - } else if (str_begins(*fields, "blocking=")) { - const char *value = (*fields)+9; + if (str_begins(*fields, "file=", &value)) { + module->file = p_strdup(pool, value); + } else if (str_begins(*fields, "blocking=", &value)) { if (strcmp(value, "yes") == 0) { blocking = TRUE; } else if (strcmp(value, "no") == 0) { @@ -127,13 +126,13 @@ passdb_lua_preinit(pool_t pool, const char *args) "Field blocking must be yes or no", value); } - } else if (str_begins(*fields, "cache_key=")) { - if (*((*fields)+10) != '\0') - cache_key = (*fields)+10; + } else if (str_begins(*fields, "cache_key=", &value)) { + if (value[0] != '\0') + cache_key = value; else /* explicitly disable auth caching for lua */ cache_key = NULL; - } else if (str_begins(*fields, "scheme=")) { - scheme = p_strdup(pool, (*fields)+7); + } else if (str_begins(*fields, "scheme=", &value)) { + scheme = p_strdup(pool, value); } else { i_fatal("Unsupported parameter %s", *fields); } diff --git a/src/auth/passdb-pam.c b/src/auth/passdb-pam.c index 6a1032dfc5..6fd5e8ca1b 100644 --- a/src/auth/passdb-pam.c +++ b/src/auth/passdb-pam.c @@ -339,7 +339,7 @@ static struct passdb_module * pam_preinit(pool_t pool, const char *args) { struct pam_passdb_module *module; - const char *const *t_args; + const char *value, *const *t_args; int i; module = p_new(pool, struct pam_passdb_module, 1); @@ -358,9 +358,9 @@ pam_preinit(pool_t pool, const char *args) module->pam_session = TRUE; else if (strcmp(t_args[i], "setcred=yes") == 0) module->pam_setcred = TRUE; - else if (str_begins(t_args[i], "cache_key=")) { + else if (str_begins(t_args[i], "cache_key=", &value)) { module->module.default_cache_key = - auth_cache_parse_key(pool, t_args[i] + 10); + auth_cache_parse_key(pool, value); } else if (strcmp(t_args[i], "blocking=yes") == 0) { /* ignore, for backwards compatibility */ } else if (strcmp(t_args[i], "failure_show_msg=yes") == 0) { @@ -368,11 +368,10 @@ pam_preinit(pool_t pool, const char *args) } else if (strcmp(t_args[i], "*") == 0) { /* for backwards compatibility */ module->service_name = "%Ls"; - } else if (str_begins(t_args[i], "max_requests=")) { - if (str_to_uint(t_args[i] + 13, - &module->requests_left) < 0) { + } else if (str_begins(t_args[i], "max_requests=", &value)) { + if (str_to_uint(value, &module->requests_left) < 0) { i_error("pam: Invalid requests_left value: %s", - t_args[i] + 13); + value); } } else if (t_args[i+1] == NULL) { module->service_name = p_strdup(pool, t_args[i]); diff --git a/src/auth/password-scheme.c b/src/auth/password-scheme.c index 6d09af603d..46755918e8 100644 --- a/src/auth/password-scheme.c +++ b/src/auth/password-scheme.c @@ -110,14 +110,14 @@ int password_verify(const char *plaintext, const char *password_get_scheme(const char **password) { - const char *p, *scheme; + const char *p, *suffix, *scheme; if (*password == NULL) return NULL; - if (str_begins(*password, "$1$")) { + if (str_begins(*password, "$1$", &suffix)) { /* $1$$[$] */ - p = strchr(*password + 3, '$'); + p = strchr(suffix, '$'); if (p != NULL) { /* stop at next '$' after password */ p = strchr(p+1, '$'); diff --git a/src/auth/userdb-blocking.c b/src/auth/userdb-blocking.c index 4163259118..37952535ad 100644 --- a/src/auth/userdb-blocking.c +++ b/src/auth/userdb-blocking.c @@ -20,15 +20,12 @@ static bool user_callback(const char *reply, void *context) enum userdb_result result; const char *username, *args; - if (str_begins(reply, "FAIL\t")) { + if (str_begins(reply, "FAIL\t", &args)) { result = USERDB_RESULT_INTERNAL_FAILURE; - args = reply + 5; - } else if (str_begins(reply, "NOTFOUND\t")) { + } else if (str_begins(reply, "NOTFOUND\t", &args)) { result = USERDB_RESULT_USER_UNKNOWN; - args = reply + 9; - } else if (str_begins(reply, "OK\t")) { + } else if (str_begins(reply, "OK\t", &username)) { result = USERDB_RESULT_OK; - username = reply + 3; args = strchr(username, '\t'); if (args == NULL) args = ""; @@ -73,12 +70,13 @@ void userdb_blocking_lookup(struct auth_request *request) static bool iter_callback(const char *reply, void *context) { struct blocking_userdb_iterate_context *ctx = context; + const char *args; - if (str_begins(reply, "*\t")) { + if (str_begins(reply, "*\t", &args)) { if (ctx->destroyed) return TRUE; ctx->next = FALSE; - ctx->ctx.callback(reply + 2, ctx->ctx.context); + ctx->ctx.callback(args, ctx->ctx.context); return ctx->next || ctx->destroyed; } diff --git a/src/auth/userdb-lua.c b/src/auth/userdb-lua.c index 6ffa12464f..1712f70162 100644 --- a/src/auth/userdb-lua.c +++ b/src/auth/userdb-lua.c @@ -33,16 +33,15 @@ static struct userdb_module * userdb_lua_preinit(pool_t pool, const char *args) { struct dlua_userdb_module *module; - const char *cache_key = DB_LUA_CACHE_KEY; + const char *value, *cache_key = DB_LUA_CACHE_KEY; bool blocking = TRUE; module = p_new(pool, struct dlua_userdb_module, 1); const char *const *fields = t_strsplit_spaces(args, " "); while(*fields != NULL) { - if (str_begins(*fields, "file=")) { - module->file = p_strdup(pool, (*fields)+5); - } else if (str_begins(*fields, "blocking=")) { - const char *value = (*fields)+9; + if (str_begins(*fields, "file=", &value)) + module->file = p_strdup(pool, value); + else if (str_begins(*fields, "blocking=", &value)) { if (strcmp(value, "yes") == 0) { blocking = TRUE; } else if (strcmp(value, "no") == 0) { @@ -52,9 +51,9 @@ userdb_lua_preinit(pool_t pool, const char *args) "Field blocking must be yes or no", value); } - } else if (str_begins(*fields, "cache_key=")) { - if (*((*fields)+10) != '\0') - cache_key = (*fields)+10; + } else if (str_begins(*fields, "cache_key=", &value)) { + if (value[0] != '\0') + cache_key = value; else /* explicitly disable auth caching for lua */ cache_key = NULL; } else { diff --git a/src/auth/userdb-passwd-file.c b/src/auth/userdb-passwd-file.c index 1e87138edc..b9f736824c 100644 --- a/src/auth/userdb-passwd-file.c +++ b/src/auth/userdb-passwd-file.c @@ -38,10 +38,9 @@ passwd_file_add_extra_fields(struct auth_request *request, char *const *fields) table = auth_request_get_var_expand_table(request, NULL); for (i = 0; fields[i] != NULL; i++) { - if (!str_begins(fields[i], "userdb_")) + if (!str_begins(fields[i], "userdb_", &key)) continue; - key = fields[i] + 7; value = strchr(key, '='); if (value != NULL) { key = t_strdup_until(key, value); @@ -189,8 +188,7 @@ passwd_file_preinit(pool_t pool, const char *args) const char *format = PASSWD_FILE_DEFAULT_USERNAME_FORMAT; const char *p; - if (str_begins(args, "username_format=")) { - args += 16; + if (str_begins(args, "username_format=", &args)) { p = strchr(args, ' '); if (p == NULL) { format = p_strdup(pool, args); diff --git a/src/config/config-connection.c b/src/config/config-connection.c index bd3db86505..26c3e4eb57 100644 --- a/src/config/config-connection.c +++ b/src/config/config-connection.c @@ -70,7 +70,7 @@ static int config_connection_request(struct config_connection *conn, struct config_export_context *ctx; struct master_service_settings_output output; struct config_filter filter; - const char *path, *error, *module, *const *wanted_modules; + const char *path, *value, *error, *module, *const *wanted_modules; ARRAY(const char *) modules; ARRAY(const char *) exclude_settings; bool is_master = FALSE; @@ -80,26 +80,24 @@ static int config_connection_request(struct config_connection *conn, t_array_init(&exclude_settings, 4); i_zero(&filter); for (; *args != NULL; args++) { - if (str_begins(*args, "service=")) - filter.service = *args + 8; - else if (str_begins(*args, "module=")) { - module = *args + 7; + if (str_begins(*args, "service=", &filter.service)) + ; + else if (str_begins(*args, "module=", &module)) { if (strcmp(module, "master") == 0) is_master = TRUE; array_push_back(&modules, &module); - } else if (str_begins(*args, "exclude=")) { - const char *value = *args + 8; + } else if (str_begins(*args, "exclude=", &value)) array_push_back(&exclude_settings, &value); - } else if (str_begins(*args, "lname=")) - filter.local_name = *args + 6; - else if (str_begins(*args, "lip=")) { - if (net_addr2ip(*args + 4, &filter.local_net) == 0) { + else if (str_begins(*args, "lname=", &filter.local_name)) + ; + else if (str_begins(*args, "lip=", &value)) { + if (net_addr2ip(value, &filter.local_net) == 0) { filter.local_bits = IPADDR_IS_V4(&filter.local_net) ? 32 : 128; } - } else if (str_begins(*args, "rip=")) { - if (net_addr2ip(*args + 4, &filter.remote_net) == 0) { + } else if (str_begins(*args, "rip=", &value)) { + if (net_addr2ip(value, &filter.remote_net) == 0) { filter.remote_bits = IPADDR_IS_V4(&filter.remote_net) ? 32 : 128; diff --git a/src/config/config-parser.c b/src/config/config-parser.c index 26090deb5b..e555767093 100644 --- a/src/config/config-parser.c +++ b/src/config/config-parser.c @@ -797,7 +797,7 @@ static int config_write_keyvariable(struct config_parser_context *ctx, const char *var_end, *p_start = value; bool dump; while (value != NULL) { - const char *var_name; + const char *var_name, *env_name; bool expand_parent; var_end = strchr(value, ' '); @@ -816,9 +816,9 @@ static int config_write_keyvariable(struct config_parser_context *ctx, str_append(str, var_name); } else if (!ctx->expand_values && !expand_parent) { str_append(str, var_name); - } else if (str_begins(var_name, "$ENV:")) { + } else if (str_begins(var_name, "$ENV:", &env_name)) { /* use environment variable */ - const char *envval = getenv(var_name+5); + const char *envval = getenv(env_name); if (envval != NULL) str_append(str, envval); } else { diff --git a/src/config/old-set-parser.c b/src/config/old-set-parser.c index 08f3085d9f..89c05292f7 100644 --- a/src/config/old-set-parser.c +++ b/src/config/old-set-parser.c @@ -123,7 +123,7 @@ static bool old_settings_handle_root(struct config_parser_context *ctx, const char *key, const char *value) { - const char *p; + const char *p, *suffix; size_t len; if (strcmp(key, "base_dir") == 0) { @@ -240,8 +240,8 @@ old_settings_handle_root(struct config_parser_context *ctx, set_rename(ctx, key, "mdbox_rotate_size", value); return TRUE; } - if (str_begins(key, "mail_cache_compress_")) { - const char *new_key = t_strconcat("mail_cache_purge_", key+20, NULL); + if (str_begins(key, "mail_cache_compress_", &suffix)) { + const char *new_key = t_strconcat("mail_cache_purge_", suffix, NULL); set_rename(ctx, key, new_key, value); return TRUE; } @@ -588,7 +588,7 @@ static bool old_auth_section(struct config_parser_context *ctx, static void socket_apply(struct config_parser_context *ctx) { const struct socket_set *set = &ctx->old->socket_set; - const char *path, *prefix; + const char *path, *prefix, *suffix; size_t len; bool master_suffix; @@ -597,10 +597,9 @@ static void socket_apply(struct config_parser_context *ctx) return; } path = set->path; - len = strlen(ctx->old->base_dir); - if (str_begins(path, ctx->old->base_dir) && - path[len] == '/') - path += len + 1; + if (str_begins(path, ctx->old->base_dir, &suffix) && + suffix[0] == '/') + path = suffix + 1; len = strlen(path); master_suffix = len >= 7 && diff --git a/src/config/sysinfo-get.c b/src/config/sysinfo-get.c index dffebe6e2c..0d55cd634d 100644 --- a/src/config/sysinfo-get.c +++ b/src/config/sysinfo-get.c @@ -31,19 +31,19 @@ static bool readfile(const char *path, const char **data_r) static bool lsb_distro_get(const char *path, const char **name_r) { - const char *data, *const *p, *str, *end; + const char *data, *const *p, *str = NULL, *end; if (!readfile(path, &data)) return FALSE; for (p = t_strsplit(data, "\n"); *p != NULL; p++) { - if (str_begins(*p, "DISTRIB_DESCRIPTION=")) + if (str_begins(*p, "DISTRIB_DESCRIPTION=", &str)) break; } - if (*p == NULL) + if (str == NULL) return FALSE; - str = t_strcut(*p + 20, '\n'); + str = t_strcut(str, '\n'); if (*str != '"') *name_r = str; else { diff --git a/src/director/login-connection.c b/src/director/login-connection.c index 765ad0aabb..eae0c66ef7 100644 --- a/src/director/login-connection.c +++ b/src/director/login-connection.c @@ -144,11 +144,8 @@ login_host_callback(const struct mail_host *host, const char *hostname, unsigned int secs; if (host == NULL) { - if (str_begins(request->line, "OK\t")) - line_params = request->line + 3; - else if (str_begins(request->line, "PASS\t")) - line_params = request->line + 5; - else + if (!str_begins(request->line, "OK\t", &line_params) && + !str_begins(request->line, "PASS\t", &line_params)) i_panic("BUG: Unexpected line: %s", request->line); e_error(dir->event, "director: User %s host lookup failed: %s", @@ -191,6 +188,7 @@ static void auth_input_line(const char *line, void *context) struct login_connection *conn = context; struct login_host_request *request, temp_request; const char *const *args, *line_params, *username = NULL, *tag = ""; + const char *value; bool proxy = FALSE, host = FALSE; if (line == NULL) { @@ -199,11 +197,11 @@ static void auth_input_line(const char *line, void *context) return; } if (conn->type != LOGIN_CONNECTION_TYPE_USERDB && - str_begins(line, "OK\t")) - line_params = line + 3; + str_begins(line, "OK\t", &line_params)) + ; else if (conn->type == LOGIN_CONNECTION_TYPE_USERDB && - str_begins(line, "PASS\t")) - line_params = line + 5; + str_begins(line, "PASS\t", &line_params)) + ; else { login_connection_send_line(conn, line); return; @@ -219,30 +217,30 @@ static void auth_input_line(const char *line, void *context) i_zero(&temp_request); for (; *args != NULL; args++) { - if (str_begins(*args, "proxy") && - ((*args)[5] == '=' || (*args)[5] == '\0')) + if (str_begins(*args, "proxy", &value) && + (value[0] == '=' || value[0] == '\0')) proxy = TRUE; else if (str_begins_with(*args, "host=")) host = TRUE; - else if (str_begins(*args, "lip=")) { - if (net_addr2ip((*args) + 4, &temp_request.local_ip) < 0) + else if (str_begins(*args, "lip=", &value)) { + if (net_addr2ip(value, &temp_request.local_ip) < 0) e_error(conn->dir->event, "auth sent invalid lip field: %s", (*args) + 6); - } else if (str_begins(*args, "lport=")) { - if (net_str2port((*args) + 6, &temp_request.local_port) < 0) + } else if (str_begins(*args, "lport=", &value)) { + if (net_str2port(value, &temp_request.local_port) < 0) e_error(conn->dir->event, "auth sent invalid lport field: %s", (*args) + 6); - } else if (str_begins(*args, "port=")) { - if (net_str2port((*args) + 5, &temp_request.dest_port) < 0) + } else if (str_begins(*args, "port=", &value)) { + if (net_str2port(value, &temp_request.dest_port) < 0) e_error(conn->dir->event, "auth sent invalid port field: %s", (*args) + 6); - } else if (str_begins(*args, "destuser=")) - username = *args + 9; - else if (str_begins(*args, "director_tag=")) - tag = *args + 13; - else if (str_begins(*args, "director_proxy_maybe") && - ((*args)[20] == '=' || (*args)[20] == '\0')) + } else if (str_begins(*args, "destuser=", &value)) + username = value; + else if (str_begins(*args, "director_tag=", &value)) + tag = value; + else if (str_begins(*args, "director_proxy_maybe", &value) && + (value[0] == '=' || value[0] == '\0')) temp_request.director_proxy_maybe = TRUE; - else if (str_begins(*args, "user=")) { + else if (str_begins(*args, "user=", &value)) { if (username == NULL) - username = *args + 5; + username = value; } } if ((!proxy && !temp_request.director_proxy_maybe) || diff --git a/src/doveadm/client-connection-tcp.c b/src/doveadm/client-connection-tcp.c index 23f24dc320..c1a2448470 100644 --- a/src/doveadm/client-connection-tcp.c +++ b/src/doveadm/client-connection-tcp.c @@ -336,7 +336,7 @@ static int client_connection_tcp_authenticate(struct client_connection_tcp *conn) { const struct doveadm_settings *set = conn->conn.set; - const char *line, *pass; + const char *line, *args, *pass; buffer_t *plain; const unsigned char *data; size_t size; @@ -363,13 +363,13 @@ client_connection_tcp_authenticate(struct client_connection_tcp *conn) /* FIXME: some day we should probably let auth process do this and support all kinds of authentication */ - if (!str_begins(line, "PLAIN\t")) { + if (!str_begins(line, "PLAIN\t", &args)) { i_error("doveadm client attempted non-PLAIN authentication: %s", line); return -1; } plain = t_buffer_create(128); - if (base64_decode(line + 6, strlen(line + 6), plain) < 0) { + if (base64_decode(args, strlen(args), plain) < 0) { i_error("doveadm client sent invalid base64 auth PLAIN data"); return -1; } diff --git a/src/doveadm/doveadm-auth-server.c b/src/doveadm/doveadm-auth-server.c index f50fa5f4e5..7a6016543b 100644 --- a/src/doveadm/doveadm-auth-server.c +++ b/src/doveadm/doveadm-auth-server.c @@ -141,19 +141,21 @@ cmd_user_input(struct auth_master_connection *conn, static void auth_user_info_parse(struct auth_user_info *info, const char *arg) { - if (str_begins(arg, "service=")) - info->service = arg + 8; - else if (str_begins(arg, "lip=")) { - if (net_addr2ip(arg + 4, &info->local_ip) < 0) + const char *value; + + if (str_begins(arg, "service=", &value)) + info->service = value; + else if (str_begins(arg, "lip=", &value)) { + if (net_addr2ip(value, &info->local_ip) < 0) i_fatal("lip: Invalid ip"); - } else if (str_begins(arg, "rip=")) { - if (net_addr2ip(arg + 4, &info->remote_ip) < 0) + } else if (str_begins(arg, "rip=", &value)) { + if (net_addr2ip(value, &info->remote_ip) < 0) i_fatal("rip: Invalid ip"); - } else if (str_begins(arg, "lport=")) { - if (net_str2port(arg + 6, &info->local_port) < 0) + } else if (str_begins(arg, "lport=", &value)) { + if (net_str2port(value, &info->local_port) < 0) i_fatal("lport: Invalid port number"); - } else if (str_begins(arg, "rport=")) { - if (net_str2port(arg + 6, &info->remote_port) < 0) + } else if (str_begins(arg, "rport=", &value)) { + if (net_str2port(value, &info->remote_port) < 0) i_fatal("rport: Invalid port number"); } else { i_fatal("Unknown -x argument: %s", arg); diff --git a/src/doveadm/doveadm-auth.c b/src/doveadm/doveadm-auth.c index d89befe2e4..17058f611c 100644 --- a/src/doveadm/doveadm-auth.c +++ b/src/doveadm/doveadm-auth.c @@ -236,39 +236,40 @@ cmd_auth_input(const char *auth_socket_path, struct authtest_input *input) static void auth_user_info_parse_arg(struct auth_user_info *info, const char *arg) { - if (str_begins(arg, "service=")) - info->service = arg + 8; - else if (str_begins(arg, "session=")) - info->session_id = arg + 8; - else if (str_begins(arg, "local_name=")) - info->local_name = arg + 11; - else if (str_begins(arg, "lip=")) { - if (net_addr2ip(arg + 4, &info->local_ip) < 0) + const char *key, *value; + + if (str_begins(arg, "service=", &value)) + info->service = value; + else if (str_begins(arg, "session=", &value)) + info->session_id = value; + else if (str_begins(arg, "local_name=", &value)) + info->local_name = value; + else if (str_begins(arg, "lip=", &value)) { + if (net_addr2ip(value, &info->local_ip) < 0) i_fatal("lip: Invalid ip"); - } else if (str_begins(arg, "rip=")) { - if (net_addr2ip(arg + 4, &info->remote_ip) < 0) + } else if (str_begins(arg, "rip=", &value)) { + if (net_addr2ip(value, &info->remote_ip) < 0) i_fatal("rip: Invalid ip"); - } else if (str_begins(arg, "lport=")) { - if (net_str2port(arg + 6, &info->local_port) < 0) + } else if (str_begins(arg, "lport=", &value)) { + if (net_str2port(value, &info->local_port) < 0) i_fatal("lport: Invalid port number"); - } else if (str_begins(arg, "rport=")) { - if (net_str2port(arg + 6, &info->remote_port) < 0) + } else if (str_begins(arg, "rport=", &value)) { + if (net_str2port(value, &info->remote_port) < 0) i_fatal("rport: Invalid port number"); - } else if (str_begins(arg, "real_lip=")) { - if (net_addr2ip(arg + 9, &info->real_local_ip) < 0) + } else if (str_begins(arg, "real_lip=", &value)) { + if (net_addr2ip(value, &info->real_local_ip) < 0) i_fatal("real_lip: Invalid ip"); - } else if (str_begins(arg, "real_rip=")) { - if (net_addr2ip(arg + 9, &info->real_remote_ip) < 0) + } else if (str_begins(arg, "real_rip=", &value)) { + if (net_addr2ip(value, &info->real_remote_ip) < 0) i_fatal("real_rip: Invalid ip"); - } else if (str_begins(arg, "real_lport=")) { - if (net_str2port(arg + 11, &info->real_local_port) < 0) + } else if (str_begins(arg, "real_lport=", &value)) { + if (net_str2port(value, &info->real_local_port) < 0) i_fatal("real_lport: Invalid port number"); - } else if (str_begins(arg, "real_rport=")) { - if (net_str2port(arg + 11, &info->real_remote_port) < 0) + } else if (str_begins(arg, "real_rport=", &value)) { + if (net_str2port(value, &info->real_remote_port) < 0) i_fatal("real_rport: Invalid port number"); - } else if (str_begins(arg, "forward_")) { - const char *key = arg+8; - const char *value = strchr(arg+8, '='); + } else if (str_begins(arg, "forward_", &key)) { + value = strchr(key, '='); if (value == NULL) value = ""; diff --git a/src/doveadm/doveadm-dsync.c b/src/doveadm/doveadm-dsync.c index ed10499230..fbb1ce8d85 100644 --- a/src/doveadm/doveadm-dsync.c +++ b/src/doveadm/doveadm-dsync.c @@ -1008,26 +1008,22 @@ parse_location(struct dsync_cmd_context *ctx, { struct doveadm_cmd_context *cctx = ctx->ctx.cctx; - if (str_begins(location, "tcp:")) { + if (str_begins(location, "tcp:", &ctx->remote_name)) { /* TCP connection to remote dsync */ - ctx->remote_name = location+4; return dsync_connect_tcp(ctx, ssl_set, ctx->remote_name, FALSE, error_r); } - if (str_begins(location, "tcps:")) { + if (str_begins(location, "tcps:", &ctx->remote_name)) { /* TCP+SSL connection to remote dsync */ - ctx->remote_name = location+5; return dsync_connect_tcp(ctx, ssl_set, ctx->remote_name, TRUE, error_r); } - if (str_begins(location, "remote:")) { + if (str_begins(location, "remote:", &ctx->remote_name)) { /* this is a remote (ssh) command */ - ctx->remote_name = location+7; - } else if (str_begins(location, "remoteprefix:")) { + } else if (str_begins(location, "remoteprefix:", &ctx->remote_name)) { /* this is a remote (ssh) command with a "user\n" prefix sent before dsync actually starts */ - ctx->remote_name = location+13; ctx->remote_user_prefix = TRUE; } else { /* local with e.g. maildir:path */ diff --git a/src/doveadm/doveadm-mail-fetch.c b/src/doveadm/doveadm-mail-fetch.c index 932a54de70..bed1a0147f 100644 --- a/src/doveadm/doveadm-mail-fetch.c +++ b/src/doveadm/doveadm-mail-fetch.c @@ -206,8 +206,11 @@ static int fetch_body_field(struct fetch_cmd_context *ctx) bool binary; int ret; - binary = str_begins(name, "binary."); - name += binary ? 7 : 5; + binary = str_begins(name, "binary.", &name); + if (!binary) { + if (!str_begins(name, "body.", &name)) + i_unreached(); + } if (imap_msgpart_parse(name, &msgpart) < 0) i_unreached(); /* we already verified this was ok */ if (binary) @@ -530,7 +533,7 @@ static void print_fetch_fields(void) static void parse_fetch_fields(struct fetch_cmd_context *ctx, const char *str) { - const char *const *fields, *name; + const char *const *fields, *name, *section; const struct fetch_field *field; struct fetch_field hdr_field, body_field; struct imap_msgpart *msgpart; @@ -551,21 +554,18 @@ static void parse_fetch_fields(struct fetch_cmd_context *ctx, const char *str) if ((field = fetch_field_find(name)) != NULL) { ctx->wanted_fields |= field->wanted_fields; array_push_back(&ctx->fields, field); - } else if (str_begins(name, "hdr.")) { - name += 4; + } else if (str_begins(name, "hdr.", &name)) { hdr_field.name = name; array_push_back(&ctx->fields, &hdr_field); name = t_strcut(name, '.'); array_push_back(&ctx->header_fields, &name); - } else if (str_begins(name, "body.") || - str_begins(name, "binary.")) { - bool binary = str_begins(name, "binary."); + } else if (str_begins(name, "body.", §ion) || + str_begins(name, "binary.", §ion)) { body_field.name = t_strarray_join(t_strsplit(name, ","), " "); - name += binary ? 7 : 5; - if (imap_msgpart_parse(name, &msgpart) < 0) { + if (imap_msgpart_parse(section, &msgpart) < 0) { print_fetch_fields(); - i_fatal("Unknown fetch section: %s", name); + i_fatal("Unknown fetch section: %s", section); } array_push_back(&ctx->fields, &body_field); ctx->wanted_fields |= imap_msgpart_get_fetch_data(msgpart); diff --git a/src/doveadm/doveadm-mail-mailbox-metadata.c b/src/doveadm/doveadm-mail-mailbox-metadata.c index 593555b05a..e5271d1505 100644 --- a/src/doveadm/doveadm-mail-mailbox-metadata.c +++ b/src/doveadm/doveadm-mail-mailbox-metadata.c @@ -124,12 +124,10 @@ cmd_mailbox_metadata_parse_key(const char *arg, { arg = t_str_lcase(arg); - if (str_begins(arg, "/private/")) { + if (str_begins(arg, "/private/", key_r)) { *type_r = MAIL_ATTRIBUTE_TYPE_PRIVATE; - *key_r = arg + 9; - } else if (str_begins(arg, "/shared/")) { + } else if (str_begins(arg, "/shared/", key_r)) { *type_r = MAIL_ATTRIBUTE_TYPE_SHARED; - *key_r = arg + 8; } else if (strcmp(arg, "/private") == 0) { *type_r = MAIL_ATTRIBUTE_TYPE_PRIVATE; *key_r = ""; diff --git a/src/doveadm/doveadm-mail-server.c b/src/doveadm/doveadm-mail-server.c index f9a8f752be..1a888a0e35 100644 --- a/src/doveadm/doveadm-mail-server.c +++ b/src/doveadm/doveadm-mail-server.c @@ -152,7 +152,7 @@ doveadm_cmd_pass_reply_parse(struct doveadm_mail_cmd_context *ctx, bool *nologin_r, const char **error_r) { const char *orig_user = proxy_set->username; - const char *error; + const char *error, *mend; int ret; proxy_set->username = NULL; @@ -190,13 +190,13 @@ doveadm_cmd_pass_reply_parse(struct doveadm_mail_cmd_context *ctx, else if (strcmp(key, "user") == 0) { if (proxy_set->username == NULL) proxy_set->username = t_strdup(value); - } else if (str_begins(key, "forward_")) { + } else if (str_begins(key, "forward_", &mend)) { if (!array_is_created(&ctx->proxy_forward_fields)) { p_array_init(&ctx->proxy_forward_fields, ctx->pool, 8); } value = p_strdup_printf(ctx->pool, "%s=%s", - key + 8, value); + mend, value); array_push_back(&ctx->proxy_forward_fields, &value); } } diff --git a/src/doveadm/doveadm-util.c b/src/doveadm/doveadm-util.c index 5a10692312..c5ec5d18a8 100644 --- a/src/doveadm/doveadm-util.c +++ b/src/doveadm/doveadm-util.c @@ -65,8 +65,7 @@ bool doveadm_has_unloaded_plugin(const char *name) while ((d = readdir(dir)) != NULL) { plugin_name = module_file_get_name(d->d_name); - if (str_begins(plugin_name, "doveadm_")) - plugin_name += 8; + (void)str_begins(plugin_name, "doveadm_", &plugin_name); if (strncmp(plugin_name, name, name_len) == 0 && (plugin_name[name_len] == '\0' || diff --git a/src/doveadm/dsync/dsync-brain-mailbox-tree.c b/src/doveadm/dsync/dsync-brain-mailbox-tree.c index 44b76bf47c..b529e4b21e 100644 --- a/src/doveadm/dsync/dsync-brain-mailbox-tree.c +++ b/src/doveadm/dsync/dsync-brain-mailbox-tree.c @@ -155,8 +155,7 @@ static bool dsync_namespace_match_parts(struct mail_namespace *ns, const char *const *name_parts) { - const char *part, *prefix = ns->prefix; - size_t part_len; + const char *part, *suffix, *prefix = ns->prefix; char ns_sep = mail_namespace_get_sep(ns); if ((ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0 && @@ -165,13 +164,12 @@ dsync_namespace_match_parts(struct mail_namespace *ns, for (; *name_parts != NULL && *prefix != '\0'; name_parts++) { part = *name_parts; - part_len = strlen(part); - if (!str_begins(prefix, part)) + if (!str_begins(prefix, part, &suffix)) return FALSE; - if (prefix[part_len] != ns_sep) + if (suffix[0] != ns_sep) return FALSE; - prefix += part_len + 1; + prefix = suffix + 1; } if (*name_parts != NULL) { /* namespace prefix found with a mailbox */ diff --git a/src/imap-hibernate/imap-client.c b/src/imap-hibernate/imap-client.c index 6ac0951e00..9dd26a8faf 100644 --- a/src/imap-hibernate/imap-client.c +++ b/src/imap-hibernate/imap-client.c @@ -141,10 +141,8 @@ imap_client_parse_userdb_fields(struct imap_client *client, field = t_strsplit_tabescaped(client->state.userdb_fields); for (i = 0; field[i] != NULL; i++) { - if (str_begins(field[i], "auth_user=")) { - *auth_user_r = field[i] + 10; + if (str_begins(field[i], "auth_user=", auth_user_r)) break; - } } } @@ -546,10 +544,8 @@ imap_client_var_expand_func_userdb(const char *data, void *context, const char *value = NULL; for(;*fields != NULL; fields++) { - if (str_begins(*fields, field_name)) { - value = *fields+strlen(field_name); + if (str_begins(*fields, field_name, &value)) break; - } } *value_r = value != NULL ? value : default_value; diff --git a/src/imap-login/imap-proxy.c b/src/imap-login/imap-proxy.c index 1fe5fbbf6d..aa38062ebf 100644 --- a/src/imap-login/imap-proxy.c +++ b/src/imap-login/imap-proxy.c @@ -168,11 +168,11 @@ static int proxy_write_login(struct imap_client *client, string_t *str) static int proxy_input_banner(struct imap_client *client, struct ostream *output, const char *line) { - const char *const *capabilities = NULL; + const char *suffix, *const *capabilities = NULL; string_t *str; int ret; - if (!str_begins(line, "* OK ")) { + if (!str_begins(line, "* OK ", &line)) { const char *reason = t_strdup_printf("Invalid banner: %s", str_sanitize(line, 160)); login_proxy_failed(client->common.login_proxy, @@ -182,15 +182,15 @@ static int proxy_input_banner(struct imap_client *client, } str = t_str_new(128); - if (str_begins(line + 5, "[CAPABILITY ")) { - capabilities = t_strsplit(t_strcut(line + 5 + 12, ']'), " "); + if (str_begins(line, "[CAPABILITY ", &suffix)) { + capabilities = t_strsplit(t_strcut(suffix, ']'), " "); if (str_array_icase_find(capabilities, "SASL-IR")) client->proxy_sasl_ir = TRUE; if (str_array_icase_find(capabilities, "LOGINDISABLED")) client->proxy_logindisabled = TRUE; i_free(client->proxy_backend_capability); client->proxy_backend_capability = - i_strdup(t_strcut(line + 5 + 12, ']')); + i_strdup(t_strcut(suffix, ']')); if (str_array_icase_find(capabilities, "ID") && !client->common.proxy_not_trusted) { client->proxy_sent_state |= IMAP_PROXY_SENT_STATE_ID; @@ -304,7 +304,7 @@ int imap_proxy_parse_line(struct client *client, const char *line) string_t *str; const unsigned char *data; size_t data_len; - const char *error; + const char *suffix, *error; int ret; i_assert(!client->destroyed); @@ -359,15 +359,15 @@ int imap_proxy_parse_line(struct client *client, const char *line) imap_client->proxy_sent_state |= IMAP_PROXY_SENT_STATE_AUTH_CONTINUE; o_stream_nsend(output, str_data(str), str_len(str)); return 0; - } else if (str_begins(line, "S ")) { + } else if (str_begins(line, "S ", &suffix)) { imap_client->proxy_sent_state &= ENUM_NEGATE(IMAP_PROXY_SENT_STATE_STARTTLS); imap_client->proxy_rcvd_state = IMAP_PROXY_RCVD_STATE_STARTTLS; - if (!str_begins_with(line, "S OK ")) { + if (!str_begins_with(suffix, "OK ")) { /* STARTTLS failed */ const char *reason = t_strdup_printf( "STARTTLS failed: %s", - str_sanitize(line + 2, 160)); + str_sanitize(suffix, 160)); login_proxy_failed(client->login_proxy, login_proxy_get_event(client->login_proxy), LOGIN_PROXY_FAILURE_TYPE_REMOTE, reason); @@ -383,21 +383,20 @@ int imap_proxy_parse_line(struct client *client, const char *line) return -1; o_stream_nsend(output, str_data(str), str_len(str)); return 1; - } else if (str_begins(line, "L OK ")) { + } else if (str_begins(line, "L OK ", &suffix)) { /* Login successful. Send this line to client. */ imap_client->proxy_sent_state &= ENUM_NEGATE(IMAP_PROXY_SENT_STATE_LOGIN); imap_client->proxy_rcvd_state = IMAP_PROXY_RCVD_STATE_LOGIN; str = t_str_new(128); - client_send_login_reply(imap_client, str, line + 5); + client_send_login_reply(imap_client, str, suffix); o_stream_nsend(client->output, str_data(str), str_len(str)); client_proxy_finish_destroy_client(client); return 1; - } else if (str_begins(line, "L ")) { + } else if (str_begins(line, "L ", &line)) { imap_client->proxy_sent_state &= ENUM_NEGATE(IMAP_PROXY_SENT_STATE_LOGIN); imap_client->proxy_rcvd_state = IMAP_PROXY_RCVD_STATE_LOGIN; - line += 2; const char *log_line = line; if (strncasecmp(log_line, "NO ", 3) == 0) log_line += 3; diff --git a/src/imap-urlauth/imap-urlauth.c b/src/imap-urlauth/imap-urlauth.c index 3585cdff7b..a849783dff 100644 --- a/src/imap-urlauth/imap-urlauth.c +++ b/src/imap-urlauth/imap-urlauth.c @@ -156,10 +156,8 @@ login_client_connected(const struct master_login_client *client, fields = array_get(&reply.extra_fields, &count); for (i = 0; i < count; i++) { - if (str_begins(fields[i], "client_service=")) { - service = fields[i] + 15; + if (str_begins(fields[i], "client_service=", &service)) break; - } } if (service == NULL) { diff --git a/src/imap/cmd-notify.c b/src/imap/cmd-notify.c index bd17fd29da..cdb6dc961f 100644 --- a/src/imap/cmd-notify.c +++ b/src/imap/cmd-notify.c @@ -151,9 +151,8 @@ cmd_notify_add_mailbox(struct imap_notify_context *ctx, { struct imap_notify_namespace *notify_ns; struct imap_notify_mailboxes *notify_boxes; - const char *const *names; + const char *suffix, *const *names; unsigned int i, count; - size_t cur_len, name_len = strlen(name); char ns_sep = mail_namespace_get_sep(ns); if (mail_namespace_is_removable(ns)) { @@ -183,14 +182,13 @@ cmd_notify_add_mailbox(struct imap_notify_context *ctx, i++; else { /* see if one is a subtree of the other */ - cur_len = strlen(names[i]); - if (str_begins(name, names[i]) && - names[i][cur_len] == ns_sep) { + if (str_begins(name, names[i], &suffix) && + suffix[0] == ns_sep) { /* already matched in this subtree */ return; } - if (str_begins(names[i], name) && - names[i][name_len] == ns_sep) { + if (str_begins(names[i], name, &suffix) && + suffix[0] == ns_sep) { /* we're adding a parent, remove the child */ array_delete(¬ify_boxes->names, i, 1); names = array_get(¬ify_boxes->names, &count); diff --git a/src/imap/cmd-rename.c b/src/imap/cmd-rename.c index 45b44fd183..a2f8c36178 100644 --- a/src/imap/cmd-rename.c +++ b/src/imap/cmd-rename.c @@ -8,8 +8,7 @@ bool cmd_rename(struct client_command_context *cmd) { struct mail_namespace *old_ns, *new_ns; struct mailbox *old_box, *new_box; - const char *oldname, *newname; - size_t oldlen; + const char *suffix, *oldname, *newname; /* */ if (!client_read_string_args(cmd, 2, &oldname, &newname)) @@ -26,9 +25,8 @@ bool cmd_rename(struct client_command_context *cmd) /* disallow box -> box/child, because it may break clients and there's really no point in doing it anyway. */ old_ns = mailbox_list_get_namespace(old_ns->list); - oldlen = strlen(oldname); - if (str_begins(newname, oldname) && - newname[oldlen] == mail_namespace_get_sep(old_ns)) { + if (str_begins(newname, oldname, &suffix) && + suffix[0] == mail_namespace_get_sep(old_ns)) { client_send_tagline(cmd, "NO Can't rename mailbox under its own child."); return TRUE; diff --git a/src/imap/imap-fetch-body.c b/src/imap/imap-fetch-body.c index b467334ec3..0c8f87f298 100644 --- a/src/imap/imap-fetch-body.c +++ b/src/imap/imap-fetch-body.c @@ -328,14 +328,12 @@ bool imap_fetch_body_section_init(struct imap_fetch_init_context *ctx) unsigned int list_count; const char *str, *p, *error; - i_assert(str_begins(ctx->name, "BODY")); - p = ctx->name + 4; + if (!str_begins(ctx->name, "BODY", &p)) + i_unreached(); body = p_new(ctx->pool, struct imap_fetch_body_data, 1); - if (str_begins(p, ".PEEK")) - p += 5; - else + if (!str_begins(p, ".PEEK", &p)) ctx->fetch_ctx->flags_update_seen = TRUE; if (*p != '[') { ctx->error = "Invalid BODY[..] parameter: Missing '['"; @@ -393,19 +391,16 @@ bool imap_fetch_binary_init(struct imap_fetch_init_context *ctx) unsigned int list_count; const char *str, *p, *error; - i_assert(str_begins(ctx->name, "BINARY")); - p = ctx->name + 6; + if (!str_begins(ctx->name, "BINARY", &p)) + i_unreached(); body = p_new(ctx->pool, struct imap_fetch_body_data, 1); body->binary = TRUE; - if (str_begins(p, ".SIZE")) { + if (str_begins(p, ".SIZE", &p)) { /* fetch decoded size of the section */ - p += 5; body->binary_size = TRUE; - } else if (str_begins(p, ".PEEK")) { - p += 5; - } else { + } else if (!str_begins(p, ".PEEK", &p)) { ctx->fetch_ctx->flags_update_seen = TRUE; } if (*p != '[') { diff --git a/src/imap/imap-notify.c b/src/imap/imap-notify.c index fa2c9ef4c1..80bc41bfa8 100644 --- a/src/imap/imap-notify.c +++ b/src/imap/imap-notify.c @@ -189,8 +189,7 @@ bool imap_notify_match_mailbox(struct imap_notify_namespace *notify_ns, const char *vname) { struct mailbox *box; - const char *name; - size_t name_len; + const char *name, *suffix; char ns_sep; bool ret; @@ -203,16 +202,14 @@ bool imap_notify_match_mailbox(struct imap_notify_namespace *notify_ns, case IMAP_NOTIFY_TYPE_SUBTREE: ns_sep = mail_namespace_get_sep(notify_ns->ns); array_foreach_elem(¬ify_boxes->names, name) { - name_len = strlen(name); - if (name_len == 0) { + if (name[0] == 0) { /* everything under root. NOTIFY spec itself doesn't define this, but we use it for implementing "personal" */ return TRUE; } - if (str_begins(vname, name) && - (vname[name_len] == '\0' || - vname[name_len] == ns_sep)) + if (str_begins(vname, name, &suffix) && + (suffix[0] == '\0' || suffix[0] == ns_sep)) return TRUE; } break; diff --git a/src/imap/imap-sync.c b/src/imap/imap-sync.c index fc49ae7230..b9990393e8 100644 --- a/src/imap/imap-sync.c +++ b/src/imap/imap-sync.c @@ -216,6 +216,7 @@ imap_sync_send_highestmodseq(struct imap_sync_context *ctx, struct client_command_context *sync_cmd) { struct client *client = ctx->client; + const char *suffix; uint64_t send_modseq = 0; if (ctx->sync_status.sync_delayed_expunges && @@ -237,12 +238,12 @@ imap_sync_send_highestmodseq(struct imap_sync_context *ctx, /* no sending */ } else if (sync_cmd->sync != NULL && /* IDLE doesn't have ->sync */ sync_cmd->sync->tagline != NULL && /* NOTIFY doesn't have tagline */ - str_begins(sync_cmd->sync->tagline, "OK ") && - sync_cmd->sync->tagline[3] != '[') { + str_begins(sync_cmd->sync->tagline, "OK ", &suffix) && + suffix[0] != '[') { /* modify the tagged reply directly */ sync_cmd->sync->tagline = p_strdup_printf(sync_cmd->pool, "OK [HIGHESTMODSEQ %"PRIu64"] %s", - send_modseq, sync_cmd->sync->tagline + 3); + send_modseq, suffix); } else { /* send an untagged OK reply */ client_send_line(client, t_strdup_printf( diff --git a/src/lib-auth/auth-client-request.c b/src/lib-auth/auth-client-request.c index 629b77bcfa..df68b5e4ea 100644 --- a/src/lib-auth/auth-client-request.c +++ b/src/lib-auth/auth-client-request.c @@ -284,12 +284,14 @@ time_t auth_client_request_get_create_time(struct auth_client_request *request) static void args_parse_user(struct auth_client_request *request, const char *arg) { - if (str_begins(arg, "user=")) - event_add_str(request->event, "user", arg + 5); - else if (str_begins(arg, "original_user=")) - event_add_str(request->event, "original_user", arg + 14); - else if (str_begins(arg, "auth_user=")) - event_add_str(request->event, "auth_user", arg + 10); + const char *value; + + if (str_begins(arg, "user=", &value)) + event_add_str(request->event, "user", value); + else if (str_begins(arg, "original_user=", &value)) + event_add_str(request->event, "original_user", value); + else if (str_begins(arg, "auth_user=", &value)) + event_add_str(request->event, "auth_user", value); } void auth_client_request_server_input(struct auth_client_request *request, @@ -316,9 +318,7 @@ void auth_client_request_server_input(struct auth_client_request *request, } for (tmp = args; *tmp != NULL; tmp++) { - if (str_begins(*tmp, "resp=")) { - base64_data = *tmp + 5; - } + (void)str_begins(*tmp, "resp=", &base64_data); args_parse_user(request, *tmp); } diff --git a/src/lib-auth/auth-master.c b/src/lib-auth/auth-master.c index 57cf8d21ba..1ff0e1bf79 100644 --- a/src/lib-auth/auth-master.c +++ b/src/lib-auth/auth-master.c @@ -279,6 +279,7 @@ static bool auth_lookup_reply_callback(const char *cmd, const char *const *args, void *context) { struct auth_master_lookup_ctx *ctx = context; + const char *value; unsigned int i, len; io_loop_stop(ctx->conn->ioloop); @@ -295,9 +296,8 @@ static bool auth_lookup_reply_callback(const char *cmd, const char *const *args, /* put the reason string into first field */ ctx->fields = p_new(ctx->pool, const char *, 2); for (i = 0; i < len; i++) { - if (str_begins(args[i], "reason=")) { - ctx->fields[0] = - p_strdup(ctx->pool, args[i] + 7); + if (str_begins(args[i], "reason=", &value)) { + ctx->fields[0] = p_strdup(ctx->pool, value); break; } } @@ -717,22 +717,24 @@ int auth_master_user_lookup(struct auth_master_connection *conn, void auth_user_fields_parse(const char *const *fields, pool_t pool, struct auth_user_reply *reply_r) { + const char *value; + i_zero(reply_r); reply_r->uid = (uid_t)-1; reply_r->gid = (gid_t)-1; p_array_init(&reply_r->extra_fields, pool, 64); for (; *fields != NULL; fields++) { - if (str_begins(*fields, "uid=")) { - if (str_to_uid(*fields + 4, &reply_r->uid) < 0) + if (str_begins(*fields, "uid=", &value)) { + if (str_to_uid(value, &reply_r->uid) < 0) i_error("Invalid uid in reply"); - } else if (str_begins(*fields, "gid=")) { - if (str_to_gid(*fields + 4, &reply_r->gid) < 0) + } else if (str_begins(*fields, "gid=", &value)) { + if (str_to_gid(value, &reply_r->gid) < 0) i_error("Invalid gid in reply"); - } else if (str_begins(*fields, "home=")) - reply_r->home = p_strdup(pool, *fields + 5); - else if (str_begins(*fields, "chroot=")) - reply_r->chroot = p_strdup(pool, *fields + 7); + } else if (str_begins(*fields, "home=", &value)) + reply_r->home = p_strdup(pool, value); + else if (str_begins(*fields, "chroot=", &value)) + reply_r->chroot = p_strdup(pool, value); else if (strcmp(*fields, "anonymous") == 0) reply_r->anonymous = TRUE; else { diff --git a/src/lib-dcrypt/dcrypt-openssl.c b/src/lib-dcrypt/dcrypt-openssl.c index 01b70b9891..ffb0a8bf06 100644 --- a/src/lib-dcrypt/dcrypt-openssl.c +++ b/src/lib-dcrypt/dcrypt-openssl.c @@ -2681,18 +2681,15 @@ dcrypt_openssl_key_string_get_info( i_assert(key_data != NULL); /* is it PEM key */ - if (str_begins(key_data, "-----BEGIN ")) { + if (str_begins(key_data, "-----BEGIN ", &key_data)) { format = DCRYPT_FORMAT_PEM; version = DCRYPT_KEY_VERSION_NA; - key_data += 11; if (str_begins_with(key_data, "RSA ")) { DCRYPT_SET_ERROR("RSA private key format not supported, convert it to PKEY format with openssl pkey"); return FALSE; } - if (str_begins(key_data, "ENCRYPTED ")) { + if (str_begins(key_data, "ENCRYPTED ", &key_data)) encryption_type = DCRYPT_KEY_ENCRYPTION_TYPE_PASSWORD; - key_data += 10; - } if (str_begins_with(key_data, "PRIVATE KEY-----")) kind = DCRYPT_KEY_KIND_PRIVATE; else if (str_begins_with(key_data, "PUBLIC KEY-----")) diff --git a/src/lib-dict-backend/dict-sql-settings.c b/src/lib-dict-backend/dict-sql-settings.c index fec48b380b..66203a0bfa 100644 --- a/src/lib-dict-backend/dict-sql-settings.c +++ b/src/lib-dict-backend/dict-sql-settings.c @@ -204,7 +204,6 @@ parse_setting(const char *key, const char *value, struct setting_parser_ctx *ctx) { struct dict_sql_map_field *field; - size_t value_len; switch (ctx->type) { case SECTION_ROOT: @@ -224,26 +223,19 @@ parse_setting(const char *key, const char *value, } field = array_append_space(&ctx->cur_fields); field->sql_field.name = p_strdup(ctx->pool, key); - value_len = strlen(value); - if (str_begins_with(value, "${hexblob:") && - value[value_len-1] == '}') { - field->variable = p_strndup(ctx->pool, value + 10, - value_len-10-1); + + const char *arg, *last = value + strlen(value) - 1; + if (str_begins(value, "${hexblob:", &arg) && *last == '}') { + field->variable = p_strdup_until(ctx->pool, arg, last); field->sql_field.value_type = DICT_SQL_TYPE_HEXBLOB; - } else if (str_begins_with(value, "${int:") && - value[value_len-1] == '}') { - field->variable = p_strndup(ctx->pool, value + 6, - value_len-6-1); + } else if (str_begins(value, "${int:", &arg) && *last == '}') { + field->variable = p_strdup_until(ctx->pool, arg, last); field->sql_field.value_type = DICT_SQL_TYPE_INT; - } else if (str_begins_with(value, "${uint:") && - value[value_len-1] == '}') { - field->variable = p_strndup(ctx->pool, value + 7, - value_len-7-1); + } else if (str_begins(value, "${uint:", &arg) && *last == '}') { + field->variable = p_strdup_until(ctx->pool, arg, last); field->sql_field.value_type = DICT_SQL_TYPE_UINT; - } else if (str_begins(value, "${double:") && - value[value_len-1] == '}') { - field->variable = p_strndup(ctx->pool, value + 9, - value_len-9-1); + } else if (str_begins(value, "${double:", &arg) && *last == '}') { + field->variable = p_strdup_until(ctx->pool, arg, last); field->sql_field.value_type = DICT_SQL_TYPE_DOUBLE; } else { field->variable = p_strdup(ctx->pool, value + 1); diff --git a/src/lib-dict-extra/dict-fs.c b/src/lib-dict-extra/dict-fs.c index 7bd0b82dd6..0d68d24eb3 100644 --- a/src/lib-dict-extra/dict-fs.c +++ b/src/lib-dict-extra/dict-fs.c @@ -94,14 +94,12 @@ static const char *fs_dict_escape_key(const char *key) static const char *fs_dict_get_full_key(const char *username, const char *key) { key = fs_dict_escape_key(key); - if (str_begins(key, DICT_PATH_SHARED)) - return key + strlen(DICT_PATH_SHARED); - else if (str_begins(key, DICT_PATH_PRIVATE)) { - return t_strdup_printf("%s/%s", username, - key + strlen(DICT_PATH_PRIVATE)); - } else { + if (str_begins(key, DICT_PATH_SHARED, &key)) + return key; + else if (str_begins(key, DICT_PATH_PRIVATE, &key)) + return t_strdup_printf("%s/%s", username, key); + else i_unreached(); - } } static int fs_dict_lookup(struct dict *_dict, const struct dict_op_settings *set, diff --git a/src/lib-dict/dict-client.c b/src/lib-dict/dict-client.c index f18ae6b3ab..57344d27fc 100644 --- a/src/lib-dict/dict-client.c +++ b/src/lib-dict/dict-client.c @@ -707,30 +707,30 @@ client_dict_init(struct dict *driver, const char *uri, { struct ioloop *old_ioloop = current_ioloop; struct client_dict *dict; - const char *p, *dest_uri, *path; + const char *p, *dest_uri, *value, *path; unsigned int idle_msecs = DICT_CLIENT_DEFAULT_TIMEOUT_MSECS; unsigned int warn_slow_msecs = DICT_CLIENT_DEFAULT_WARN_SLOW_MSECS; /* uri = [idle_msecs=:] [warn_slow_msecs=:] [] ":" */ for (;;) { - if (str_begins(uri, "idle_msecs=")) { - p = strchr(uri+11, ':'); + if (str_begins(uri, "idle_msecs=", &value)) { + p = strchr(value, ':'); if (p == NULL) { *error_r = t_strdup_printf("Invalid URI: %s", uri); return -1; } - if (str_to_uint(t_strdup_until(uri+11, p), &idle_msecs) < 0) { + if (str_to_uint(t_strdup_until(value, p), &idle_msecs) < 0) { *error_r = "Invalid idle_msecs"; return -1; } uri = p+1; - } else if (str_begins(uri, "warn_slow_msecs=")) { - p = strchr(uri+11, ':'); + } else if (str_begins(uri, "warn_slow_msecs=", &value)) { + p = strchr(value, ':'); if (p == NULL) { *error_r = t_strdup_printf("Invalid URI: %s", uri); return -1; } - if (str_to_uint(t_strdup_until(uri+16, p), &warn_slow_msecs) < 0) { + if (str_to_uint(t_strdup_until(value, p), &warn_slow_msecs) < 0) { *error_r = "Invalid warn_slow_msecs"; return -1; } diff --git a/src/lib-dict/dict-redis.c b/src/lib-dict/dict-redis.c index 57fe333715..72e1506073 100644 --- a/src/lib-dict/dict-redis.c +++ b/src/lib-dict/dict-redis.c @@ -351,7 +351,7 @@ redis_dict_init(struct dict *driver, const char *uri, struct ip_addr ip; unsigned int secs; in_port_t port = REDIS_DEFAULT_PORT; - const char *const *args, *unix_path = NULL; + const char *const *args, *value, *unix_path = NULL; int ret = 0; if (redis_connections == NULL) { @@ -369,32 +369,30 @@ redis_dict_init(struct dict *driver, const char *uri, args = t_strsplit(uri, ":"); for (; *args != NULL; args++) { - if (str_begins(*args, "path=")) { - unix_path = *args + 5; - } else if (str_begins(*args, "host=")) { - if (net_addr2ip(*args+5, &ip) < 0) { + if (str_begins(*args, "path=", &value)) { + unix_path = value; + } else if (str_begins(*args, "host=", &value)) { + if (net_addr2ip(value, &ip) < 0) { *error_r = t_strdup_printf("Invalid IP: %s", - *args+5); + value); ret = -1; } - } else if (str_begins(*args, "port=")) { - if (net_str2port(*args+5, &port) < 0) { + } else if (str_begins(*args, "port=", &value)) { + if (net_str2port(value, &port) < 0) { *error_r = t_strdup_printf("Invalid port: %s", - *args+5); + value); ret = -1; } - } else if (str_begins(*args, "prefix=")) { + } else if (str_begins(*args, "prefix=", &value)) { i_free(dict->key_prefix); - dict->key_prefix = i_strdup(*args + 7); - } else if (str_begins(*args, "db=")) { - if (str_to_uint(*args+3, &dict->db_id) < 0) { + dict->key_prefix = i_strdup(value); + } else if (str_begins(*args, "db=", &value)) { + if (str_to_uint(value, &dict->db_id) < 0) { *error_r = t_strdup_printf( - "Invalid db number: %s", *args+3); + "Invalid db number: %s", value); ret = -1; } - } else if (str_begins(*args, "expire_secs=")) { - const char *value = *args + 12; - + } else if (str_begins(*args, "expire_secs=", &value)) { if (str_to_uint(value, &secs) < 0 || secs == 0) { *error_r = t_strdup_printf( "Invalid expire_secs: %s", value); @@ -402,15 +400,15 @@ redis_dict_init(struct dict *driver, const char *uri, } i_free(dict->expire_value); dict->expire_value = i_strdup(value); - } else if (str_begins(*args, "timeout_msecs=")) { - if (str_to_uint(*args+14, &dict->timeout_msecs) < 0) { + } else if (str_begins(*args, "timeout_msecs=", &value)) { + if (str_to_uint(value, &dict->timeout_msecs) < 0) { *error_r = t_strdup_printf( - "Invalid timeout_msecs: %s", *args+14); + "Invalid timeout_msecs: %s", value); ret = -1; } - } else if (str_begins(*args, "password=")) { + } else if (str_begins(*args, "password=", &value)) { i_free(dict->password); - dict->password = i_strdup(*args + 9); + dict->password = i_strdup(value); } else { *error_r = t_strdup_printf("Unknown parameter: %s", *args); @@ -488,14 +486,13 @@ redis_dict_get_full_key(struct redis_dict *dict, const char *username, { const char *username_sp = strchr(username, DICT_USERNAME_SEPARATOR); - if (str_begins(key, DICT_PATH_SHARED)) - key += strlen(DICT_PATH_SHARED); - else if (str_begins(key, DICT_PATH_PRIVATE)) { + if (str_begins(key, DICT_PATH_SHARED, &key)) + ; + else if (str_begins(key, DICT_PATH_PRIVATE, &key)) { key = t_strdup_printf("%s%c%s", username_sp == NULL ? username : redis_escape_username(username), - DICT_USERNAME_SEPARATOR, - key + strlen(DICT_PATH_PRIVATE)); + DICT_USERNAME_SEPARATOR, key); } else { i_unreached(); } diff --git a/src/lib-dns/test-dns-lookup.c b/src/lib-dns/test-dns-lookup.c index db70923367..3ca66fa34b 100644 --- a/src/lib-dns/test-dns-lookup.c +++ b/src/lib-dns/test-dns-lookup.c @@ -46,16 +46,18 @@ static void server_handle_timeout(struct connection *client) static int test_dns_client_input_args(struct connection *client, const char *const *args) { + const char *value; + if (strcmp(args[0], "QUIT") == 0) return 0; if (strcmp(args[0], "IP") != 0 && strcmp(args[0], "NAME") != 0) return -1; test_server.lookup_counter++; /* never finish this query */ - if (str_begins(args[1], "waitfor")) { + if (str_begins(args[1], "waitfor", &value)) { unsigned int msecs; i_assert(test_server.to == NULL); - if (str_to_uint(args[1]+7, &msecs) < 0) + if (str_to_uint(value, &msecs) < 0) i_unreached(); connection_input_halt(client); test_server.to = diff --git a/src/lib-fs/fs-posix.c b/src/lib-fs/fs-posix.c index 5b882d522f..b9f5a155e9 100644 --- a/src/lib-fs/fs-posix.c +++ b/src/lib-fs/fs-posix.c @@ -80,7 +80,7 @@ fs_posix_init(struct fs *_fs, const char *args, const struct fs_settings *set, const char **error_r) { struct posix_fs *fs = container_of(_fs, struct posix_fs, fs); - const char *const *tmp; + const char *value, *const *tmp; fs->temp_file_prefix = set->temp_file_prefix != NULL ? i_strdup(set->temp_file_prefix) : i_strdup("temp.dovecot."); @@ -100,9 +100,9 @@ fs_posix_init(struct fs *_fs, const char *args, const struct fs_settings *set, fs->lock_method = FS_POSIX_LOCK_METHOD_FLOCK; else if (strcmp(arg, "lock=dotlock") == 0) fs->lock_method = FS_POSIX_LOCK_METHOD_DOTLOCK; - else if (str_begins(arg, "prefix=")) { + else if (str_begins(arg, "prefix=", &value)) { i_free(fs->path_prefix); - fs->path_prefix = i_strdup(arg + 7); + fs->path_prefix = i_strdup(value); } else if (strcmp(arg, "mode=auto") == 0) { fs->mode_auto = TRUE; } else if (strcmp(arg, "dirs") == 0) { @@ -111,15 +111,15 @@ fs_posix_init(struct fs *_fs, const char *args, const struct fs_settings *set, fs->disable_fsync = TRUE; } else if (strcmp(arg, "accurate-mtime") == 0) { fs->accurate_mtime = TRUE; - } else if (str_begins(arg, "mode=")) { + } else if (str_begins(arg, "mode=", &value)) { unsigned int mode; - if (str_to_uint_oct(arg+5, &mode) < 0) { - *error_r = t_strdup_printf("Invalid mode value: %s", arg+5); + if (str_to_uint_oct(value, &mode) < 0) { + *error_r = t_strdup_printf("Invalid mode value: %s", value); return -1; } fs->mode = mode & 0666; if (fs->mode == 0) { - *error_r = t_strdup_printf("Invalid mode: %s", arg+5); + *error_r = t_strdup_printf("Invalid mode: %s", value); return -1; } } else { diff --git a/src/lib-http/http-server-resource.c b/src/lib-http/http-server-resource.c index dc602e4048..943914deff 100644 --- a/src/lib-http/http-server-resource.c +++ b/src/lib-http/http-server-resource.c @@ -50,7 +50,7 @@ http_server_location_find(struct http_server *server, const char *path, const char **sub_path_r) { struct http_server_location qloc, *loc; - size_t loc_len; + const char *loc_suffix; unsigned int insert_idx; *sub_path_r = NULL; @@ -73,16 +73,15 @@ http_server_location_find(struct http_server *server, const char *path, } loc = array_idx_elem(&server->locations, insert_idx-1); - loc_len = strlen(loc->path); - if (!str_begins(path, loc->path)) { + if (!str_begins(path, loc->path, &loc_suffix)) { /* Location isn't a prefix of path */ return -1; - } else if (path[loc_len] != '/') { + } else if (loc_suffix[0] != '/') { /* Match doesn't end at '/' */ return -1; } - *sub_path_r = &path[loc_len + 1]; + *sub_path_r = loc_suffix + 1; *loc_r = loc; return 0; } diff --git a/src/lib-imap-storage/imap-metadata.c b/src/lib-imap-storage/imap-metadata.c index ebbcd69504..1a1552f7d4 100644 --- a/src/lib-imap-storage/imap-metadata.c +++ b/src/lib-imap-storage/imap-metadata.c @@ -86,14 +86,12 @@ imap_metadata_entry2key(struct imap_metadata_transaction *imtrans, /* names are case-insensitive so we'll always lowercase them */ entry = t_str_lcase(entry); - if (str_begins(entry, IMAP_METADATA_PRIVATE_PREFIX)) { - *key_r = entry + strlen(IMAP_METADATA_PRIVATE_PREFIX); + if (str_begins(entry, IMAP_METADATA_PRIVATE_PREFIX, key_r)) *type_r = MAIL_ATTRIBUTE_TYPE_PRIVATE; - } else { - i_assert(str_begins(entry, IMAP_METADATA_SHARED_PREFIX)); - *key_r = entry + strlen(IMAP_METADATA_SHARED_PREFIX); + else if (str_begins(entry, IMAP_METADATA_SHARED_PREFIX, key_r)) *type_r = MAIL_ATTRIBUTE_TYPE_SHARED; - } + else + i_unreached(); if ((*key_r)[0] == '\0') { /* /private or /shared prefix has no value itself */ } else { diff --git a/src/lib-imap-storage/imap-msgpart.c b/src/lib-imap-storage/imap-msgpart.c index 3bce11754b..46bc089e43 100644 --- a/src/lib-imap-storage/imap-msgpart.c +++ b/src/lib-imap-storage/imap-msgpart.c @@ -201,6 +201,7 @@ int imap_msgpart_parse(const char *section, struct imap_msgpart **msgpart_r) struct imap_msgpart *msgpart; pool_t pool; unsigned int i; + const char *suffix; bool next_digit; int ret; @@ -264,19 +265,17 @@ int imap_msgpart_parse(const char *section, struct imap_msgpart **msgpart_r) /* body (for root or for message/rfc822) */ msgpart->fetch_type = FETCH_BODY; msgpart->wanted_fields |= MAIL_FETCH_STREAM_BODY; - } else if (str_begins(section, "HEADER")) { + } else if (str_begins(section, "HEADER", &suffix)) { /* header (for root or for message/rfc822) */ - if (section[6] == '\0') { + if (suffix[0] == '\0') { msgpart->fetch_type = FETCH_HEADER; ret = 0; - } else if (str_begins(section, "HEADER.FIELDS.NOT")) { + } else if (str_begins(section, "HEADER.FIELDS.NOT", &suffix)) { msgpart->fetch_type = FETCH_HEADER_FIELDS_NOT; - ret = imap_msgpart_parse_header_fields(msgpart, - section+17); - } else if (str_begins(section, "HEADER.FIELDS")) { + ret = imap_msgpart_parse_header_fields(msgpart, suffix); + } else if (str_begins(section, "HEADER.FIELDS", &suffix)) { msgpart->fetch_type = FETCH_HEADER_FIELDS; - ret = imap_msgpart_parse_header_fields(msgpart, - section+13); + ret = imap_msgpart_parse_header_fields(msgpart, suffix); } else { ret = -1; } diff --git a/src/lib-imap/imap-base-subject.c b/src/lib-imap/imap-base-subject.c index 5736fa8786..cb5fa50ad5 100644 --- a/src/lib-imap/imap-base-subject.c +++ b/src/lib-imap/imap-base-subject.c @@ -129,13 +129,9 @@ static bool remove_subj_leader(buffer_t *buf, size_t *start_pos, return ret; } - if (str_begins(data, "RE")) - data += 2; - else if (str_begins(data, "FWD")) - data += 3; - else if (str_begins(data, "FW")) - data += 2; - else + if (!str_begins(data, "RE", &data) && + !str_begins(data, "FWD", &data) && + !str_begins(data, "FW", &data)) return ret; if (*data == ' ') diff --git a/src/lib-master/master-login-auth.c b/src/lib-master/master-login-auth.c index 34c777a5ca..a200c1de4a 100644 --- a/src/lib-master/master-login-auth.c +++ b/src/lib-master/master-login-auth.c @@ -435,10 +435,8 @@ master_login_auth_input_fail(struct master_login_auth *auth, unsigned int id, /* FAIL [..] [reason=] [..] */ for (i = 0; args[i] != NULL; i++) { - if (str_begins(args[i], "reason=")) { - error = args[i] + 7; + if (str_begins(args[i], "reason=", &error)) break; - } } request = master_login_auth_lookup_request(auth, id); diff --git a/src/lib-master/master-login.c b/src/lib-master/master-login.c index e25ce35a79..888fe5cfb4 100644 --- a/src/lib-master/master-login.c +++ b/src/lib-master/master-login.c @@ -399,9 +399,11 @@ static int master_login_postlogin(struct master_login_client *client, static const char * auth_args_find_postlogin_socket(const char *const *auth_args) { + const char *value; + for (unsigned int i = 0; auth_args[i] != NULL; i++) { - if (str_begins(auth_args[i], "postlogin=")) - return auth_args[i]+10; + if (str_begins(auth_args[i], "postlogin=", &value)) + return value; } return NULL; } diff --git a/src/lib-master/master-service-settings-cache.c b/src/lib-master/master-service-settings-cache.c index 11dd66bb5a..fc409fcff3 100644 --- a/src/lib-master/master-service-settings-cache.c +++ b/src/lib-master/master-service-settings-cache.c @@ -86,7 +86,7 @@ master_service_settings_cache_init(struct master_service *service, int master_service_settings_cache_init_filter(struct master_service_settings_cache *cache) { const char *const *filters; - const char *error; + const char *value, *error; if (cache->filters != NULL) return 0; @@ -101,14 +101,14 @@ int master_service_settings_cache_init_filter(struct master_service_settings_cac struct config_filter *filter = p_new(cache->pool, struct config_filter, 1); while(*keys != NULL) { - if (str_begins(*keys, "local-net=")) { - (void)net_parse_range((*keys)+10, + if (str_begins(*keys, "local-net=", &value)) { + (void)net_parse_range(value, &filter->local_ip, &filter->local_bits); - } else if (str_begins(*keys, "remote-net=")) { - (void)net_parse_range((*keys)+11, + } else if (str_begins(*keys, "remote-net=", &value)) { + (void)net_parse_range(value, &filter->remote_ip, &filter->remote_bits); - } else if (str_begins(*keys, "local-name=")) { - filter->local_name = p_strdup(cache->pool, (*keys)+11); + } else if (str_begins(*keys, "local-name=", &value)) { + filter->local_name = p_strdup(cache->pool, value); } keys++; } diff --git a/src/lib-master/master-service-settings.c b/src/lib-master/master-service-settings.c index f0f0797f43..d2ecb59704 100644 --- a/src/lib-master/master-service-settings.c +++ b/src/lib-master/master-service-settings.c @@ -465,7 +465,7 @@ config_read_reply_header(struct istream *istream, const char *path, pool_t pool, } T_BEGIN { - const char *const *arg = t_strsplit_tabescaped(line); + const char *value, *const *arg = t_strsplit_tabescaped(line); ARRAY_TYPE(const_string) services; p_array_init(&services, pool, 8); @@ -478,8 +478,8 @@ config_read_reply_header(struct istream *istream, const char *path, pool_t pool, output_r->used_local = TRUE; else if (strcmp(*arg, "used-remote") == 0) output_r->used_remote = TRUE; - else if (str_begins(*arg, "service=")) { - const char *name = p_strdup(pool, *arg + 8); + else if (str_begins(*arg, "service=", &value)) { + const char *name = p_strdup(pool, value); array_push_back(&services, &name); } } @@ -549,8 +549,8 @@ int master_service_settings_get_filters(struct master_service *service, while((line = i_stream_read_next_line(is)) != NULL) { if (*line == '\0') break; - if (str_begins(line, "FILTER\t")) { - line = t_strdup(line+7); + if (str_begins(line, "FILTER\t", &line)) { + line = t_strdup(line); array_push_back(&filters_tmp, &line); } } diff --git a/src/lib-master/master-service.c b/src/lib-master/master-service.c index c8cd3ac801..6e9ab341d0 100644 --- a/src/lib-master/master-service.c +++ b/src/lib-master/master-service.c @@ -1863,9 +1863,8 @@ bool version_string_verify_full(const char *line, const char *service_name, size_t service_name_len = strlen(service_name); bool ret; - if (!str_begins(line, "VERSION\t")) + if (!str_begins(line, "VERSION\t", &line)) return FALSE; - line += 8; if (strncmp(line, service_name, service_name_len) != 0 || line[service_name_len] != '\t') diff --git a/src/lib-program-client/program-client.c b/src/lib-program-client/program-client.c index ad7dfa72ff..f85dda3cfd 100644 --- a/src/lib-program-client/program-client.c +++ b/src/lib-program-client/program-client.c @@ -669,21 +669,23 @@ int program_client_create(const char *uri, const char *const *args, bool noreply, struct program_client **pc_r, const char **error_r) { - if (str_begins(uri, "exec:")) { - *pc_r = program_client_local_create(uri+5, args, set); + const char *suffix; + + if (str_begins(uri, "exec:", &suffix)) { + *pc_r = program_client_local_create(suffix, args, set); return 0; - } else if (str_begins(uri, "unix:")) { - *pc_r = program_client_unix_create(uri+5, args, set, noreply); + } else if (str_begins(uri, "unix:", &suffix)) { + *pc_r = program_client_unix_create(suffix, args, set, noreply); return 0; - } else if (str_begins(uri, "tcp:")) { + } else if (str_begins(uri, "tcp:", &suffix)) { const char *host; in_port_t port; - if (net_str2hostport(uri+4, 0, &host, &port) < 0 || + if (net_str2hostport(suffix, 0, &host, &port) < 0 || port == 0) { *error_r = t_strdup_printf( "Invalid tcp syntax, " - "must be host:port in '%s'", uri+4); + "must be host:port in '%s'", suffix); return -1; } *pc_r = program_client_net_create(host, port, args, set, diff --git a/src/lib-settings/settings-parser.c b/src/lib-settings/settings-parser.c index 1fb398853b..eb15b96968 100644 --- a/src/lib-settings/settings-parser.c +++ b/src/lib-settings/settings-parser.c @@ -990,8 +990,8 @@ int settings_parse_stream(struct setting_parser_context *ctx, return 0; } ctx->linenum++; - if (ctx->linenum == 1 && str_begins(line, "ERROR ")) { - ctx->error = p_strdup(ctx->parser_pool, line + 6); + if (ctx->linenum == 1 && str_begins(line, "ERROR ", &line)) { + ctx->error = p_strdup(ctx->parser_pool, line); return -1; } diff --git a/src/lib-sql/driver-pgsql.c b/src/lib-sql/driver-pgsql.c index b87d41576c..2775b7eca1 100644 --- a/src/lib-sql/driver-pgsql.c +++ b/src/lib-sql/driver-pgsql.c @@ -324,6 +324,7 @@ static int driver_pgsql_init_full_v(const struct sql_settings *set, struct sql_db **db_r, const char **error_r ATTR_UNUSED) { struct pgsql_db *db; + const char *value; db = i_new(struct pgsql_db, 1); db->connect_string = i_strdup(set->connect_string); @@ -337,8 +338,8 @@ static int driver_pgsql_init_full_v(const struct sql_settings *set, const char *const *arg = t_strsplit(db->connect_string, " "); for (; *arg != NULL; arg++) { - if (str_begins(*arg, "host=")) - db->host = i_strdup(*arg + 5); + if (str_begins(*arg, "host=", &value)) + db->host = i_strdup(value); } } T_END; diff --git a/src/lib-sql/driver-sqlite.c b/src/lib-sql/driver-sqlite.c index a80265a7ce..77bc59c439 100644 --- a/src/lib-sql/driver-sqlite.c +++ b/src/lib-sql/driver-sqlite.c @@ -92,7 +92,7 @@ static int driver_sqlite_parse_connect_string(struct sqlite_db *db, const char **error_r) { const char *const *params = t_strsplit_spaces(connect_string, " "); - const char *file = NULL; + const char *arg, *file = NULL; bool val; if (str_array_length(params) < 1) { @@ -101,19 +101,18 @@ static int driver_sqlite_parse_connect_string(struct sqlite_db *db, } for (; *params != NULL; params++) { - if (str_begins(*params, "journal_mode=")) { - const char *mode = (*params)+13; - if (strcmp(mode, "delete") == 0) + if (str_begins(*params, "journal_mode=", &arg)) { + if (strcmp(arg, "delete") == 0) db->use_wal = FALSE; - else if (strcmp(mode, "wal") == 0) + else if (strcmp(arg, "wal") == 0) db->use_wal = TRUE; else { *error_r = t_strdup_printf("journal_mode: Unsupported mode '%s', " - "use either 'delete' or 'wal'", mode); + "use either 'delete' or 'wal'", arg); return -1; } - } else if (str_begins(*params, "readonly=")) { - if (settings_get_bool((*params)+9, &val, error_r) < 0) { + } else if (str_begins(*params, "readonly=", &arg)) { + if (settings_get_bool(arg, &val, error_r) < 0) { *error_r = t_strdup_printf("readonly: %s", *error_r); return -1; } diff --git a/src/lib-storage/index/dbox-multi/mdbox-purge.c b/src/lib-storage/index/dbox-multi/mdbox-purge.c index 8461074fb1..60508e315a 100644 --- a/src/lib-storage/index/dbox-multi/mdbox-purge.c +++ b/src/lib-storage/index/dbox-multi/mdbox-purge.c @@ -498,6 +498,7 @@ static int mdbox_purge_get_primary_files(struct mdbox_purge_context *ctx) DIR *dir; struct dirent *d; string_t *path; + const char *suffix; unsigned int file_id; size_t dir_len; int ret = 0; @@ -526,10 +527,9 @@ static int mdbox_purge_get_primary_files(struct mdbox_purge_context *ctx) dir_len = str_len(path); for (errno = 0; (d = readdir(dir)) != NULL; errno = 0) { - if (!str_begins(d->d_name, MDBOX_MAIL_FILE_PREFIX)) + if (!str_begins(d->d_name, MDBOX_MAIL_FILE_PREFIX, &suffix)) continue; - if (str_to_uint32(d->d_name + strlen(MDBOX_MAIL_FILE_PREFIX), - &file_id) < 0) + if (str_to_uint32(suffix, &file_id) < 0) continue; str_truncate(path, dir_len); diff --git a/src/lib-storage/index/dbox-single/sdbox-sync-rebuild.c b/src/lib-storage/index/dbox-single/sdbox-sync-rebuild.c index aa4832f15f..c4feeca17a 100644 --- a/src/lib-storage/index/dbox-single/sdbox-sync-rebuild.c +++ b/src/lib-storage/index/dbox-single/sdbox-sync-rebuild.c @@ -73,9 +73,8 @@ sdbox_sync_add_file(struct index_rebuild_context *ctx, uint32_t uid; int ret; - if (!str_begins(fname, SDBOX_MAIL_FILE_PREFIX)) + if (!str_begins(fname, SDBOX_MAIL_FILE_PREFIX, &fname)) return 0; - fname += strlen(SDBOX_MAIL_FILE_PREFIX); if (str_to_uint32(fname, &uid) < 0 || uid == 0) { i_warning("sdbox %s: Ignoring invalid filename %s", diff --git a/src/lib-storage/index/imapc/imapc-list.c b/src/lib-storage/index/imapc/imapc-list.c index a9e03ecf02..5ecf6faf91 100644 --- a/src/lib-storage/index/imapc/imapc-list.c +++ b/src/lib-storage/index/imapc/imapc-list.c @@ -396,14 +396,12 @@ imapc_list_get_vname(struct mailbox_list *_list, const char *storage_name) { struct imapc_mailbox_list *list = (struct imapc_mailbox_list *)_list; const char *prefix = list->set->imapc_list_prefix; - size_t prefix_len; if (*storage_name == '\0') { /* ACL plugin does these lookups */ } else if (*prefix != '\0' && strcasecmp(storage_name, "INBOX") != 0) { - prefix_len = strlen(prefix); - i_assert(str_begins(storage_name, prefix)); - storage_name += prefix_len; + if (!str_begins(storage_name, prefix, &storage_name)) + i_unreached(); if (storage_name[0] == '\0') { /* we're looking up the prefix itself */ } else { diff --git a/src/lib-storage/index/imapc/imapc-mail-fetch.c b/src/lib-storage/index/imapc/imapc-mail-fetch.c index 1b0eee7100..0e00a1d8ca 100644 --- a/src/lib-storage/index/imapc/imapc-mail-fetch.c +++ b/src/lib-storage/index/imapc/imapc-mail-fetch.c @@ -144,14 +144,16 @@ imapc_mail_try_merge_fetch(struct imapc_mailbox *mbox, string_t *str) { const char *s1 = str_c(str); const char *s2 = str_c(mbox->pending_fetch_cmd); - const char *p1, *p2; + const char *s1_args, *s2_args, *p1, *p2; - i_assert(str_begins(s1, "UID FETCH ")); - i_assert(str_begins(s2, "UID FETCH ")); + if (!str_begins(s1, "UID FETCH ", &s1_args)) + i_unreached(); + if (!str_begins(s2, "UID FETCH ", &s2_args)) + i_unreached(); /* skip over UID range */ - p1 = strchr(s1+10, ' '); - p2 = strchr(s2+10, ' '); + p1 = strchr(s1_args, ' '); + p2 = strchr(s2_args, ' '); if (null_strcmp(p1, p2) != 0) return FALSE; diff --git a/src/lib-storage/index/index-storage.c b/src/lib-storage/index/index-storage.c index 01f7fef57b..adfd90445f 100644 --- a/src/lib-storage/index/index-storage.c +++ b/src/lib-storage/index/index-storage.c @@ -1103,8 +1103,8 @@ int index_storage_set_subscribed(struct mailbox *box, bool set) subscription name */ subs_name = t_strconcat(list->ns->prefix, box->name, NULL); /* drop the common prefix (typically there isn't one) */ - i_assert(str_begins(subs_name, ns->prefix)); - subs_name += strlen(ns->prefix); + if (!str_begins(subs_name, ns->prefix, &subs_name)) + i_unreached(); list = ns->list; } diff --git a/src/lib-storage/index/pop3c/pop3c-storage.c b/src/lib-storage/index/pop3c/pop3c-storage.c index f7846836e8..de8934aa03 100644 --- a/src/lib-storage/index/pop3c/pop3c-storage.c +++ b/src/lib-storage/index/pop3c/pop3c-storage.c @@ -141,15 +141,16 @@ static void pop3c_login_callback(enum pop3c_command_state state, const char *reply, void *context) { struct pop3c_mailbox *mbox = context; + const char *suffix; switch (state) { case POP3C_COMMAND_STATE_OK: mbox->logged_in = TRUE; break; case POP3C_COMMAND_STATE_ERR: - if (str_begins(reply, "[IN-USE] ")) { + if (str_begins(reply, "[IN-USE] ", &suffix)) { mail_storage_set_error(mbox->box.storage, - MAIL_ERROR_INUSE, reply + 9); + MAIL_ERROR_INUSE, suffix); } else { /* authentication failure probably */ mail_storage_set_error(mbox->box.storage, diff --git a/src/lib-storage/index/shared/shared-list.c b/src/lib-storage/index/shared/shared-list.c index c69c4dbb5f..839ff39633 100644 --- a/src/lib-storage/index/shared/shared-list.c +++ b/src/lib-storage/index/shared/shared-list.c @@ -90,11 +90,8 @@ shared_list_join_refpattern(struct mailbox_list *list, { struct mail_namespace *ns = list->ns; const char *ns_ref, *prefix = list->ns->prefix; - size_t prefix_len = strlen(prefix); - if (*ref != '\0' && str_begins(ref, prefix)) - ns_ref = ref + prefix_len; - else + if (*ref == '\0' || !str_begins(ref, prefix, &ns_ref)) ns_ref = NULL; if (ns_ref != NULL && *ns_ref != '\0' && diff --git a/src/lib-storage/list/mailbox-list-fs-iter.c b/src/lib-storage/list/mailbox-list-fs-iter.c index b95aabc110..436934f594 100644 --- a/src/lib-storage/list/mailbox-list-fs-iter.c +++ b/src/lib-storage/list/mailbox-list-fs-iter.c @@ -403,9 +403,8 @@ static void fs_list_get_roots(struct fs_list_iterate_context *ctx) bool full_fs_access = ctx->ctx.list->mail_set->mail_full_filesystem_access; const char *const *patterns, *pattern, *parent, *child; - const char *p, *last, *root, *prefix_vname; + const char *p, *last, *root, *prefix_vname, *suffix; unsigned int i; - size_t parentlen; i_assert(*ctx->valid_patterns != NULL); @@ -482,11 +481,9 @@ static void fs_list_get_roots(struct fs_list_iterate_context *ctx) for (i = 1; i < array_count(&ctx->roots); ) { parent = array_idx_elem(&ctx->roots, i-1); child = array_idx_elem(&ctx->roots, i); - parentlen = strlen(parent); - if (str_begins(child, parent) && - (parentlen == 0 || - child[parentlen] == ctx->sep || - child[parentlen] == '\0')) + if (str_begins(child, parent, &suffix) && + (parent[0] == '\0' || + suffix[0] == ctx->sep || suffix[0] == '\0')) array_delete(&ctx->roots, i, 1); else i++; diff --git a/src/lib-storage/list/mailbox-list-index-backend.c b/src/lib-storage/list/mailbox-list-index-backend.c index 8abfe44d30..b33f840de7 100644 --- a/src/lib-storage/list/mailbox-list-index-backend.c +++ b/src/lib-storage/list/mailbox-list-index-backend.c @@ -808,11 +808,11 @@ index_list_rename_mailbox(struct mailbox_list *_oldlist, const char *oldname, struct mailbox_list *_newlist, const char *newname) { struct index_mailbox_list *list = (struct index_mailbox_list *)_oldlist; - const size_t oldname_len = strlen(oldname); struct mailbox_list_index_sync_context *sync_ctx; struct mailbox_list_index_record oldrec, newrec; struct mailbox_list_index_node *oldnode, *newnode, *child; const void *data; + const char *suffix; bool created, expunged; uint32_t oldseq, newseq; int ret; @@ -823,8 +823,8 @@ index_list_rename_mailbox(struct mailbox_list *_oldlist, const char *oldname, return -1; } - if (str_begins(newname, oldname) && - newname[oldname_len] == mailbox_list_get_hierarchy_sep(_newlist)) { + if (str_begins(newname, oldname, &suffix) && + suffix[0] == mailbox_list_get_hierarchy_sep(_newlist)) { mailbox_list_set_error(_oldlist, MAIL_ERROR_NOTPOSSIBLE, "Can't rename mailbox under itself."); return -1; diff --git a/src/lib-storage/list/mailbox-list-iter.c b/src/lib-storage/list/mailbox-list-iter.c index 4098d8fb84..ab4736428d 100644 --- a/src/lib-storage/list/mailbox-list-iter.c +++ b/src/lib-storage/list/mailbox-list-iter.c @@ -909,13 +909,12 @@ mailbox_list_iter_autocreate_filter(struct mailbox_list_iterate_context *ctx, /* there are autocreate parent boxes. set their children flag states. */ struct autocreate_box *autobox; - size_t name_len; + const char *suffix; char sep = mail_namespace_get_sep(ctx->list->ns); array_foreach_modifiable(&actx->boxes, autobox) { - name_len = strlen(autobox->name); - if (!str_begins(info->vname, autobox->name) || - info->vname[name_len] != sep) + if (!str_begins(info->vname, autobox->name, &suffix) || + suffix[0] != sep) continue; if ((info->flags & MAILBOX_NONEXISTENT) == 0) diff --git a/src/lib-storage/mail-search-register-imap.c b/src/lib-storage/mail-search-register-imap.c index c888b9e195..07cecb711f 100644 --- a/src/lib-storage/mail-search-register-imap.c +++ b/src/lib-storage/mail-search-register-imap.c @@ -366,9 +366,8 @@ arg_modseq_set_ext(struct mail_search_build_context *ctx, const char *value; name = t_str_lcase(name); - if (!str_begins(name, "/flags/")) + if (!str_begins(name, "/flags/", &name)) return 0; - name += 7; /* set name */ if (*name == '\\') { diff --git a/src/lib-storage/mail-storage-hooks.c b/src/lib-storage/mail-storage-hooks.c index d368bd7c80..aa1d8496a7 100644 --- a/src/lib-storage/mail-storage-hooks.c +++ b/src/lib-storage/mail-storage-hooks.c @@ -117,10 +117,8 @@ mail_storage_module_hooks_cmp(const struct mail_storage_module_hooks *h1, p = strrchr(s2, '/'); if (p != NULL) s2 = p+1; - if (str_begins(s1, "lib")) - s1 += 3; - if (str_begins(s2, "lib")) - s2 += 3; + (void)str_begins(s1, "lib", &s1); + (void)str_begins(s2, "lib", &s2); return strcmp(s1, s2); } diff --git a/src/lib-storage/mail-storage-service.c b/src/lib-storage/mail-storage-service.c index 671987b766..91fccb1988 100644 --- a/src/lib-storage/mail-storage-service.c +++ b/src/lib-storage/mail-storage-service.c @@ -229,7 +229,7 @@ user_reply_handle(struct mail_storage_service_ctx *ctx, { const char *home = reply->home; const char *chroot = reply->chroot; - const char *const *str, *line, *p; + const char *const *str, *line, *p, *value; unsigned int i, count; int ret = 0; @@ -273,33 +273,33 @@ user_reply_handle(struct mail_storage_service_ctx *ctx, str = array_get(&reply->extra_fields, &count); for (i = 0; i < count; i++) { line = str[i]; - if (str_begins(line, "system_groups_user=")) { + if (str_begins(line, "system_groups_user=", &value)) { user->system_groups_user = - p_strdup(user->pool, line + 19); - } else if (str_begins(line, "chdir=")) { - user->chdir_path = p_strdup(user->pool, line+6); - } else if (str_begins(line, "nice=")) { + p_strdup(user->pool, value); + } else if (str_begins(line, "chdir=", &value)) { + user->chdir_path = p_strdup(user->pool, value); + } else if (str_begins(line, "nice=", &value)) { #ifdef HAVE_SETPRIORITY int n; - if (str_to_int(line + 5, &n) < 0) { + if (str_to_int(value, &n) < 0) { e_error(user->event, "userdb returned invalid nice value %s", - line + 5); + value); } else if (n != 0) { if (setpriority(PRIO_PROCESS, 0, n) < 0) e_error(user->event, "setpriority(%d) failed: %m", n); } #endif - } else if (str_begins(line, "auth_mech=")) { - user->auth_mech = p_strdup(user->pool, line+10); - } else if (str_begins(line, "auth_token=")) { - user->auth_token = p_strdup(user->pool, line+11); - } else if (str_begins(line, "auth_user=")) { - user->auth_user = p_strdup(user->pool, line+10); - } else if (str_begins(line, "admin=")) { - user->admin = line[6] == 'y' || line[6] == 'Y' || - line[6] == '1'; + } else if (str_begins(line, "auth_mech=", &value)) { + user->auth_mech = p_strdup(user->pool, value); + } else if (str_begins(line, "auth_token=", &value)) { + user->auth_token = p_strdup(user->pool, value); + } else if (str_begins(line, "auth_user=", &value)) { + user->auth_user = p_strdup(user->pool, value); + } else if (str_begins(line, "admin=", &value)) { + user->admin = value[0] == 'y' || value[0] == 'Y' || + value[0] == '1'; } else T_BEGIN { ret = set_line(ctx, user, line); } T_END; diff --git a/src/lib-storage/mail-storage-settings.c b/src/lib-storage/mail-storage-settings.c index cd4f5ad2fc..4b802ebc2b 100644 --- a/src/lib-storage/mail-storage-settings.c +++ b/src/lib-storage/mail-storage-settings.c @@ -433,7 +433,7 @@ static bool mail_storage_settings_check(void *_set, pool_t pool, { struct mail_storage_settings *set = _set; struct hash_format *format; - const char *p, *error; + const char *p, *value, *error; bool uidl_format_ok; char c; @@ -550,8 +550,8 @@ static bool mail_storage_settings_check(void *_set, pool_t pool, set->parsed_mail_attachment_detection_no_flags_on_fetch = TRUE; } else if (strcmp(opt, "exclude-inlined") == 0) { set->parsed_mail_attachment_exclude_inlined = TRUE; - } else if (str_begins(opt, "content-type=")) { - const char *value = p_strdup(pool, opt+13); + } else if (str_begins(opt, "content-type=", &value)) { + value = p_strdup(pool, value); array_push_back(&content_types, &value); } else { *error_r = t_strdup_printf("mail_attachment_detection_options: " diff --git a/src/lib-storage/mail-user-lua.c b/src/lib-storage/mail-user-lua.c index 529bd75443..4f2aa7fb92 100644 --- a/src/lib-storage/mail-user-lua.c +++ b/src/lib-storage/mail-user-lua.c @@ -182,14 +182,14 @@ static int lua_storage_mail_user_unref(lua_State *L) static const char *lua_storage_mail_user_metadata_key(const char *key) { - if (str_begins(key, "/private/")) { + if (str_begins(key, "/private/", &key)) { return t_strdup_printf("/private/%s%s", MAILBOX_ATTRIBUTE_PREFIX_DOVECOT_PVT_SERVER, - key + 9); - } else if (str_begins(key, "/shared/")) { + key); + } else if (str_begins(key, "/shared/", &key)) { return t_strdup_printf("/shared/%s%s", MAILBOX_ATTRIBUTE_PREFIX_DOVECOT_PVT_SERVER, - key + 8); + key); } return NULL; } diff --git a/src/lib-storage/mailbox-attribute-lua.c b/src/lib-storage/mailbox-attribute-lua.c index 8d615a0428..c7dfed6760 100644 --- a/src/lib-storage/mailbox-attribute-lua.c +++ b/src/lib-storage/mailbox-attribute-lua.c @@ -22,13 +22,11 @@ int lua_storage_mailbox_attribute_get(struct mailbox *box, const char *key, enum mail_attribute_type attr_type; int ret; - if (str_begins(key, "/private/")) { + if (str_begins(key, "/private/", &key)) attr_type = MAIL_ATTRIBUTE_TYPE_PRIVATE; - key += 9; - } else if (str_begins(key, "/shared/")) { + else if (str_begins(key, "/shared/", &key)) attr_type = MAIL_ATTRIBUTE_TYPE_SHARED; - key += 8; - } else { + else { *error_r = "Invalid key prefix, must be /private/ or /shared/"; return -1; } @@ -84,13 +82,11 @@ int lua_storage_mailbox_attribute_set(struct mailbox *box, const char *key, i_assert(value != NULL || value_len == 0); - if (str_begins(key, "/private/")) { + if (str_begins(key, "/private/", &key)) attr_type = MAIL_ATTRIBUTE_TYPE_PRIVATE; - key += 9; - } else if (str_begins(key, "/shared/")) { + else if (str_begins(key, "/shared/", &key)) attr_type = MAIL_ATTRIBUTE_TYPE_SHARED; - key += 8; - } else { + else { *error_r = "Invalid key prefix, must be /private/ or /shared/"; return -1; } @@ -127,13 +123,11 @@ int lua_storage_mailbox_attribute_list(struct mailbox *box, const char *prefix, enum mail_attribute_type attr_type; int ret; - if (str_begins(prefix, "/private/")) { + if (str_begins(prefix, "/private/", &prefix)) attr_type = MAIL_ATTRIBUTE_TYPE_PRIVATE; - prefix += 9; - } else if (str_begins(prefix, "/shared/")) { + else if (str_begins(prefix, "/shared/", &prefix)) attr_type = MAIL_ATTRIBUTE_TYPE_SHARED; - prefix += 8; - } else { + else { *error_r = "Invalid key prefix, must be /private/ or /shared/"; return -1; } diff --git a/src/lib-storage/mailbox-attribute.c b/src/lib-storage/mailbox-attribute.c index 5eebbd2c4a..643746f500 100644 --- a/src/lib-storage/mailbox-attribute.c +++ b/src/lib-storage/mailbox-attribute.c @@ -197,9 +197,10 @@ mailbox_internal_attributes_get(struct mailbox *box, regs = array_get(&mailbox_internal_attributes, &count); for (j = i; j > 0; j--) { const struct mailbox_attribute_internal *attr = ®s[j-1]; + const char *suffix; if ((attr->flags & MAIL_ATTRIBUTE_INTERNAL_FLAG_CHILDREN) == 0 || - !str_begins(bare_prefix, attr->key)) + !str_begins(bare_prefix, attr->key, &suffix)) break; /* For example: bare_prefix="foo/bar" and attr->key="foo/", so @@ -207,8 +208,7 @@ mailbox_internal_attributes_get(struct mailbox *box, attrs: { "", "baz" }, which means with the full prefix: { "foo/bar", "foo/bar/baz" } */ if (attr->iter != NULL && - attr->iter(box, bare_prefix + strlen(attr->key), - attr_pool, attrs) < 0) + attr->iter(box, suffix, attr_pool, attrs) < 0) ret = -1; } diff --git a/src/lib-storage/mailbox-list.c b/src/lib-storage/mailbox-list.c index 0e99d19fe7..e5d8f9cd93 100644 --- a/src/lib-storage/mailbox-list.c +++ b/src/lib-storage/mailbox-list.c @@ -458,7 +458,7 @@ const char *mailbox_list_get_unexpanded_path(struct mailbox_list *list, static bool need_escape_dirstart(const char *vname, const char *maildir_name) { - size_t len; + const char *suffix; if (vname[0] == '.') { if (vname[1] == '\0' || vname[1] == '/') @@ -467,9 +467,8 @@ static bool need_escape_dirstart(const char *vname, const char *maildir_name) return TRUE; /* ".." */ } if (*maildir_name != '\0') { - len = strlen(maildir_name); - if (str_begins(vname, maildir_name) && - (vname[len] == '\0' || vname[len] == '/')) + if (str_begins(vname, maildir_name, &suffix) && + (suffix[0] == '\0' || suffix[0] == '/')) return TRUE; /* e.g. dbox-Mails */ } return FALSE; @@ -480,17 +479,14 @@ mailbox_list_escape_name_params(const char *vname, const char *ns_prefix, char ns_sep, char list_sep, char escape_char, const char *maildir_name) { - size_t ns_prefix_len = strlen(ns_prefix); string_t *escaped_name = t_str_new(64); bool dirstart = TRUE; i_assert(escape_char != '\0'); /* no escaping of namespace prefix */ - if (str_begins(vname, ns_prefix)) { - str_append_data(escaped_name, vname, ns_prefix_len); - vname += ns_prefix_len; - } + if (str_begins(vname, ns_prefix, &vname)) + str_append(escaped_name, ns_prefix); /* escape the mailbox name */ if (*vname == '~') { @@ -660,14 +656,11 @@ const char * mailbox_list_unescape_name_params(const char *src, const char *ns_prefix, char ns_sep, char list_sep, char escape_char) { - size_t ns_prefix_len = strlen(ns_prefix); string_t *dest = t_str_new(strlen(src)); unsigned int num; - if (str_begins(src, ns_prefix)) { - str_append_data(dest, src, ns_prefix_len); - src += ns_prefix_len; - } + if (str_begins(src, ns_prefix, &src)) + str_append(dest, ns_prefix); for (; *src != '\0'; src++) { if (*src == escape_char && @@ -1535,8 +1528,7 @@ int mailbox_has_children(struct mailbox_list *list, const char *name) int mailbox_list_mailbox(struct mailbox_list *list, const char *name, enum mailbox_info_flags *flags_r) { - const char *path, *fname, *rootdir, *dir, *inbox; - size_t len; + const char *path, *fname, *suffix, *rootdir, *dir, *inbox; *flags_r = 0; @@ -1611,8 +1603,7 @@ int mailbox_list_mailbox(struct mailbox_list *list, const char *name, fname++; } - len = strlen(rootdir); - if (str_begins(path, rootdir) && path[len] == '/') { + if (str_begins(path, rootdir, &suffix) && suffix[0] == '/') { /* looking up a regular mailbox under mail root dir */ } else if ((list->ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0 && strcasecmp(name, "INBOX") == 0) { @@ -1867,7 +1858,6 @@ bool mailbox_list_try_get_absolute_path(struct mailbox_list *list, const char **name) { const char *root_dir, *path, *mailbox_name; - size_t len; if (!list->mail_set->mail_full_filesystem_access) return FALSE; @@ -1886,9 +1876,9 @@ bool mailbox_list_try_get_absolute_path(struct mailbox_list *list, /* okay, we have an absolute path now. but check first if it points to same directory as one of our regular mailboxes. */ root_dir = mailbox_list_get_root_forced(list, MAILBOX_LIST_PATH_TYPE_MAILBOX); - len = strlen(root_dir); - if (str_begins(*name, root_dir) && (*name)[len] == '/') { - mailbox_name = *name + len + 1; + if (str_begins(*name, root_dir, &mailbox_name) && + mailbox_name[0] == '/') { + mailbox_name++; if (mailbox_list_get_path(list, mailbox_name, MAILBOX_LIST_PATH_TYPE_MAILBOX, &path) <= 0) diff --git a/src/lib-storage/test-mail-storage.c b/src/lib-storage/test-mail-storage.c index 335f48d29d..f9a8944eef 100644 --- a/src/lib-storage/test-mail-storage.c +++ b/src/lib-storage/test-mail-storage.c @@ -44,7 +44,7 @@ static void test_mail_storage_errors(void) /* NOTE: keep in sync with test-mailbox-list.c */ struct mail_storage storage; enum mail_error mail_error; - const char *errstr; + const char *errstr, *errstr_suffix = ""; test_begin("mail storage errors"); test_init_storage(&storage); @@ -137,8 +137,8 @@ static void test_mail_storage_errors(void) MAIL_ERRSTR_CRITICAL_MSG) != NULL); test_assert(mail_error == MAIL_ERROR_TEMP); errstr = mail_storage_get_last_internal_error(&storage, &mail_error); - test_assert(str_begins(errstr, "critical3: ")); - test_assert(strstr(errstr+11, MAIL_ERRSTR_CRITICAL_MSG) != NULL); + test_assert(str_begins(errstr, "critical3: ", &errstr_suffix)); + test_assert(strstr(errstr_suffix, MAIL_ERRSTR_CRITICAL_MSG) != NULL); test_assert(mail_error == MAIL_ERROR_TEMP); test_assert(storage.last_error_is_internal); diff --git a/src/lib-storage/test-mailbox-list.c b/src/lib-storage/test-mailbox-list.c index aa8f62ab37..d24857d18b 100644 --- a/src/lib-storage/test-mailbox-list.c +++ b/src/lib-storage/test-mailbox-list.c @@ -53,7 +53,7 @@ static void test_mailbox_list_errors(void) /* NOTE: keep in sync with test-mail-storage.c */ struct mailbox_list list; enum mail_error mail_error; - const char *errstr; + const char *errstr, *suffix = ""; test_begin("mail list errors"); test_init_list(&list); @@ -146,8 +146,8 @@ static void test_mailbox_list_errors(void) MAIL_ERRSTR_CRITICAL_MSG) != NULL); test_assert(mail_error == MAIL_ERROR_TEMP); errstr = mailbox_list_get_last_internal_error(&list, &mail_error); - test_assert(str_begins(errstr, "critical3: ")); - test_assert(strstr(errstr+11, MAIL_ERRSTR_CRITICAL_MSG) != NULL); + test_assert(str_begins(errstr, "critical3: ", &suffix)); + test_assert(strstr(suffix, MAIL_ERRSTR_CRITICAL_MSG) != NULL); test_assert(mail_error == MAIL_ERROR_TEMP); test_assert(list.last_error_is_internal); diff --git a/src/lib/iostream-rawlog.c b/src/lib/iostream-rawlog.c index 5805c9b30d..ccb1c6af6c 100644 --- a/src/lib/iostream-rawlog.c +++ b/src/lib/iostream-rawlog.c @@ -170,9 +170,8 @@ iostream_rawlog_try_create_tcp(const char *path, int ret, fd; /* tcp:host:port */ - if (!str_begins(path, "tcp:")) + if (!str_begins(path, "tcp:", &path)) return 0; - path += 4; if (strchr(path, '/') != NULL) return 0; diff --git a/src/lib/mempool-alloconly.c b/src/lib/mempool-alloconly.c index 5e743d05f8..42b9ff2fa2 100644 --- a/src/lib/mempool-alloconly.c +++ b/src/lib/mempool-alloconly.c @@ -252,10 +252,8 @@ pool_t pool_alloconly_create(const char *name ATTR_UNUSED, size_t size) new_apool = p_new(&apool.pool, struct alloconly_pool, 1); *new_apool = apool; #ifdef DEBUG - if (str_begins(name, MEMPOOL_GROWING)) { - name += strlen(MEMPOOL_GROWING); - new_apool->disable_warning = TRUE; - } else if (getenv("DEBUG_SILENT") != NULL) + if (str_begins(name, MEMPOOL_GROWING, &name) || + getenv("DEBUG_SILENT") != NULL) new_apool->disable_warning = TRUE; new_apool->name = p_strdup(&new_apool->pool, name); diff --git a/src/lib/module-dir.c b/src/lib/module-dir.c index 26fdeac175..87bf128e95 100644 --- a/src/lib/module-dir.c +++ b/src/lib/module-dir.c @@ -279,11 +279,8 @@ static int module_name_cmp(const char *const *n1, const char *const *n2) { const char *s1 = *n1, *s2 = *n2; - if (str_begins(s1, "lib")) - s1 += 3; - if (str_begins(s2, "lib")) - s2 += 3; - + (void)str_begins(s1, "lib", &s1); + (void)str_begins(s2, "lib", &s2); return strcmp(s1, s2); } @@ -664,8 +661,7 @@ const char *module_file_get_name(const char *fname) const char *p; /* [lib][nn_]name(.so) */ - if (str_begins(fname, "lib")) - fname += 3; + (void)str_begins(fname, "lib", &fname); for (p = fname; *p != '\0'; p++) { if (*p < '0' || *p > '9') diff --git a/src/lib/strfuncs.c b/src/lib/strfuncs.c index 32da9b0140..2f72ea74bf 100644 --- a/src/lib/strfuncs.c +++ b/src/lib/strfuncs.c @@ -633,8 +633,8 @@ str_match(const char *p1, const char *p2) return i; } -#undef str_begins_suffix -bool str_begins_suffix(const char *haystack, const char *needle, const char **suffix_r) +#undef str_begins +bool str_begins(const char *haystack, const char *needle, const char **suffix_r) { size_t prefix_len = str_match(haystack, needle); if (needle[prefix_len] != '\0') diff --git a/src/lib/strfuncs.h b/src/lib/strfuncs.h index 0042991de2..99baa28064 100644 --- a/src/lib/strfuncs.h +++ b/src/lib/strfuncs.h @@ -87,8 +87,8 @@ bool mem_equals_timing_safe(const void *p1, const void *p2, size_t size); bool str_equals_timing_almost_safe(const char *s1, const char *s2); size_t str_match(const char *p1, const char *p2) ATTR_PURE; -bool str_begins_suffix(const char *haystack, const char *needle, - const char **suffix_r); +bool str_begins(const char *haystack, const char *needle, + const char **suffix_r); static inline ATTR_PURE bool str_begins_with(const char *haystack, const char *needle) { @@ -107,12 +107,11 @@ str_begins_builtin_success(const char *haystack, size_t needle_len, # define str_begins_with(h, n) \ (__builtin_constant_p(n) ? strncmp((h), (n), strlen(n))==0 : \ (str_begins_with)((h), (n))) -# define str_begins_suffix(h, n, suffix_r) \ - (!__builtin_constant_p(n) ? (str_begins_suffix)((h), (n), (suffix_r)) : \ +# define str_begins(h, n, suffix_r) \ + (!__builtin_constant_p(n) ? (str_begins)((h), (n), (suffix_r)) : \ (strncmp((h), (n), strlen(n)) != 0 ? FALSE : \ str_begins_builtin_success((h), strlen(n), suffix_r))) #endif -#define str_begins(h, n) str_begins_with(h, n) /* Get length of a prefix segment. diff --git a/src/lib/test-failures.c b/src/lib/test-failures.c index c76d5b8c10..7cf42abcb3 100644 --- a/src/lib/test-failures.c +++ b/src/lib/test-failures.c @@ -80,13 +80,11 @@ internal_line_match(const char *line, const char *prefix, const char *text) return FALSE; line += 2; - if (!str_begins(line, "123 ")) + if (!str_begins(line, "123 ", &line)) return FALSE; - line += 4; - if (!str_begins(line, prefix)) + if (!str_begins(line, prefix, &line)) return FALSE; - line += strlen(prefix); return strcmp(line, text) == 0; } diff --git a/src/lib/test-strfuncs.c b/src/lib/test-strfuncs.c index 0972fea392..0100e733ec 100644 --- a/src/lib/test-strfuncs.c +++ b/src/lib/test-strfuncs.c @@ -489,20 +489,20 @@ test_str_match(void) sanity tests the match values above. */ bool equals = strncmp(tests[i].s1, tests[i].s2, strlen(tests[i].s2)) == 0; test_assert_idx(str_begins_with(tests[i].s1, tests[i].s2) == equals, i); - test_assert_idx(str_begins_suffix(tests[i].s1, tests[i].s2, &suffix) == equals && + test_assert_idx(str_begins(tests[i].s1, tests[i].s2, &suffix) == equals && (!equals || suffix == tests[i].s1 + strlen(tests[i].s2)), i); - test_assert_idx(str_begins_suffix(tests[i].s1, tests[i].s2, &suffix) == + test_assert_idx(str_begins(tests[i].s1, tests[i].s2, &suffix) == (strlen(tests[i].s2) == tests[i].match), i); } /* test literal-optimized versions of these */ - test_assert(str_begins_suffix("", "", &suffix) && suffix[0] == '\0'); - test_assert(str_begins_suffix("123", "", &suffix) && strcmp(suffix, "123") == 0); - test_assert(str_begins_suffix("123", "1", &suffix) && strcmp(suffix, "23") == 0); - test_assert(str_begins_suffix("123", "123", &suffix) && suffix[0] == '\0'); + test_assert(str_begins("", "", &suffix) && suffix[0] == '\0'); + test_assert(str_begins("123", "", &suffix) && strcmp(suffix, "123") == 0); + test_assert(str_begins("123", "1", &suffix) && strcmp(suffix, "23") == 0); + test_assert(str_begins("123", "123", &suffix) && suffix[0] == '\0'); suffix = NULL; - test_assert(!str_begins_suffix("123", "1234", &suffix) && suffix == NULL); - test_assert(!str_begins_suffix("", "123", &suffix) && suffix == NULL); - test_assert(!str_begins_suffix("12", "123", &suffix) && suffix == NULL); + test_assert(!str_begins("123", "1234", &suffix) && suffix == NULL); + test_assert(!str_begins("", "123", &suffix) && suffix == NULL); + test_assert(!str_begins("12", "123", &suffix) && suffix == NULL); test_assert(str_begins_with("", "")); test_assert(str_begins_with("123", "")); diff --git a/src/log/log-connection.c b/src/log/log-connection.c index 926798bb38..f65226c85c 100644 --- a/src/log/log-connection.c +++ b/src/log/log-connection.c @@ -116,13 +116,14 @@ static void log_parse_option(struct log_connection *log, const struct failure_line *failure) { struct log_client *client; + const char *value; client = log_client_get(log, failure->pid); - if (str_begins(failure->text, "ip=")) - (void)net_addr2ip(failure->text + 3, &client->ip); - else if (str_begins(failure->text, "prefix=")) { + if (str_begins(failure->text, "ip=", &value)) + (void)net_addr2ip(value, &client->ip); + else if (str_begins(failure->text, "prefix=", &value)) { i_free(client->prefix); - client->prefix = i_strdup(failure->text + 7); + client->prefix = i_strdup(value); } } @@ -193,7 +194,7 @@ log_parse_master_line(const char *line, const struct timeval *log_time, { struct log_connection *const *logs, *log; struct log_client *client; - const char *p, *p2, *cmd, *pidstr; + const char *p, *p2, *cmd, *args, *pidstr; unsigned int count; unsigned int service_fd; pid_t pid; @@ -232,13 +233,13 @@ log_parse_master_line(const char *line, const struct timeval *log_time, return; } log_client_free(log, client, pid); - } else if (str_begins(cmd, "FATAL ")) { - client_log_fatal(log, client, cmd + 6, log_time, tm); - } else if (str_begins(cmd, "DEFAULT-FATAL ")) { + } else if (str_begins(cmd, "FATAL ", &args)) { + client_log_fatal(log, client, args, log_time, tm); + } else if (str_begins(cmd, "DEFAULT-FATAL ", &args)) { /* If the client has logged a fatal/panic, don't log this message. */ if (client == NULL || !client->fatal_logged) - client_log_fatal(log, client, cmd + 14, log_time, tm); + client_log_fatal(log, client, args, log_time, tm); } else { i_error("Received unknown command from master: %s", cmd); } diff --git a/src/login-common/sasl-server.c b/src/login-common/sasl-server.c index 61616440d7..1369a01b85 100644 --- a/src/login-common/sasl-server.c +++ b/src/login-common/sasl-server.c @@ -301,18 +301,20 @@ sasl_server_check_login(struct client *client) static bool args_parse_user(struct client *client, const char *arg) { - if (str_begins(arg, "user=")) { + const char *value; + + if (str_begins(arg, "user=", &value)) { i_free(client->virtual_user); i_free_and_null(client->virtual_user_orig); i_free_and_null(client->virtual_auth_user); - client->virtual_user = i_strdup(arg + 5); + client->virtual_user = i_strdup(value); event_add_str(client->event, "user", client->virtual_user); - } else if (str_begins(arg, "original_user=")) { + } else if (str_begins(arg, "original_user=", &value)) { i_free(client->virtual_user_orig); - client->virtual_user_orig = i_strdup(arg + 14); - } else if (str_begins(arg, "auth_user=")) { + client->virtual_user_orig = i_strdup(value); + } else if (str_begins(arg, "auth_user=", &value)) { i_free(client->virtual_auth_user); - client->virtual_auth_user = i_strdup(arg + 10); + client->virtual_auth_user = i_strdup(value); } else { return FALSE; } @@ -325,6 +327,7 @@ authenticate_callback(struct auth_client_request *request, const char *const *args, void *context) { struct client *client = context; + const char *value; unsigned int i; bool nologin; @@ -353,19 +356,19 @@ authenticate_callback(struct auth_client_request *request, for (i = 0; args[i] != NULL; i++) { if (args_parse_user(client, args[i])) ; - else if (str_begins(args[i], "postlogin_socket=")) { + else if (str_begins(args[i], "postlogin_socket=", &value)) { client->postlogin_socket_path = - p_strdup(client->pool, args[i] + 17); + p_strdup(client->pool, value); } else if (strcmp(args[i], "nologin") == 0 || strcmp(args[i], "proxy") == 0) { /* user can't login */ nologin = TRUE; } else if (strcmp(args[i], "anonymous") == 0 ) { client->auth_anonymous = TRUE; - } else if (str_begins(args[i], "resp=") && + } else if (str_begins(args[i], "resp=", &value) && login_binary->sasl_support_final_reply) { client->sasl_final_resp = - p_strdup(client->pool, args[i] + 5); + p_strdup(client->pool, value); } } diff --git a/src/master/test-auth-client.c b/src/master/test-auth-client.c index f9e79df8dc..4cbc143bc4 100644 --- a/src/master/test-auth-client.c +++ b/src/master/test-auth-client.c @@ -455,10 +455,8 @@ test_auth_handshake_auth(struct server_connection *conn, unsigned int id, mech = args[0]; resp = NULL; for (i = 1; args[i] != NULL; i++) { - if (str_begins(args[i], "resp=")) { - resp = t_strdup(args[i] + 5); + if (str_begins(args[i], "resp=", &resp)) break; - } } data = t_buffer_create(256); if (resp != NULL) { diff --git a/src/plugins/acl/acl-api.c b/src/plugins/acl/acl-api.c index 2e422ea54b..539050f199 100644 --- a/src/plugins/acl/acl-api.c +++ b/src/plugins/acl/acl-api.c @@ -518,17 +518,16 @@ bool acl_rights_has_nonowner_lookup_changes(const struct acl_rights *rights) int acl_identifier_parse(const char *line, struct acl_rights *rights) { - if (str_begins(line, ACL_ID_NAME_USER_PREFIX)) { + if (str_begins(line, ACL_ID_NAME_USER_PREFIX, &rights->identifier)) { rights->id_type = ACL_ID_USER; - rights->identifier = line + 5; } else if (strcmp(line, ACL_ID_NAME_OWNER) == 0) { rights->id_type = ACL_ID_OWNER; - } else if (str_begins(line, ACL_ID_NAME_GROUP_PREFIX)) { + } else if (str_begins(line, ACL_ID_NAME_GROUP_PREFIX, + &rights->identifier)) { rights->id_type = ACL_ID_GROUP; - rights->identifier = line + 6; - } else if (str_begins(line, ACL_ID_NAME_GROUP_OVERRIDE_PREFIX)) { + } else if (str_begins(line, ACL_ID_NAME_GROUP_OVERRIDE_PREFIX, + &rights->identifier)) { rights->id_type = ACL_ID_GROUP_OVERRIDE; - rights->identifier = line + 15; } else if (strcmp(line, ACL_ID_NAME_AUTHENTICATED) == 0) { rights->id_type = ACL_ID_AUTHENTICATED; } else if (strcmp(line, ACL_ID_NAME_ANYONE) == 0 || diff --git a/src/plugins/acl/acl-backend-vfile.c b/src/plugins/acl/acl-backend-vfile.c index e7cc2dbf06..2098006a01 100644 --- a/src/plugins/acl/acl-backend-vfile.c +++ b/src/plugins/acl/acl-backend-vfile.c @@ -34,7 +34,7 @@ acl_backend_vfile_init(struct acl_backend *_backend, const char *data) struct acl_backend_vfile *backend = (struct acl_backend_vfile *)_backend; struct stat st; - const char *const *tmp; + const char *value, *const *tmp; const char *global_path; tmp = t_strsplit(data, ":"); @@ -44,8 +44,8 @@ acl_backend_vfile_init(struct acl_backend *_backend, const char *data) if (*tmp != NULL) tmp++; for (; *tmp != NULL; tmp++) { - if (str_begins(*tmp, "cache_secs=")) { - if (str_to_uint(*tmp + 11, &backend->cache_secs) < 0) { + if (str_begins(*tmp, "cache_secs=", &value)) { + if (str_to_uint(value, &backend->cache_secs) < 0) { i_error("acl vfile: Invalid cache_secs value: %s", *tmp + 11); return -1; diff --git a/src/plugins/acl/acl-backend.c b/src/plugins/acl/acl-backend.c index 0514dc736f..ff6b551255 100644 --- a/src/plugins/acl/acl-backend.c +++ b/src/plugins/acl/acl-backend.c @@ -46,8 +46,8 @@ acl_backend_init(const char *data, struct mailbox_list *list, group_count = str_array_length(groups); - if (str_begins(data, "vfile:")) - data += 6; + if (str_begins(data, "vfile:", &data)) + ; else if (strcmp(data, "vfile") == 0) data = ""; else diff --git a/src/plugins/fs-compress/fs-compress.c b/src/plugins/fs-compress/fs-compress.c index ab03076e03..cda1de1698 100644 --- a/src/plugins/fs-compress/fs-compress.c +++ b/src/plugins/fs-compress/fs-compress.c @@ -52,10 +52,8 @@ fs_compress_init(struct fs *_fs, const char *args, int ret; /* get compression handler name */ - if (str_begins(args, "maybe-")) { + if (str_begins(args, "maybe-", &args)) fs->try_plain = TRUE; - args += 6; - } p = strchr(args, ':'); if (p == NULL) { diff --git a/src/plugins/fts-solr/fts-solr-plugin.c b/src/plugins/fts-solr/fts-solr-plugin.c index 5899784330..ad8568de7b 100644 --- a/src/plugins/fts-solr/fts-solr-plugin.c +++ b/src/plugins/fts-solr/fts-solr-plugin.c @@ -21,7 +21,7 @@ static int fts_solr_plugin_init_settings(struct mail_user *user, struct fts_solr_settings *set, const char *str) { - const char *const *tmp; + const char *value, *const *tmp; if (str == NULL) str = ""; @@ -30,27 +30,26 @@ fts_solr_plugin_init_settings(struct mail_user *user, set->soft_commit = TRUE; for (tmp = t_strsplit_spaces(str, " "); *tmp != NULL; tmp++) { - if (str_begins(*tmp, "url=")) { - set->url = p_strdup(user->pool, *tmp + 4); + if (str_begins(*tmp, "url=", &value)) { + set->url = p_strdup(user->pool, value); } else if (strcmp(*tmp, "debug") == 0) { set->debug = TRUE; } else if (strcmp(*tmp, "use_libfts") == 0) { set->use_libfts = TRUE; - } else if (str_begins(*tmp, "default_ns=")) { - set->default_ns_prefix = - p_strdup(user->pool, *tmp + 11); - } else if (str_begins(*tmp, "rawlog_dir=")) { - set->rawlog_dir = p_strdup(user->pool, *tmp + 11); - } else if (str_begins(*tmp, "batch_size=")) { - if (str_to_uint(*tmp+11, &set->batch_size) < 0 || + } else if (str_begins(*tmp, "default_ns=", &value)) { + set->default_ns_prefix = p_strdup(user->pool, value); + } else if (str_begins(*tmp, "rawlog_dir=", &value)) { + set->rawlog_dir = p_strdup(user->pool, value); + } else if (str_begins(*tmp, "batch_size=", &value)) { + if (str_to_uint(value, &set->batch_size) < 0 || set->batch_size == 0) { i_error("fts_solr: batch_size must be a positive integer"); return -1; } - } else if (str_begins(*tmp, "soft_commit=")) { - if (strcmp(*tmp + 12, "yes") == 0) { + } else if (str_begins(*tmp, "soft_commit=", &value)) { + if (strcmp(value, "yes") == 0) { set->soft_commit = TRUE; - } else if (strcmp(*tmp + 12, "no") == 0) { + } else if (strcmp(value, "no") == 0) { set->soft_commit = FALSE; } else { i_error("fts_solr: Invalid setting for soft_commit: %s", *tmp+12); diff --git a/src/plugins/imap-acl/imap-acl-plugin.c b/src/plugins/imap-acl/imap-acl-plugin.c index 87e1628cc6..ab602a92e9 100644 --- a/src/plugins/imap-acl/imap-acl-plugin.c +++ b/src/plugins/imap-acl/imap-acl-plugin.c @@ -822,13 +822,11 @@ imap_acl_identifier_parse(struct client_command_context *cmd, rights->id_type = ACL_ID_AUTHENTICATED; } else if (strcmp(id, IMAP_ACL_OWNER) == 0) rights->id_type = ACL_ID_OWNER; - else if (str_begins(id, IMAP_ACL_GROUP_PREFIX)) { + else if (str_begins(id, IMAP_ACL_GROUP_PREFIX, &rights->identifier)) rights->id_type = ACL_ID_GROUP; - rights->identifier = id + strlen(IMAP_ACL_GROUP_PREFIX); - } else if (str_begins(id, IMAP_ACL_GROUP_OVERRIDE_PREFIX)) { + else if (str_begins(id, IMAP_ACL_GROUP_OVERRIDE_PREFIX, + &rights->identifier)) { rights->id_type = ACL_ID_GROUP_OVERRIDE; - rights->identifier = id + - strlen(IMAP_ACL_GROUP_OVERRIDE_PREFIX); } else { rights->id_type = ACL_ID_USER; rights->identifier = id; diff --git a/src/plugins/quota/quota-status.c b/src/plugins/quota/quota-status.c index 7db0cb4262..54ec0c0da7 100644 --- a/src/plugins/quota/quota-status.c +++ b/src/plugins/quota/quota-status.c @@ -218,6 +218,7 @@ static void client_handle_request(struct quota_client *client) static int client_input_line(struct connection *conn, const char *line) { struct quota_client *client = (struct quota_client *)conn; + const char *value; e_debug(client->event, "Request: %s", str_sanitize(line, 1024)); @@ -228,15 +229,15 @@ static int client_input_line(struct connection *conn, const char *line) client_reset(client); return 1; } - if (str_begins(line, "recipient=")) { + if (str_begins(line, "recipient=", &value)) { if (client->recipient == NULL) - client->recipient = i_strdup(line + 10); - } else if (str_begins(line, "size=")) { - if (str_to_uoff(line+5, &client->size) < 0) + client->recipient = i_strdup(value); + } else if (str_begins(line, "size=", &value)) { + if (str_to_uoff(value, &client->size) < 0) client->size = 0; - } else if (str_begins(line, "protocol_state=")) { + } else if (str_begins(line, "protocol_state=", &value)) { if (client->state == NULL) - client->state = i_strdup(line + 15); + client->state = i_strdup(value); } return 1; } diff --git a/src/plugins/quota/quota-util.c b/src/plugins/quota/quota-util.c index 95ce369cf7..e9ff3262c5 100644 --- a/src/plugins/quota/quota-util.c +++ b/src/plugins/quota/quota-util.c @@ -228,7 +228,7 @@ int quota_root_add_rule(struct quota_root_settings *root_set, const char *rule_def, const char **error_r) { struct quota_rule *rule; - const char *p, *mailbox_mask; + const char *p, *mailbox_mask, *value; int ret = 0; p = strchr(rule_def, ':'); @@ -262,12 +262,12 @@ int quota_root_add_rule(struct quota_root_settings *root_set, return 0; } - if (str_begins(p, "backend=")) { + if (str_begins(p, "backend=", &value)) { if (root_set->backend->v.parse_rule == NULL) { *error_r = "backend rule not supported"; ret = -1; } else if (!root_set->backend->v.parse_rule(root_set, rule, - p + 8, error_r)) + value, error_r)) ret = -1; } else { bool relative_rule = rule != &root_set->default_rule; diff --git a/src/plugins/quota/quota.c b/src/plugins/quota/quota.c index 3d6d8e51e5..c972551bbf 100644 --- a/src/plugins/quota/quota.c +++ b/src/plugins/quota/quota.c @@ -184,11 +184,11 @@ quota_root_parse_set(struct mail_user *user, const char *root_name, if (value == NULL) return 0; - if (!str_begins(value, "dict:")) { + if (!str_begins(value, "dict:", &value)) { *error_r = t_strdup_printf("%s supports only dict backend", name); return -1; } - root_set->limit_set = p_strdup(root_set->set->pool, value+5); + root_set->limit_set = p_strdup(root_set->set->pool, value); return 0; } diff --git a/src/pop3-login/pop3-proxy.c b/src/pop3-login/pop3-proxy.c index 91674640c1..78c40bfa39 100644 --- a/src/pop3-login/pop3-proxy.c +++ b/src/pop3-login/pop3-proxy.c @@ -205,6 +205,7 @@ int pop3_proxy_parse_line(struct client *client, const char *line) struct pop3_client *pop3_client = (struct pop3_client *)client; struct ostream *output; enum auth_proxy_ssl_flags ssl_flags; + const char *sasl_value; i_assert(!client->destroyed); @@ -212,7 +213,7 @@ int pop3_proxy_parse_line(struct client *client, const char *line) switch (pop3_client->proxy_state) { case POP3_PROXY_BANNER: /* this is a banner */ - if (!str_begins(line, "+OK")) { + if (!str_begins(line, "+OK", &line)) { const char *reason = t_strdup_printf( "Invalid banner: %s", str_sanitize(line, 160)); login_proxy_failed(client->login_proxy, @@ -221,7 +222,7 @@ int pop3_proxy_parse_line(struct client *client, const char *line) return -1; } pop3_client->proxy_xclient = - str_begins_with(line+3, " [XCLIENT]"); + str_begins_with(line, " [XCLIENT]"); ssl_flags = login_proxy_get_ssl_flags(client->login_proxy); if ((ssl_flags & AUTH_PROXY_SSL_FLAG_STARTTLS) == 0) { @@ -271,11 +272,11 @@ int pop3_proxy_parse_line(struct client *client, const char *line) pop3_client->proxy_state = POP3_PROXY_LOGIN2; return 0; case POP3_PROXY_LOGIN2: - if (str_begins(line, "+ ") && + if (str_begins(line, "+ ", &sasl_value) && client->proxy_sasl_client != NULL) { /* continue SASL authentication */ if (pop3_proxy_continue_sasl_auth(client, output, - line+2) < 0) + sasl_value) < 0) return -1; return 0; } diff --git a/src/util/script.c b/src/util/script.c index 6ae4621dc7..e97658e590 100644 --- a/src/util/script.c +++ b/src/util/script.c @@ -148,19 +148,19 @@ parse_input(ARRAY_TYPE(const_string)* envs, const char *const **args_r, *args_r = t_strsplit(str_c(input), "\n"); script_verify_version(**args_r); (*args_r)++; if (**args_r != NULL) { - const char *p; + const char *p, *value; - if (str_begins(**args_r, "alarm=")) { + if (str_begins(**args_r, "alarm=", &value)) { unsigned int seconds; - if (str_to_uint((**args_r) + 6, &seconds) < 0) + if (str_to_uint(value, &seconds) < 0) i_fatal("invalid alarm option"); alarm(seconds); (*args_r)++; } - while (str_begins(**args_r, "env_")) { + while (str_begins(**args_r, "env_", &value)) { const char *envname, *env; - env = t_str_tabunescape((**args_r)+4); + env = t_str_tabunescape(value); p = strchr(env, '='); if (p == NULL) i_fatal("invalid environment variable");