]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
global: Rename str_begins_suffix() to str_begins() and use it everywhere
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Fri, 10 Apr 2020 16:13:07 +0000 (19:13 +0300)
committertimo.sirainen <timo.sirainen@open-xchange.com>
Wed, 23 Mar 2022 10:25:06 +0000 (10:25 +0000)
101 files changed:
src/auth/auth-cache.c
src/auth/auth-client-connection.c
src/auth/auth-master-connection.c
src/auth/auth-request-fields.c
src/auth/auth-request.c
src/auth/db-oauth2.c
src/auth/mech-oauth2.c
src/auth/mech-otp.c
src/auth/passdb-bsdauth.c
src/auth/passdb-checkpassword.c
src/auth/passdb-lua.c
src/auth/passdb-pam.c
src/auth/password-scheme.c
src/auth/userdb-blocking.c
src/auth/userdb-lua.c
src/auth/userdb-passwd-file.c
src/config/config-connection.c
src/config/config-parser.c
src/config/old-set-parser.c
src/config/sysinfo-get.c
src/director/login-connection.c
src/doveadm/client-connection-tcp.c
src/doveadm/doveadm-auth-server.c
src/doveadm/doveadm-auth.c
src/doveadm/doveadm-dsync.c
src/doveadm/doveadm-mail-fetch.c
src/doveadm/doveadm-mail-mailbox-metadata.c
src/doveadm/doveadm-mail-server.c
src/doveadm/doveadm-util.c
src/doveadm/dsync/dsync-brain-mailbox-tree.c
src/imap-hibernate/imap-client.c
src/imap-login/imap-proxy.c
src/imap-urlauth/imap-urlauth.c
src/imap/cmd-notify.c
src/imap/cmd-rename.c
src/imap/imap-fetch-body.c
src/imap/imap-notify.c
src/imap/imap-sync.c
src/lib-auth/auth-client-request.c
src/lib-auth/auth-master.c
src/lib-dcrypt/dcrypt-openssl.c
src/lib-dict-backend/dict-sql-settings.c
src/lib-dict-extra/dict-fs.c
src/lib-dict/dict-client.c
src/lib-dict/dict-redis.c
src/lib-dns/test-dns-lookup.c
src/lib-fs/fs-posix.c
src/lib-http/http-server-resource.c
src/lib-imap-storage/imap-metadata.c
src/lib-imap-storage/imap-msgpart.c
src/lib-imap/imap-base-subject.c
src/lib-master/master-login-auth.c
src/lib-master/master-login.c
src/lib-master/master-service-settings-cache.c
src/lib-master/master-service-settings.c
src/lib-master/master-service.c
src/lib-program-client/program-client.c
src/lib-settings/settings-parser.c
src/lib-sql/driver-pgsql.c
src/lib-sql/driver-sqlite.c
src/lib-storage/index/dbox-multi/mdbox-purge.c
src/lib-storage/index/dbox-single/sdbox-sync-rebuild.c
src/lib-storage/index/imapc/imapc-list.c
src/lib-storage/index/imapc/imapc-mail-fetch.c
src/lib-storage/index/index-storage.c
src/lib-storage/index/pop3c/pop3c-storage.c
src/lib-storage/index/shared/shared-list.c
src/lib-storage/list/mailbox-list-fs-iter.c
src/lib-storage/list/mailbox-list-index-backend.c
src/lib-storage/list/mailbox-list-iter.c
src/lib-storage/mail-search-register-imap.c
src/lib-storage/mail-storage-hooks.c
src/lib-storage/mail-storage-service.c
src/lib-storage/mail-storage-settings.c
src/lib-storage/mail-user-lua.c
src/lib-storage/mailbox-attribute-lua.c
src/lib-storage/mailbox-attribute.c
src/lib-storage/mailbox-list.c
src/lib-storage/test-mail-storage.c
src/lib-storage/test-mailbox-list.c
src/lib/iostream-rawlog.c
src/lib/mempool-alloconly.c
src/lib/module-dir.c
src/lib/strfuncs.c
src/lib/strfuncs.h
src/lib/test-failures.c
src/lib/test-strfuncs.c
src/log/log-connection.c
src/login-common/sasl-server.c
src/master/test-auth-client.c
src/plugins/acl/acl-api.c
src/plugins/acl/acl-backend-vfile.c
src/plugins/acl/acl-backend.c
src/plugins/fs-compress/fs-compress.c
src/plugins/fts-solr/fts-solr-plugin.c
src/plugins/imap-acl/imap-acl-plugin.c
src/plugins/quota/quota-status.c
src/plugins/quota/quota-util.c
src/plugins/quota/quota.c
src/pop3-login/pop3-proxy.c
src/util/script.c

