]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
dict-client: Code cleanup - handle tab-unescaping before callbacks.
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Mon, 21 Nov 2016 14:44:38 +0000 (16:44 +0200)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Mon, 21 Nov 2016 20:08:57 +0000 (22:08 +0200)
src/lib-dict/dict-client.c
src/lib-dict/dict-client.h

index 9708a836ce9cd2bb68a36f88fa625b96216f91ad..cb0c725c59c0a08200dba155b1e8ae7390a2dfc4 100644 (file)
@@ -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;
        }
index eb10b562b26a1478457fd5a0f48061b95475f301..87e8fbd8d700a2982d8528988a894a573371aa4e 100644 (file)
@@ -28,11 +28,14 @@ enum dict_protocol_cmd {
 };
 
 enum dict_protocol_reply {
+       DICT_PROTOCOL_REPLY_ERROR = -1,
+
        DICT_PROTOCOL_REPLY_OK = 'O', /* <value> */
        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