From d871f40b83c9d4f299ff41f88f4b5fd1984b7972 Mon Sep 17 00:00:00 2001 From: Ben Kibbey Date: Fri, 27 Mar 2015 20:51:48 -0400 Subject: [PATCH] Fix LIST showing non-existant element paths. If a user were to request a listing of the non-existant element path when a parent element of the path contained a permissions error, the original requested path would be shown in the list rather than stopping at the element with the error. --- src/commands.c | 20 ++++++----------- src/xml.c | 69 ++++++++++++++++++++++++++++++++++++++++++++-------------- src/xml.h | 1 + 3 files changed, 61 insertions(+), 29 deletions(-) diff --git a/src/commands.c b/src/commands.c index 25560386..5ae94960 100644 --- a/src/commands.c +++ b/src/commands.c @@ -1670,22 +1670,16 @@ list_path_once (struct client_s *client, char *line, { int total = slist_length (elements->list); - if (!total) - rc = GPG_ERR_NO_DATA; - - if (!rc) + if (total) { - if (!rc) - { - int i; + int i; - for (i = 0; i < total; i++) - { - char *tmp = slist_nth_data (elements->list, i); + for (i = 0; i < total; i++) + { + char *tmp = slist_nth_data (elements->list, i); - string_append_printf (result, "%s%s", tmp, - i + 1 == total ? "" : "\n"); - } + string_append_printf (result, "%s%s", tmp, + i + 1 == total ? "" : "\n"); } } else diff --git a/src/xml.c b/src/xml.c index 2431194d..67576049 100644 --- a/src/xml.c +++ b/src/xml.c @@ -1032,14 +1032,13 @@ find_elements (struct client_s *client, xmlDocPtr doc, xmlNodePtr node, if (!n) { + if (!*rc) + *rc = GPG_ERR_ELEMENT_NOT_FOUND; + if (not_found_fn) return not_found_fn (client, 0, found ? last_node : last_node->parent, p, rc, data); - - if (!*rc) - *rc = GPG_ERR_ELEMENT_NOT_FOUND; - return NULL; } @@ -1096,13 +1095,15 @@ find_elements (struct client_s *client, xmlDocPtr doc, xmlNodePtr node, xmlFree (content); tmp = find_root_element (client, doc, &nreq, rc, target, 0, 0); - if (!tmp) { strv_free (nreq); - return NULL; + if (not_found_fn && *rc == GPG_ERR_EACCES) + return not_found_fn (client, 0, NULL, p, rc, data); + return NULL; } + if (found_fn) { found_fn (client, tmp, nreq, rc, p + 1, data); @@ -1505,6 +1506,19 @@ add_attribute (struct client_s *client, xmlNodePtr node, const char *name, return rc; } +static xmlNodePtr +list_not_found_cb (struct client_s *client, int i, xmlNodePtr node, + char **req, gpg_error_t *rc, void *data) +{ + struct element_list_s *elements = data; + + if (*rc != GPG_ERR_EACCES) + return NULL; + + elements->data = req; + return NULL; +} + /* * From the element path 'path', find sub-nodes and append them to the list. */ @@ -1516,6 +1530,7 @@ create_path_list (struct client_s *client, xmlDocPtr doc, char **req, **req_orig; xmlNodePtr n; int a_target = 0; + int root_only = 0; req = str_split (path, "\t", 0); if (!req) @@ -1539,12 +1554,17 @@ create_path_list (struct client_s *client, xmlDocPtr doc, { if (rc != GPG_ERR_EACCES) rc = 0; + else + root_only = 1; goto done; } if (rc == GPG_ERR_EACCES) - goto done; + { + root_only = 1; + goto done; + } if (!n && rc == GPG_ERR_ELEMENT_NOT_FOUND && elements->resolving == 1) { @@ -1564,16 +1584,14 @@ create_path_list (struct client_s *client, xmlDocPtr doc, { int e_target = 0; - n = - find_elements (client, doc, n->children, req + 1, &rc, &e_target, - NULL, NULL, 1, 0, NULL, 0); - + n = find_elements (client, doc, n->children, req + 1, &rc, &e_target, + NULL, list_not_found_cb, 1, 0, elements, 0); if (!n && rc == GPG_ERR_ELEMENT_NOT_FOUND && elements->resolving == 1) { rc = 0; goto fail; } - else if (!n) + else if (!n && rc && rc != GPG_ERR_EACCES) goto fail; } @@ -1588,7 +1606,28 @@ done: * client isn't human because child elements are prefixed for the * current path. But may be confusing if editing by hand. */ - elements->prefix = strv_join ("\t", req_orig); + if (elements->data) + { + /* This is needed to prune the original requested element path to the + * length of the failed element in the path. */ + int x = strv_length (req_orig)-strv_length ((char **)elements->data); + int i; + char **tmp = NULL; + + for (i = 0; i <= x; i++) + tmp = strv_cat (tmp, str_dup (req_orig[i])); + + elements->prefix = strv_join ("\t", tmp); + strv_free (tmp); + elements->data = NULL; + } + else + { + if (root_only) + elements->prefix = str_dup (*req_orig); + else + elements->prefix = strv_join ("\t", req_orig); + } if (!elements->prefix) { @@ -1643,9 +1682,7 @@ done: rc = path_list_recurse (client, doc, n ? n->children : n, elements); fail: - if (req_orig) - strv_free (req_orig); - + strv_free (req_orig); strv_free (req); return rc; } diff --git a/src/xml.h b/src/xml.h index e37d12bd..0bab487f 100644 --- a/src/xml.h +++ b/src/xml.h @@ -38,6 +38,7 @@ struct element_list_s int verbose; int with_target; char **req; + void *data; }; gpg_error_t new_root_element (struct client_s *, xmlDocPtr doc, char *name); -- 2.11.4.GIT