index e8aa10573c325d34f75608ace3d8c7c388f66a02..46f697cee7142019965709882339d03ec42fa8d5 100644 (file)
@@ -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,
index 961480e0f94bf0ba138e63b2d59cac9e1c7b1432..902967d2a8c1ad1bb50859349f3108098b5144a8 100644 (file)
@@ -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;
                        }
index 9aa83feeed3792563480db71dc1ef47b94476746..1f13362d7d9d9c3830cba7551d19fae98a1a63ab 100644 (file)
@@ -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 "
index 590e6711b17226c8a8d3fc05657c9762855d40c8..9335e90f08c309076abc8966d2a6eaeabae8f371 100644 (file)
@@ -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;
 
index a9131e6438b61b84d5b6480b311849e3675aa88c..cd08b1fa02faf8f27753204c108f885274475055 100644 (file)
@@ -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. */
index 3c6ef3acb9d2538a091037bc3e7ef0569211ce01..f34060a7d308fb3d29b09298cea55b49920e24a8 100644 (file)
@@ -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;
                        }
index 1b145674b3b2568a154f05978735e07d376cf66c..4348b10afff7c72ef7814b4b279c72e694c99ac8 100644 (file)
@@ -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;
index 58f3db15e09c374d359c7ee32896d0d2d0d1b590..7aa9d7e58593f3a47cad7612d86dba1639a39329 100644 (file)
@@ -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");
index 36469c679b827a32bae4d45ea10b471268e521cc..c8d902a097dc858e2c9fd857c2eddbb228f57d91 100644 (file)
@@ -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;
index 101c7f0c57233c28507f4f13f8811f5da1a355be..b351b94d7277933262a48c7fdd28275bd70c2e2d 100644 (file)
@@ -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);
index 0ad15a5162919588d7bebb5575acb6943436368f..1b39146efc522006b46f6b8299958a2298f0c82a 100644 (file)
@@ -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);
                }
index 6a1032dfc5390e6d25f971ffe9b3b119ebb342f7..6fd5e8ca1b929af85fd678981e6f9b1673133fb7 100644 (file)
@@ -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]);
index 6d09af603d7eb81d350b34f13f4cbdbf200371a1..46755918e849f197ae2f1f49ed167366bb4439c5 100644 (file)
@@ -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$<salt>$<password>[$<ignored>] */
-               p = strchr(*password + 3, '$');
+               p = strchr(suffix, '$');
                if (p != NULL) {
                        /* stop at next '$' after password */
                        p = strchr(p+1, '$');
index 4163259118bb7a40c4f6ef6ef7904be3e329bca3..37952535ad71de80721d66d93d79b3f2973385b7 100644 (file)
@@ -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;
        }
 
