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.
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,
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",
static void auth_client_input(struct auth_client_connection *conn)
{
+ const char *args;
char *line;
bool ret;
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);
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;
}
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 "
static void master_input(struct auth_master_connection *conn)
{
+ const char *args;
char *line;
bool ret;
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 "
} 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;
const char *name, const char *value,
const char *default_scheme)
{
+ const char *suffix;
size_t name_len = strlen(name);
i_assert(*name != '\0');
} 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)
"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. */
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;
}
/* 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;
}
bool user_given = FALSE;
- const char *error;
+ const char *value, *error;
const char *username;
const char *const *ptr;
/* split the data from ^A */
}
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;
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");
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 */
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;
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);
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);
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) {
"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);
}
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);
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) {
} 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]);
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, '$');
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 = "";
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;
}
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) {
"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 {
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);
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);
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;
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;
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, ' ');
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 {
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) {
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;
}
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;
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 &&
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 {
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",
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) {
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;
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) ||
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;
/* 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;
}
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);
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 = "";
{
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 */
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)
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;
if ((field = fetch_field_find(name)) != NULL) {
ctx->wanted_fields |= field->wanted_fields;
array_push_back(&ctx->fields, field);
- } else if (str_begins(name, "hdr.")) {
- name += 4;
+ } else if (str_begins(name, "hdr.", &name)) {
hdr_field.name = name;
array_push_back(&ctx->fields, &hdr_field);
name = t_strcut(name, '.');
array_push_back(&ctx->header_fields, &name);
- } else if (str_begins(name, "body.") ||
- str_begins(name, "binary.")) {
- bool binary = str_begins(name, "binary.");
+ } else if (str_begins(name, "body.", §ion) ||
+ str_begins(name, "binary.", §ion)) {
body_field.name = t_strarray_join(t_strsplit(name, ","), " ");
- name += binary ? 7 : 5;
- if (imap_msgpart_parse(name, &msgpart) < 0) {
+ if (imap_msgpart_parse(section, &msgpart) < 0) {
print_fetch_fields();
- i_fatal("Unknown fetch section: %s", name);
+ i_fatal("Unknown fetch section: %s", section);
}
array_push_back(&ctx->fields, &body_field);
ctx->wanted_fields |= imap_msgpart_get_fetch_data(msgpart);
{
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 = "";
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;
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);
}
}
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' ||
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 &&
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 */
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;
- }
}
}
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;
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,
}
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;
string_t *str;
const unsigned char *data;
size_t data_len;
- const char *error;
+ const char *suffix, *error;
int ret;
i_assert(!client->destroyed);
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);
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;
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) {
{
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)) {
i++;
else {
/* see if one is a subtree of the other */
- cur_len = strlen(names[i]);
- if (str_begins(name, names[i]) &&
- names[i][cur_len] == ns_sep) {
+ if (str_begins(name, names[i], &suffix) &&
+ suffix[0] == ns_sep) {
/* already matched in this subtree */
return;
}
- if (str_begins(names[i], name) &&
- names[i][name_len] == ns_sep) {
+ if (str_begins(names[i], name, &suffix) &&
+ suffix[0] == ns_sep) {
/* we're adding a parent, remove the child */
array_delete(¬ify_boxes->names, i, 1);
names = array_get(¬ify_boxes->names, &count);
{
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))
/* 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;
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 '['";
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 != '[') {
const char *vname)
{
struct mailbox *box;
- const char *name;
- size_t name_len;
+ const char *name, *suffix;
char ns_sep;
bool ret;
case IMAP_NOTIFY_TYPE_SUBTREE:
ns_sep = mail_namespace_get_sep(notify_ns->ns);
array_foreach_elem(¬ify_boxes->names, name) {
- name_len = strlen(name);
- if (name_len == 0) {
+ if (name[0] == 0) {
/* everything under root. NOTIFY spec itself
doesn't define this, but we use it for
implementing "personal" */
return TRUE;
}
- if (str_begins(vname, name) &&
- (vname[name_len] == '\0' ||
- vname[name_len] == ns_sep))
+ if (str_begins(vname, name, &suffix) &&
+ (suffix[0] == '\0' || suffix[0] == ns_sep))
return TRUE;
}
break;
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 &&
/* 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(
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,
}
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);
}
void *context)
{
struct auth_master_lookup_ctx *ctx = context;
+ const char *value;
unsigned int i, len;
io_loop_stop(ctx->conn->ioloop);
/* 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;
}
}
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 {
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-----"))
struct setting_parser_ctx *ctx)
{
struct dict_sql_map_field *field;
- size_t value_len;
switch (ctx->type) {
case SECTION_ROOT:
}
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);
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,
{
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;
}
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) {
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);
}
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);
{
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();
}
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 =
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.");
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) {
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 {
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;
}
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;
}
/* 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 {
struct imap_msgpart *msgpart;
pool_t pool;
unsigned int i;
+ const char *suffix;
bool next_digit;
int ret;
/* 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;
}
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 == ' ')
/* 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);
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;
}
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;
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++;
}
}
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);
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);
}
}
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);
}
}
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')
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,
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;
}
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);
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;
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) {
}
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;
}
DIR *dir;
struct dirent *d;
string_t *path;
+ const char *suffix;
unsigned int file_id;
size_t dir_len;
int ret = 0;
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);
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",
{
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 {
{
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;
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;
}
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,
{
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' &&
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);
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++;
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;
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;
/* 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)
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 == '\\') {
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);
}
{
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;
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;
{
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;
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: "
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;
}
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;
}
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;
}
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;
}
regs = array_get(&mailbox_internal_attributes, &count);
for (j = i; j > 0; j--) {
const struct mailbox_attribute_internal *attr = ®s[j-1];
+ const char *suffix;
if ((attr->flags & MAIL_ATTRIBUTE_INTERNAL_FLAG_CHILDREN) == 0 ||
- !str_begins(bare_prefix, attr->key))
+ !str_begins(bare_prefix, attr->key, &suffix))
break;
/* For example: bare_prefix="foo/bar" and attr->key="foo/", so
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;
}
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] == '/')
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;
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 == '~') {
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 &&
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;
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) {
const char **name)
{
const char *root_dir, *path, *mailbox_name;
- size_t len;
if (!list->mail_set->mail_full_filesystem_access)
return FALSE;
/* 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)
/* 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);
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);
/* 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);
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);
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;
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);
{
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);
}
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')
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')
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)
{
# 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.
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;
}
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", ""));
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);
}
}
{
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;
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);
}
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;
}
const char *const *args, void *context)
{
struct client *client = context;
+ const char *value;
unsigned int i;
bool nologin;
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);
}
}
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) {
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 ||
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, ":");
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;
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
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) {
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 = "";
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);
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;
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));
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;
}
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, ':');
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;
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;
}
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);
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,
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) {
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;
}
*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");