David Lutterkort e24587
commit ea010d85e796dc979cdfacc91bc1d06a8c6dac7c
David Lutterkort e24587
Author: David Lutterkort <lutter@redhat.com>
David Lutterkort e24587
Date:   Fri Apr 29 14:32:13 2011 -0700
David Lutterkort e24587
David Lutterkort e24587
    path expressions: allow whitespace inside names
David Lutterkort e24587
    
David Lutterkort e24587
    This makes the path expression '/files/etc/foo bar/baz' legal, i.e. it is
David Lutterkort e24587
    no longer necessary to escape whitespace in path expressions.
David Lutterkort e24587
    
David Lutterkort e24587
    Fixes BZ 700608
David Lutterkort e24587
David Lutterkort e24587
diff --git a/doc/xpath.txt b/doc/xpath.txt
David Lutterkort e24587
index cd12ebe..a609003 100644
David Lutterkort e24587
--- a/doc/xpath.txt
David Lutterkort e24587
+++ b/doc/xpath.txt
David Lutterkort e24587
@@ -133,7 +133,10 @@ UnionExpr ::= PathExpr ("|" PathExpr)*
David Lutterkort e24587
 
David Lutterkort e24587
 Literal ::= '"' /[^"]* / '"' | "'" /[^']* / "'"
David Lutterkort e24587
 Number       ::= /[0-9]+/
David Lutterkort e24587
-Name ::= /([^][/\= \t\n]|\\.)+/
David Lutterkort e24587
+/* Names can contain whitespace in the interior */
David Lutterkort e24587
+NameNoWS ::= [^][|/\= \t\n] | \\.
David Lutterkort e24587
+NameWS   ::= [^][|/\=] | \\.
David Lutterkort e24587
+Name ::= NameNoWS NameWS* NameNoWS | NameNoWS
David Lutterkort e24587
 
David Lutterkort e24587
 VariableReference ::= '$' /[a-zA-Z_][a-zA-Z0-9_]*/
David Lutterkort e24587
 
David Lutterkort e24587
diff --git a/src/pathx.c b/src/pathx.c
David Lutterkort e24587
index a4cdf48..acd4eb0 100644
David Lutterkort e24587
--- a/src/pathx.c
David Lutterkort e24587
+++ b/src/pathx.c
David Lutterkort e24587
@@ -1374,17 +1374,16 @@ static void push_new_binary_op(enum binary_op op, struct state *state) {
David Lutterkort e24587
 }
David Lutterkort e24587
 
David Lutterkort e24587
 /*
David Lutterkort e24587
- * Name ::= /[^][/=) \t\n]+/
David Lutterkort e24587
+ * NameNoWS ::= [^][|/\= \t\n] | \\.
David Lutterkort e24587
+ * NameWS   ::= [^][|/\=] | \\.
David Lutterkort e24587
+ * Name ::= NameNoWS NameWS* NameNoWS | NameNoWS
David Lutterkort e24587
  */
David Lutterkort e24587
 static char *parse_name(struct state *state) {
David Lutterkort e24587
+    static const char const follow[] = "][|/=()";
David Lutterkort e24587
     const char *s = state->pos;
David Lutterkort e24587
     char *result;
David Lutterkort e24587
 
David Lutterkort e24587
-    while (*state->pos != '\0' &&
David Lutterkort e24587
-           *state->pos != L_BRACK && *state->pos != SEP &&
David Lutterkort e24587
-           *state->pos != R_BRACK && *state->pos != '=' &&
David Lutterkort e24587
-           *state->pos != ')' &&
David Lutterkort e24587
-           !isspace(*state->pos)) {
David Lutterkort e24587
+    while (*state->pos != '\0' && strchr(follow, *state->pos) == NULL) {
David Lutterkort e24587
         if (*state->pos == '\\') {
David Lutterkort e24587
             state->pos += 1;
David Lutterkort e24587
             if (*state->pos == '\0') {
David Lutterkort e24587
@@ -1395,6 +1394,14 @@ static char *parse_name(struct state *state) {
David Lutterkort e24587
         state->pos += 1;
David Lutterkort e24587
     }
David Lutterkort e24587
 
David Lutterkort e24587
+    /* Strip trailing white space */
David Lutterkort e24587
+    if (state->pos > s) {
David Lutterkort e24587
+        state->pos -= 1;
David Lutterkort e24587
+        while (isspace(*state->pos) && state->pos >= s)
David Lutterkort e24587
+            state->pos -= 1;
David Lutterkort e24587
+        state->pos += 1;
David Lutterkort e24587
+    }
David Lutterkort e24587
+
David Lutterkort e24587
     if (state->pos == s) {
David Lutterkort e24587
         STATE_ERROR(state, PATHX_ENAME);
David Lutterkort e24587
         return NULL;
David Lutterkort e24587
diff --git a/tests/test-xpath.c b/tests/test-xpath.c
David Lutterkort e24587
index 3a3d241..c990364 100644
David Lutterkort e24587
--- a/tests/test-xpath.c
David Lutterkort e24587
+++ b/tests/test-xpath.c
David Lutterkort e24587
@@ -78,6 +78,19 @@ static char *token_to_eol(char *s, char **tok) {
David Lutterkort e24587
     return s;
David Lutterkort e24587
 }
David Lutterkort e24587
 
David Lutterkort e24587
+static char *findpath(char *s, char **p) {
David Lutterkort e24587
+    char *t = skipws(s);
David Lutterkort e24587
+
David Lutterkort e24587
+    while (*s && *s != '=') s++;
David Lutterkort e24587
+    if (s > t) {
David Lutterkort e24587
+        s -= 1;
David Lutterkort e24587
+        while (*s && isspace(*s)) s -= 1;
David Lutterkort e24587
+        s += 1;
David Lutterkort e24587
+    }
David Lutterkort e24587
+    *p = strndup(t, s - t);
David Lutterkort e24587
+    return s;
David Lutterkort e24587
+}
David Lutterkort e24587
+
David Lutterkort e24587
 static struct test *read_tests(void) {
David Lutterkort e24587
     char *fname;
David Lutterkort e24587
     FILE *fp;
David Lutterkort e24587
@@ -107,7 +120,7 @@ static struct test *read_tests(void) {
David Lutterkort e24587
             if (ALLOC(e) < 0)
David Lutterkort e24587
                 die("out of memory");
David Lutterkort e24587
             list_append(t->entries, e);
David Lutterkort e24587
-            s = token(s, &(e->path));
David Lutterkort e24587
+            s = findpath(s, &(e->path));
David Lutterkort e24587
             s = skipws(s);
David Lutterkort e24587
             if (*s) {
David Lutterkort e24587
                 if (*s != '=') {
David Lutterkort e24587
@@ -318,6 +331,9 @@ static int run_tests(struct test *tests) {
David Lutterkort e24587
     r = aug_defvar(aug, "localhost", "'127.0.0.1'");
David Lutterkort e24587
     if (r != 0)
David Lutterkort e24587
         die("aug_defvar $localhost");
David Lutterkort e24587
+    r = aug_defvar(aug, "php", "/files/etc/php.ini");
David Lutterkort e24587
+    if (r != 1)
David Lutterkort e24587
+        die("aug_defvar $php");
David Lutterkort e24587
 
David Lutterkort e24587
     list_for_each(t, tests) {
David Lutterkort e24587
         if (run_one_test(aug, t) < 0)
David Lutterkort e24587
diff --git a/tests/xpath.tests b/tests/xpath.tests
David Lutterkort e24587
index b16792a..cd1909c 100644
David Lutterkort e24587
--- a/tests/xpath.tests
David Lutterkort e24587
+++ b/tests/xpath.tests
David Lutterkort e24587
@@ -16,7 +16,9 @@
David Lutterkort e24587
 # results listed in the test
David Lutterkort e24587
 #
David Lutterkort e24587
 # The test framework sets up variables:
David Lutterkort e24587
-#   hosts   /files/etc/hosts/*
David Lutterkort e24587
+#   hosts      /files/etc/hosts/*
David Lutterkort e24587
+#   localhost  '127.0.0.1'
David Lutterkort e24587
+#   php        /files/etc/php.ini
David Lutterkort e24587
 
David Lutterkort e24587
 # Very simple to warm up
David Lutterkort e24587
 test wildcard /files/etc/hosts/*/ipaddr
David Lutterkort e24587
@@ -235,3 +237,19 @@ test union (/files/etc/yum.conf | /files/etc/yum.repos.d/*)/*/gpgcheck
David Lutterkort e24587
      /files/etc/yum.repos.d/fedora.repo/fedora-source/gpgcheck = 1
David Lutterkort e24587
      /files/etc/yum.repos.d/remi.repo/remi/gpgcheck = 1
David Lutterkort e24587
      /files/etc/yum.repos.d/remi.repo/remi-test/gpgcheck = 1
David Lutterkort e24587
+
David Lutterkort e24587
+# Paths with whitespace in them
David Lutterkort e24587
+test php1 $php/mail function
David Lutterkort e24587
+     /files/etc/php.ini/mail function
David Lutterkort e24587
+
David Lutterkort e24587
+test php2 $php[mail function]
David Lutterkort e24587
+     /files/etc/php.ini
David Lutterkort e24587
+
David Lutterkort e24587
+test php3 $php[count(mail function) = 1]
David Lutterkort e24587
+     /files/etc/php.ini
David Lutterkort e24587
+
David Lutterkort e24587
+test php4 $php/mail function/SMTP
David Lutterkort e24587
+     /files/etc/php.ini/mail function/SMTP = localhost
David Lutterkort e24587
+
David Lutterkort e24587
+test php5 $php/mail\ function
David Lutterkort e24587
+     /files/etc/php.ini/mail function