index 6ffa12464fcd837ea8aee4f813faf7ae07f3276b..1712f701623bbe1899f303410e448113a0f737be 100644 (file)
@@ -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 {
index 1e87138edcc64128646bfd17448f50dea07a4046..b9f736824c6f0c2490d36d6a2ff4f2d44acb35bc 100644 (file)
@@ -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);
index bd3db86505d3e58c07965972b5b956464ab6296a..26c3e4eb577c411bc7683c30fd08bdbfd43c539a 100644 (file)
@@ -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;
index 26090deb5bef98a6c81137a825abacd178dd9e8e..e555767093195314598f1ad3a896e407fb8aded2 100644 (file)
@@ -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 {
index 08f3085d9f76c1dedd2bb4c7df642a8cb50f3651..89c05292f7c14941cc60145fe5cda6fb01c5881a 100644 (file)
@@ -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 &&
index dffebe6e2c25a54aa169c4cc53081e7eafa2779c..0d55cd634db3050a531f3c2a79700be3f0f46838 100644 (file)
@@ -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 {
index 765ad0aabb4ccbe1964dad7b36b20e6d1405c8d9..eae0c66ef7098dec7c27af516f18d0fcfdf45ce8 100644 (file)
@@ -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) ||
index 23f24dc320486489bf17b5913fa49702422dd5d8..c1a2448470ba884dcc1d3053bd96e1ff738c85e8 100644 (file)
@@ -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;
        }
index f50fa5f4e54d8ad6d64c6330ef08ddb2c66463f0..7a6016543b49fb92f1edd8680f3a1844c7f81b58 100644 (file)
@@ -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);
index d89befe2e45f6f5f174dd7469014648f431d334b..17058f611cbe4e5ae9b95eaa85afc64d5bc77664 100644 (file)
@@ -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 = "";
index ed10499230348f1e3564dde544d3d6ee5a8f775c..fbb1ce8d859ec93e62b055132b502f7db1987372 100644 (file)
@@ -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 */
index 932a54de70b4efdcbeed41cc7cf464d301f4b77a..bed1a0147fc1ca84f1749d722020501c181c4246 100644 (file)
@@ -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.", &section) ||
+                          str_begins(name, "binary.", &section)) {
                        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);
index 593555b05ad74e44726686548ccfb6e0df494dbc..e5271d15056ba8675715b1e67db14fb1d31e1c0a 100644 (file)
@@ -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 = "";
index f9a8f752be39b3d09303556c5eee25c14e33eb7c..1a888a0e35122e6a6f107973e4fe42abfd4e117c 100644 (file)
@@ -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);
                }
        }
index 5a1069231261ede393c5206e6f7ae63bb354497d..c5ec5d18a8818c6b662eaf18fa53e7aab14d73ce 100644 (file)
@@ -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' ||
index 44b76bf47ce34ef863202173dd399ca71a57fc7c..b529e4b21e807f084339af22b7751a6ab33036d9 100644 (file)
@@ -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 */
index 6ac0951e007120fa9743ee1965646187e230ea8d..9dd26a8fafc69fed8a5aaf431ee2f97f531c1b28 100644 (file)
@@ -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;
index 1fe5fbbf6d0b2ee2999b889eb3d3e863c9d6dc05..aa38062ebf024eb506998b38074f606972cf7ebd 100644 (file)
@@ -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;
index 3585cdff7baa8e11aeb3b7ce1ebb40da9a4fad71..a849783dffb2d0c207bb98e40a2992c955738e0d 100644 (file)
@@ -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) {
index bd17fd29da6aac47a3227b43a6a3ab7cd9baf1b6..cdb6dc961f62417470832ae8a554cc0a45a81c2f 100644 (file)
@@ -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(&notify_boxes->names, i, 1);
                                names = array_get(&notify_boxes->names, &count);
index 45b44fd183c5eb64ed8f05fcdd77f35d2c972e1c..a2f8c36178b16a0e9d0e575e2ebcae48703ac838 100644 (file)
@@ -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;
 
        /* <old name> <new name> */
        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;
index b467334ec309d88181c56040f0f4d46b0fd56c9a..0c8f87f29897b056c0a9a04721ba9e9771f8398b 100644 (file)
@@ -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 != '[') {
index fa2c9ef4c143e99ff3471ab97b290ad88405618e..80bc41bfa8a7b03eea9f1edf09336c0f9bc6e414 100644 (file)
@@ -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(&notify_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;
index fc49ae7230a30345983e3a6b1ba6104b86fd0d0f..b9990393e80dee9ec1b81069aa1c2ad8a1e8b5ed 100644 (file)
@@ -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(
index 629b77bcfaac936c139bc0bcec3b852badf3cdaf..df68b5e4ea13e86707ab36737b77486eb88d26db 100644 (file)
@@ -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);
        }
 
index 57cf8d21ba5dae70672d83902c66e8ce20b32992..1ff0e1bf7950e77213a049e4997687058e7631c5 100644 (file)
@@ -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 {
index 01b70b989109068e7c51dbdbe101b10fa9f91ceb..ffb0a8bf065c883484419e50319ddf38e139ea39 100644 (file)
@@ -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-----"))
index fec48b380bb28014f5c9928f00ef4ac1bc03c0ea..66203a0bfa0990bf078e249431cb8fdac6b483d1 100644 (file)
@@ -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);
index 7bd0b82dd6f4f3a12392962c1a3d4b0ca2661712..0d68d24eb34f3709b2dc3ea91762e76f01258c43 100644 (file)
@@ -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,
index f18ae6b3ab96a2e5c65e2b1a23134b6f20996984..57344d27fc548736508221162989c8bfb5a3d521 100644 (file)
@@ -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=<n>:] [warn_slow_msecs=<n>:] [<path>] ":" <uri> */
        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;
                        }
