From: Timo Sirainen Date: Mon, 21 Nov 2016 14:44:38 +0000 (+0200) Subject: dict-client: Code cleanup - handle tab-unescaping before callbacks. X-Git-Tag: 2.3.0.rc1~2562 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fc494f157828dee9bb9885dd3630e9b7b45cdb25;p=thirdparty%2Fdovecot%2Fcore.git dict-client: Code cleanup - handle tab-unescaping before callbacks. --- diff --git a/src/lib-dict/dict-client.c b/src/lib-dict/dict-client.c index 9708a836ce..cb0c725c59 100644 --- a/src/lib-dict/dict-client.c +++ b/src/lib-dict/dict-client.c @@ -44,7 +44,8 @@ struct client_dict_cmd { bool background; void (*callback)(struct client_dict_cmd *cmd, - const char *line, const char *error, + enum dict_protocol_reply reply, const char *value, + const char *const *extra_args, const char *error, bool disconnected); struct client_dict_iterate_context *iter; struct client_dict_transaction_context *trans; @@ -183,8 +184,20 @@ static void dict_post_api_callback(struct client_dict *dict) static bool dict_cmd_callback_line(struct client_dict_cmd *cmd, const char *line) { + const char *const *args = t_strsplit_tabescaped(line); + const char *value = args[0]; + enum dict_protocol_reply reply; + + if (value == NULL) { + /* "" is a valid iteration reply */ + reply = DICT_PROTOCOL_REPLY_ITER_FINISHED; + } else { + reply = value[0]; + value++; + args++; + } cmd->unfinished = FALSE; - cmd->callback(cmd, line, NULL, FALSE); + cmd->callback(cmd, reply, value, args, NULL, FALSE); return !cmd->unfinished; } @@ -192,9 +205,13 @@ static void dict_cmd_callback_error(struct client_dict_cmd *cmd, const char *error, bool disconnected) { + const char *null_arg = NULL; + cmd->unfinished = FALSE; - if (cmd->callback != NULL) - cmd->callback(cmd, NULL, error, disconnected); + if (cmd->callback != NULL) { + cmd->callback(cmd, DICT_PROTOCOL_REPLY_ERROR, + "", &null_arg, error, disconnected); + } i_assert(!cmd->unfinished); } @@ -750,8 +767,12 @@ static const char *dict_warnings_sec(const struct client_dict_cmd *cmd, int msec } static void -client_dict_lookup_async_callback(struct client_dict_cmd *cmd, const char *line, - const char *error, bool disconnected ATTR_UNUSED) +client_dict_lookup_async_callback(struct client_dict_cmd *cmd, + enum dict_protocol_reply reply, + const char *value, + const char *const *extra_args ATTR_UNUSED, + const char *error, + bool disconnected ATTR_UNUSED) { struct client_dict *dict = cmd->dict; struct dict_lookup_result result; @@ -760,24 +781,24 @@ client_dict_lookup_async_callback(struct client_dict_cmd *cmd, const char *line, if (error != NULL) { result.ret = -1; result.error = error; - } else switch (*line) { + } else switch (reply) { case DICT_PROTOCOL_REPLY_OK: - result.value = t_str_tabunescape(line + 1); + result.value = value + 1; result.ret = 1; break; case DICT_PROTOCOL_REPLY_NOTFOUND: result.ret = 0; break; case DICT_PROTOCOL_REPLY_FAIL: - result.error = line[1] == '\0' ? "dict-server returned failure" : + result.error = value[0] == '\0' ? "dict-server returned failure" : t_strdup_printf("dict-server returned failure: %s", - t_str_tabunescape(line+1)); + value); result.ret = -1; break; default: result.error = t_strdup_printf( - "dict-client: Invalid lookup '%s' reply: %s", - cmd->query, line); + "dict-client: Invalid lookup '%s' reply: %c%s", + cmd->query, reply, value); client_dict_disconnect(dict, result.error); result.ret = -1; break; @@ -910,13 +931,17 @@ client_dict_iter_api_callback(struct client_dict_iterate_context *ctx, } static void -client_dict_iter_async_callback(struct client_dict_cmd *cmd, const char *line, - const char *error, bool disconnected ATTR_UNUSED) +client_dict_iter_async_callback(struct client_dict_cmd *cmd, + enum dict_protocol_reply reply, + const char *value, + const char *const *extra_args, + const char *error, + bool disconnected ATTR_UNUSED) { struct client_dict_iterate_context *ctx = cmd->iter; struct client_dict *dict = cmd->dict; struct client_dict_iter_result *result; - const char *key = NULL, *value = NULL; + const char *iter_key = NULL, *iter_value = NULL; if (ctx->deinit) { cmd->background = TRUE; @@ -925,8 +950,8 @@ client_dict_iter_async_callback(struct client_dict_cmd *cmd, const char *line, if (error != NULL) { /* failed */ - } else switch (*line) { - case '\0': + } else switch (reply) { + case DICT_PROTOCOL_REPLY_ITER_FINISHED: /* end of iteration */ ctx->finished = TRUE; client_dict_iter_api_callback(ctx, cmd); @@ -934,19 +959,19 @@ client_dict_iter_async_callback(struct client_dict_cmd *cmd, const char *line, return; case DICT_PROTOCOL_REPLY_OK: /* key \t value */ - key = line+1; - value = strchr(key, '\t'); + iter_key = value; + iter_value = extra_args[0]; break; case DICT_PROTOCOL_REPLY_FAIL: - error = t_strdup_printf("dict-server returned failure: %s", line+1); + error = t_strdup_printf("dict-server returned failure: %s", value); break; default: break; } - if (value == NULL && error == NULL) { + if (iter_value == NULL && error == NULL) { /* broken protocol */ - error = t_strdup_printf("dict client (%s) sent broken iterate reply: %s", - dict->conn.conn.name, line); + error = t_strdup_printf("dict client (%s) sent broken iterate reply: %c%s", + dict->conn.conn.name, reply, value); client_dict_disconnect(dict, error); } @@ -965,13 +990,9 @@ client_dict_iter_async_callback(struct client_dict_cmd *cmd, const char *line, return; } - if (value != NULL) - key = t_strdup_until(key, value++); - else - value = ""; result = array_append_space(&ctx->results); - result->key = p_strdup(ctx->results_pool, t_str_tabunescape(key)); - result->value = p_strdup(ctx->results_pool, t_str_tabunescape(value)); + result->key = p_strdup(ctx->results_pool, iter_key); + result->value = p_strdup(ctx->results_pool, iter_value); client_dict_iter_api_callback(ctx, cmd); } @@ -1102,8 +1123,10 @@ client_dict_transaction_free(struct client_dict_transaction_context **_ctx) static void client_dict_transaction_commit_callback(struct client_dict_cmd *cmd, - const char *line, const char *error, - bool disconnected) + enum dict_protocol_reply reply, + const char *value, + const char *const *extra_args, + const char *error, bool disconnected) { struct client_dict *dict = cmd->dict; struct dict_commit_result result = { @@ -1117,7 +1140,7 @@ client_dict_transaction_commit_callback(struct client_dict_cmd *cmd, if (disconnected) result.ret = DICT_COMMIT_RET_WRITE_UNCERTAIN; result.error = error; - } else switch (*line) { + } else switch (reply) { case DICT_PROTOCOL_REPLY_OK: result.ret = DICT_COMMIT_RET_OK; break; @@ -1128,7 +1151,7 @@ client_dict_transaction_commit_callback(struct client_dict_cmd *cmd, result.ret = DICT_COMMIT_RET_WRITE_UNCERTAIN; /* fallthrough */ case DICT_PROTOCOL_REPLY_FAIL: { - const char *error = i_strchr_to_next(line+1, '\t'); + const char *error = extra_args[0]; result.error = t_strdup_printf("dict-server returned failure: %s", error != NULL ? t_str_tabunescape(error) : ""); @@ -1137,7 +1160,8 @@ client_dict_transaction_commit_callback(struct client_dict_cmd *cmd, default: result.ret = DICT_COMMIT_RET_FAILED; result.error = t_strdup_printf( - "dict-client: Invalid commit reply: %s", line); + "dict-client: Invalid commit reply: %c%s", + reply, value); client_dict_disconnect(dict, result.error); break; } diff --git a/src/lib-dict/dict-client.h b/src/lib-dict/dict-client.h index eb10b562b2..87e8fbd8d7 100644 --- a/src/lib-dict/dict-client.h +++ b/src/lib-dict/dict-client.h @@ -28,11 +28,14 @@ enum dict_protocol_cmd { }; enum dict_protocol_reply { + DICT_PROTOCOL_REPLY_ERROR = -1, + DICT_PROTOCOL_REPLY_OK = 'O', /* */ DICT_PROTOCOL_REPLY_NOTFOUND = 'N', DICT_PROTOCOL_REPLY_FAIL = 'F', DICT_PROTOCOL_REPLY_WRITE_UNCERTAIN = 'W', - DICT_PROTOCOL_REPLY_ASYNC_COMMIT = 'A' + DICT_PROTOCOL_REPLY_ASYNC_COMMIT = 'A', + DICT_PROTOCOL_REPLY_ITER_FINISHED = '\0', }; #endif