index 57fe333715636d455b25072c9fffc977daedc133..72e15060738da6b4da17fbe33fcb6389dc6edbbd 100644 (file)
@@ -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();
        }
index db7092336736d7d63a43381dbca5958fe4776583..3ca66fa34b44cdfdcea554fbddf70339b1560b0f 100644 (file)
@@ -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 =
index 5b882d522f2f3c54717744b044f06d9312bbcdaf..b9f5a155e998740b614924a52c42ce0bfedef583 100644 (file)
@@ -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 {
index dc602e4048b97374c6b0b14a865a3f68138fead2..943914deffaabcf6d86676a4c7c62223282876d1 100644 (file)
@@ -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;
 }
index ebbcd69504e7ab3450cad972f1b1bdff861432b2..1a1552f7d4c45f886b33993f743e44f2d8998858 100644 (file)
@@ -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 {
index 3bce11754b81adc850850538568be9c194934954..46bc089e43244c1427be12b50d8780f207328c74 100644 (file)
@@ -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;
                }
index 5736fa8786b813a1715c3986e87322f04709c8e1..cb5fa50ad54d9dfdc48362989209770c96432760 100644 (file)
@@ -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 == ' ')
index 34c777a5ca795d493288371bd447f062507d0ae5..a200c1de4aed9a9ba4535baab87eebedb84897a7 100644 (file)
@@ -435,10 +435,8 @@ master_login_auth_input_fail(struct master_login_auth *auth, unsigned int id,
 
        /* FAIL <id> [..] [reason=<error>] [..] */
        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);
index e25ce35a79a7704866a8823680a77d3e652fcafa..888fe5cfb41406d1b91c01796458515e0ad0dc95 100644 (file)
@@ -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;
 }
index 11dd66bb5a20597926ba3ee6baeb8cf8bace454a..fc409fcff3ab26ca237d8ea313b96f5a31e50709 100644 (file)
@@ -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++;
                }
index f0f0797f43983aa5bf5bcd1e3a15dfce28a354d6..d2ecb5970449e01907a1f8cfb5f813c3dd8cb17e 100644 (file)
@@ -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);
                        }
                }
index c8cd3ac80163b014a889ee81e5a38fa1d7ba4109..6e9ab341d0e54a897992a0bd274db2b22d9856b6 100644 (file)
@@ -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')
index ad7dfa72ff1a4c94f8630c2f6401cd816920181e..f85dda3cfdefa31f7b8811bb34279659202d3e0e 100644 (file)
@@ -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,
index 1fb398853b1cfae05434915e617976842c4ab8bd..eb15b969687224a94f428f5f3617b1d8925b6ab2 100644 (file)
@@ -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;
                }
 
index b87d41576c4b90ad241882002d73db16933228a2..2775b7eca131873d2048da6a3a3898229c3129ec 100644 (file)
@@ -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;
index a80265a7ce79da9cdb5edcd3ae66ad593bd4f16f..77bc59c439d43b56ea25d9839247486b276139ce 100644 (file)
@@ -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;
                        }
index 8461074fb13d73a532c0c0565b77c9ae9194c282..60508e315ac912618b195dbb8e39149fc9fbe35b 100644 (file)
@@ -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);
index aa4832f15f45f36654eafe9b63b386466f461fbf..c4feeca17aa82f2136ff37014bb3dc39ee556452 100644 (file)
@@ -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",
index a9e03ecf02fdb3f37a52e5d7e0d15e46828b4737..5ecf6faf91408c50b130075999b979d373bf25e0 100644 (file)
@@ -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 {
index 1b0eee7100179c2047935b0426978feaee58519c..0e00a1d8ca1b7fcc86dbffd0f43250e575bec338 100644 (file)
@@ -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;
index 01f7fef57b2a78b558b80a80165b7a231c082a3a..adfd90445f6e9b02cf6530f71283c228b094c8a9 100644 (file)
@@ -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;
        }
index f7846836e8b1a05c6c4aa9f6d73f99b0d93f5ce5..de8934aa0389441e5a5240d1d86744fbf29fa844 100644 (file)
@@ -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,
index c69c4dbb5f57753ffd737d2dc753b424a9e4bfab..839ff3963381dbd6f188707789a0e5cae63f660e 100644 (file)
@@ -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' &&
index b95aabc1101316abd0914f1e41dbbfedfc30041f..436934f59491323c9f1547ce4fd6f6eff6ed4dab 100644 (file)
@@ -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++;
index 8abfe44d30d5df87e6a606a109aecde61bbcd2a5..b33f840de793c9672155a7e7c6a4bdf507480938 100644 (file)
@@ -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;
index 4098d8fb840cc60209daed68156151961b7899a3..ab4736428de2a75028e2ef55fa2a40513e29efd9 100644 (file)
@@ -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)
index c888b9e19513bb80aa34d83b4af59a2b4f98959e..07cecb711f6d98deb71687455d96e96981b5c675 100644 (file)
@@ -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 == '\\') {
index d368bd7c80b2c0c302bb1e46e8f6ad4c898660b9..aa1d8496a788e848f50b5d8f0c12a07b7cad01fc 100644 (file)
@@ -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);
 }
index 671987b766b52e21272cd1693b77d99343f3b5af..91fccb1988997e22f8a5bccaf2dcc5a742b33853 100644 (file)
@@ -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;
index cd4f5ad2fcf98803fc870f935815c875a36a2b1d..4b802ebc2b5fe9193503a80ade1d292a1306cdbf 100644 (file)
@@ -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: "
index 529bd754431dfedfee16e14128e1febff3707710..4f2aa7fb9237631c4180ad47024a209f43d8d457 100644 (file)
@@ -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;
 }
index 8d615a0428f255380ce5c7ca605fb93bd9ce5f64..c7dfed676023b51ed13bc49d020df4b2a8a02317 100644 (file)
@@ -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;
        }
index 5eebbd2c4a3b7dd83b3920aa0a0a6a2c5ff59b0b..643746f5004df809b300300e46a87908b0a57b8a 100644 (file)
@@ -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 = &regs[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;
        }
 
index 0e99d19fe72b3b5e192ec65a3140a9a18f847657..e5d8f9cd93c7c019345ae1b9097da01597bb3f42 100644 (file)
@@ -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)
index 335f48d29d15ece02887b62fd53a1637ae38ace6..f9a8944eef6e633729041609090bf2c0ceb44d1d 100644 (file)
@@ -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);
 
index aa8f62ab373912c5705b70fb9ce0d50401f3412c..d24857d18b98882e22f179c087e599dbde94e548 100644 (file)
@@ -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);
 
index 5805c9b30d89d6ee3f4e356960c319ad7df2c215..ccb1c6af6cf7ad2df21edb566cdc5bc4dc11fbd0 100644 (file)
@@ -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;
index 5e743d05f834263fe25a8b6da5c05b6d84dabf6f..42b9ff2fa2b48c85ff19b7583aaf6943f5818e4b 100644 (file)
@@ -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);
 
index 26fdeac1755bc4f5378b0460f547c4d1013f8fde..87bf128e958e698d6b286314127d671d1bf477c1 100644 (file)
@@ -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')
index 32da9b0140ca05f0332a24cb953ebbcc48e554d5..2f72ea74bfc4540a209c1b71b31a60bdd196e90f 100644 (file)
@@ -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')
index 0042991de2ec98d03303379bac3887302860dd74..99baa28064de34ea334858302fd3bb18c77d80e2 100644 (file)
@@ -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.
 
index c76d5b8c10d56eedc0406b52aef4718cfe01ddf2..7cf42abcb328b63510dc41dd5e56af3059c315bb 100644 (file)
@@ -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;
 }
index 0972fea392af08f4e10b7608a7dd24415f3126bc..0100e733ecbdfed50a0a3ace69bc3daf7eb49fb5 100644 (file)
@@ -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", ""));
index 926798bb3888b49962144276475edd351d06650c..f65226c85cdfc3f85bdb4ceea7200783f6c70494 100644 (file)
@@ -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);
        }
index 61616440d77b888bfd1c61568bb88dd7acde7bb7..1369a01b85eec184aadb532a13ec825a9efd8a42 100644 (file)
@@ -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);
                        }
                }
 
index f9e79df8dcd2f545a825326e100756316646b82d..4cbc143bc4dca7deca8889e032614605b4a141e6 100644 (file)
@@ -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) {
index 2e422ea54b77fe9c349e046d1dfd5d1a8cba6f0b..539050f199204781a3062eaca505c3c1c3ffa5f1 100644 (file)
@@ -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 ||
index e7cc2dbf06ab4d58d263dbfc14316dac68a625dc..2098006a015a4bada14920734b0f8017c134a5c3 100644 (file)
@@ -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;
index 0514dc736f9cd6074ac8043b2936a00b7c0a4951..ff6b551255f3ea9d314c129acbca106a422c6017 100644 (file)
@@ -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
index ab03076e03a2e78dd4ea010748cc4af1be70ec21..cda1de1698f2808b5a2a980d6fa91ce8ed83ba91 100644 (file)
@@ -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) {
index 58997843303c92428d11d3ed68de637ddc397fb5..ad8568de7bfed8e22f6d2045c5c1640b58994027 100644 (file)
@@ -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);
index 87e1628cc6a216d87aa323c0f3e2040d74c930cc..ab602a92e9aa476b9e7475b5426dfbe6ae620af7 100644 (file)
@@ -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;
index 7db0cb42623339136b15253d52da106acf3cc7ec..54ec0c0da70c44e5eca39292743e6cfddca98746 100644 (file)
@@ -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;
 }
index 95ce369cf75f27554a783015218fbf25dc6d1103..e9ff3262c57ccfc02c76fe58ff67c436780d0a95 100644 (file)
@@ -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;
index 3d6d8e51e5f32e278590d993db39ebde7605952c..c972551bbf2e8aebaf38b04af238105b66cc5671 100644 (file)
@@ -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;
 }
 
index 91674640c19b626f3e428c96fc1163c0699e99fb..78c40bfa39adaf9141582d7adfdec225562cd260 100644 (file)
@@ -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;
                }
index 6ae4621dc710dab52bc30e858f99287800e0c8f3..e97658e590fcf09abdab90922ace45427385d9ac 100644 (file)
@@ -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");