[gxml] CssSelectorParser: improve attribute pasing



commit a93bd5b35b4b5c0492f3579b67213dac2a633f2c
Author: Yannick Inizan <inizan yannick gmail com>
Date:   Fri Sep 29 09:21:52 2017 -0700

    CssSelectorParser: improve attribute pasing
    
    Fixes bug:
    
    https://bugzilla.gnome.org/show_bug.cgi?id=788129

 gxml/CssSelectorParser.vala |   34 +++++++++---
 test/CssSelectorTest.vala   |  122 +++++++++++++++++++++++++++----------------
 2 files changed, 102 insertions(+), 54 deletions(-)
---
diff --git a/gxml/CssSelectorParser.vala b/gxml/CssSelectorParser.vala
index b8a3e1a..12d78ca 100644
--- a/gxml/CssSelectorParser.vala
+++ b/gxml/CssSelectorParser.vala
@@ -73,6 +73,20 @@ public class GXml.CssSelectorParser : GLib.Object {
                list = new Gee.ArrayList<CssSelectorData?>();
        }
 
+       static bool is_valid_identifier (string data) {
+               unichar u = 0;
+               int index = 0;
+               while (data.get_next_char (ref index, out u))
+                       if (u == '[' || u == ']' || u == '{' || u == '}' ||
+                               u == '$' || u == '&' || u == '#' || u == '|' ||
+                               u == '`' || u == '^' || u == '@' || u == '+' ||
+                               u == '~' || u == '*' || u == '%' || u == '!' ||
+                               u == '?' || u == '<' || u == '>' || u == '"' ||
+                               u == '\'')
+                                       return false;
+               return true;
+       }
+
        void parse_class (string css, ref int position) {
                CssSelectorData idata = new CssSelectorData.with_values (CssSelectorType.INSIDE, "", "");
                list.add (idata);
@@ -124,7 +138,7 @@ public class GXml.CssSelectorParser : GLib.Object {
                if (!u.isalnum())
                        throw new CssSelectorError.ATTRIBUTE (_("Invalid attribute character"));
                sb.append_unichar (u);
-               while (css.get_next_char (ref position, out u) && u.isalnum())
+               while (css.get_next_char (ref position, out u) && (u.isalnum() || u == '-'))
                        sb.append_unichar (u);
                while (u.isspace())
                        css.get_next_char (ref position, out u);
@@ -143,11 +157,12 @@ public class GXml.CssSelectorParser : GLib.Object {
                                s = u;
                                css.get_next_char (ref position, out u);
                        }
-                       if (!u.isalnum())
-                               throw new CssSelectorError.ATTRIBUTE (_("Invalid attribute selector 
character"));
-                       sb1.append_unichar (u);
-                       while (css.get_next_char (ref position, out u) && (u.isalnum() || u.isspace()))
+                       if (s != 0 || is_valid_identifier (u.to_string()))
+                               sb1.append_unichar (u);
+                       while (css.get_next_char (ref position, out u) && (s != 0 ? u != s : u != ']'))
                                sb1.append_unichar (u);
+                       if (s == 0 && !is_valid_identifier (sb1.str))
+                               throw new CssSelectorError.ATTRIBUTE (_("Invalid attribute selector value : 
%s").printf (sb1.str));
                        if (s != 0) {
                                if (u != s)
                                        throw new CssSelectorError.STRING (_("Invalid end of attribute 
value"));
@@ -188,11 +203,12 @@ public class GXml.CssSelectorParser : GLib.Object {
                        s = u;
                        css.get_next_char (ref position, out u);
                }
-               if (!u.isalnum())
-                       throw new CssSelectorError.ATTRIBUTE (_("Invalid attribute selector character 2 
(%s)").printf (u.to_string()));
-               sb1.append_unichar (u);
-               while (css.get_next_char (ref position, out u) && (u.isalnum() || u.isspace()))
+               if (s != 0 || is_valid_identifier (u.to_string()))
+                       sb1.append_unichar (u);
+               while (css.get_next_char (ref position, out u) && (s != 0 ? u != s : u != ']'))
                        sb1.append_unichar (u);
+               if (s == 0 && !is_valid_identifier (sb1.str))
+                       throw new CssSelectorError.ATTRIBUTE (_("Invalid attribute selector value : 
%s").printf (sb1.str));
                if (s != 0) {
                        if (u != s)
                                throw new CssSelectorError.STRING (_("Invalid end of attribute value"));
diff --git a/test/CssSelectorTest.vala b/test/CssSelectorTest.vala
index bc49c1e..a008d29 100644
--- a/test/CssSelectorTest.vala
+++ b/test/CssSelectorTest.vala
@@ -65,7 +65,7 @@ class CssSelectorTest : GXmlTest {
                Test.add_func ("/gxml/css-selector/element/attribute/value", () => {
                        try {
                                var cp = new CssSelectorParser ();
-                               cp.parse ("child[prop]");
+                               cp.parse ("child[prop-name]");
                                assert (cp.selectors.size == 3);
                                var s = cp.selectors[0];
                                assert (s != null);
@@ -82,7 +82,7 @@ class CssSelectorTest : GXmlTest {
                                var c1 = d.create_element ("child");
                                r.append_child (c1);
                                var c2 = d.create_element ("child");
-                               c2.set_attribute ("prop", "val");
+                               c2.set_attribute ("prop-name", "val");
                                r.append_child (c2);
                                assert (!cp.match (r));
                                assert (!cp.match (c1));
@@ -94,7 +94,7 @@ class CssSelectorTest : GXmlTest {
                Test.add_func ("/gxml/css-selector/element/attribute/contains", () => {
                        try {
                                var cp = new CssSelectorParser ();
-                               cp.parse ("child[prop~=\"val\"]");
+                               cp.parse ("child[prop-name~=\"val\"]");
                                assert (cp.selectors.size == 3);
                                var s = cp.selectors[0];
                                assert (s != null);
@@ -111,13 +111,13 @@ class CssSelectorTest : GXmlTest {
                                var c1 = d.create_element ("child");
                                r.append_child (c1);
                                var c2 = d.create_element ("child");
-                               c2.set_attribute ("prop", "val calc soup");
+                               c2.set_attribute ("prop-name", "val calc soup");
                                r.append_child (c2);
                                var c3 = d.create_element ("child");
-                               c3.set_attribute ("prop", "calc val soup");
+                               c3.set_attribute ("prop-name", "calc val soup");
                                r.append_child (c3);
                                var c4 = d.create_element ("child");
-                               c4.set_attribute ("prop", "calc secondary soup");
+                               c4.set_attribute ("prop-name", "calc secondary soup");
                                r.append_child (c4);
                                assert (!cp.match (r));
                                assert (!cp.match (c1));
@@ -131,7 +131,7 @@ class CssSelectorTest : GXmlTest {
                Test.add_func ("/gxml/css-selector/element/attribute/starts_with", () => {
                        try {
                                var cp = new CssSelectorParser ();
-                               cp.parse ("child[prop^=\"val\"]");
+                               cp.parse ("child[prop-name^=\"val\"]");
                                assert (cp.selectors.size == 3);
                                var s = cp.selectors[0];
                                assert (s != null);
@@ -148,13 +148,13 @@ class CssSelectorTest : GXmlTest {
                                var c1 = d.create_element ("child");
                                r.append_child (c1);
                                var c2 = d.create_element ("child");
-                               c2.set_attribute ("prop", "val");
+                               c2.set_attribute ("prop-name", "val");
                                r.append_child (c2);
                                var c3 = d.create_element ("child");
-                               c3.set_attribute ("prop", "value");
+                               c3.set_attribute ("prop-name", "value");
                                r.append_child (c3);
                                var c4 = d.create_element ("child");
-                               c4.set_attribute ("prop", "secondaryvalue");
+                               c4.set_attribute ("prop-name", "secondaryvalue");
                                r.append_child (c4);
                                assert (!cp.match (r));
                                assert (!cp.match (c1));
@@ -168,7 +168,7 @@ class CssSelectorTest : GXmlTest {
                Test.add_func ("/gxml/css-selector/element/attribute/starts_with_hyphen", () => {
                        try {
                                var cp = new CssSelectorParser ();
-                               cp.parse ("child[prop|=\"val\"]");
+                               cp.parse ("child[prop-name|=\"val\"]");
                                assert (cp.selectors.size == 3);
                                var s = cp.selectors[0];
                                assert (s != null);
@@ -185,13 +185,13 @@ class CssSelectorTest : GXmlTest {
                                var c1 = d.create_element ("child");
                                r.append_child (c1);
                                var c2 = d.create_element ("child");
-                               c2.set_attribute ("prop", "val-");
+                               c2.set_attribute ("prop-name", "val-");
                                r.append_child (c2);
                                var c3 = d.create_element ("child");
-                               c3.set_attribute ("prop", "value");
+                               c3.set_attribute ("prop-name", "value");
                                r.append_child (c3);
                                var c4 = d.create_element ("child");
-                               c4.set_attribute ("prop", "secondaryvalue");
+                               c4.set_attribute ("prop-name", "secondaryvalue");
                                r.append_child (c4);
                                assert (!cp.match (r));
                                assert (!cp.match (c1));
@@ -205,7 +205,7 @@ class CssSelectorTest : GXmlTest {
                Test.add_func ("/gxml/css-selector/element/attribute/ends_with", () => {
                        try {
                                var cp = new CssSelectorParser ();
-                               cp.parse ("child[prop$=\"val\"]");
+                               cp.parse ("child[prop-name$=\"val\"]");
                                assert (cp.selectors.size == 3);
                                var s = cp.selectors[0];
                                assert (s != null);
@@ -222,13 +222,13 @@ class CssSelectorTest : GXmlTest {
                                var c1 = d.create_element ("child");
                                r.append_child (c1);
                                var c2 = d.create_element ("child");
-                               c2.set_attribute ("prop", "subval");
+                               c2.set_attribute ("prop-name", "subval");
                                r.append_child (c2);
                                var c3 = d.create_element ("child");
-                               c3.set_attribute ("prop", "techval");
+                               c3.set_attribute ("prop-name", "techval");
                                r.append_child (c3);
                                var c4 = d.create_element ("child");
-                               c4.set_attribute ("prop", "secondaryvalue");
+                               c4.set_attribute ("prop-name", "secondaryvalue");
                                r.append_child (c4);
                                assert (!cp.match (r));
                                assert (!cp.match (c1));
@@ -239,10 +239,42 @@ class CssSelectorTest : GXmlTest {
                                warning ("ERROR: "+e.message);
                        }
                });
+               Test.add_func ("/gxml/css-selector/element/attribute-value-unquoted", () => {
+                       try {
+                               var cp = new CssSelectorParser ();
+                               cp.parse ("child[prop-name=va7u3_unqu§ted]");
+                               assert (cp.selectors.size == 3);
+                               var s = cp.selectors[0];
+                               assert (s != null);
+                               assert (s.selector_type == CssSelectorType.ELEMENT);
+                               var si = cp.selectors[1];
+                               assert (si != null);
+                               assert (si.selector_type == CssSelectorType.INSIDE);
+                               var sa = cp.selectors[2];
+                               assert (sa != null);
+                               assert (sa.selector_type == CssSelectorType.ATTRIBUTE_EQUAL);
+                               var d = new GomDocument ();
+                               var r = d.create_element ("root");
+                               d.append_child (r);
+                               var c1 = d.create_element ("child");
+                               r.append_child (c1);
+                               var c2 = d.create_element ("child");
+                               c2.set_attribute ("prop-name", "t");
+                               var c3 = d.create_element ("child");
+                               c3.set_attribute ("prop-name", "va7u3_unqu§ted");
+                               r.append_child (c3);
+                               assert (!cp.match (r));
+                               assert (!cp.match (c1));
+                               assert (!cp.match (c2));
+                               assert (cp.match (c3));
+                       } catch (GLib.Error e){
+                               warning ("ERROR: "+e.message);
+                       }
+               });
                Test.add_func ("/gxml/css-selector/element/attribute-value", () => {
                        try {
                                var cp = new CssSelectorParser ();
-                               cp.parse ("child[prop=\"val\"]");
+                               cp.parse ("child[prop-name=\"val\"]");
                                assert (cp.selectors.size == 3);
                                var s = cp.selectors[0];
                                assert (s != null);
@@ -259,9 +291,9 @@ class CssSelectorTest : GXmlTest {
                                var c1 = d.create_element ("child");
                                r.append_child (c1);
                                var c2 = d.create_element ("child");
-                               c2.set_attribute ("prop", "t");
+                               c2.set_attribute ("prop-name", "t");
                                var c3 = d.create_element ("child");
-                               c3.set_attribute ("prop", "val");
+                               c3.set_attribute ("prop-name", "val");
                                r.append_child (c3);
                                assert (!cp.match (r));
                                assert (!cp.match (c1));
@@ -370,13 +402,13 @@ class CssSelectorTest : GXmlTest {
                                var c1 = d.create_element ("child");
                                r.append_child (c1);
                                var c2 = d.create_element ("child");
-                               c2.set_attribute ("prop", "subval");
+                               c2.set_attribute ("prop-name", "subval");
                                r.append_child (c2);
                                var c3 = d.create_element ("child");
-                               c3.set_attribute ("prop", "techval");
+                               c3.set_attribute ("prop-name", "techval");
                                r.append_child (c3);
                                var c4 = d.create_element ("child");
-                               c4.set_attribute ("prop", "secondaryvalue");
+                               c4.set_attribute ("prop-name", "secondaryvalue");
                                r.append_child (c4);
                                assert (cp.match (r));
                                assert (!cp.match (c1));
@@ -389,13 +421,13 @@ class CssSelectorTest : GXmlTest {
                                var c1g = d2.create_element ("child");
                                r2.append_child (c1g);
                                var c2g = d2.create_element ("child");
-                               c2g.set_attribute ("prop", "subval");
+                               c2g.set_attribute ("prop-name", "subval");
                                r2.append_child (c2g);
                                var c3g = d2.create_element ("child");
-                               c3g.set_attribute ("prop", "techval");
+                               c3g.set_attribute ("prop-name", "techval");
                                r2.append_child (c3g);
                                var c4g = d2.create_element ("child");
-                               c4g.set_attribute ("prop", "secondaryvalue");
+                               c4g.set_attribute ("prop-name", "secondaryvalue");
                                r2.append_child (c4g);
                                assert (cp.match (r));
                                assert (!cp.match (c1g));
@@ -455,13 +487,13 @@ class CssSelectorTest : GXmlTest {
                                var c1 = d.create_element ("child");
                                r.append_child (c1);
                                var c2 = d.create_element ("child");
-                               c2.set_attribute ("prop", "subval");
+                               c2.set_attribute ("prop-name", "subval");
                                r.append_child (c2);
                                var c3 = d.create_element ("child");
-                               c3.set_attribute ("prop", "techval");
+                               c3.set_attribute ("prop-name", "techval");
                                r.append_child (c3);
                                var c4 = d.create_element ("child");
-                               c4.set_attribute ("prop", "secondaryvalue");
+                               c4.set_attribute ("prop-name", "secondaryvalue");
                                r.append_child (c4);
                                var c5 = d.create_element ("common");
                                c4.append_child (c5);
@@ -482,13 +514,13 @@ class CssSelectorTest : GXmlTest {
                                var c1g = d2.create_element ("child");
                                r2.append_child (c1g);
                                var c2g = d2.create_element ("child");
-                               c2g.set_attribute ("prop", "subval");
+                               c2g.set_attribute ("prop-name", "subval");
                                r2.append_child (c2g);
                                var c3g = d2.create_element ("child");
-                               c3g.set_attribute ("prop", "techval");
+                               c3g.set_attribute ("prop-name", "techval");
                                r2.append_child (c3g);
                                var c4g = d2.create_element ("child");
-                               c4g.set_attribute ("prop", "secondaryvalue");
+                               c4g.set_attribute ("prop-name", "secondaryvalue");
                                r2.append_child (c4g);
                                var c5g = d2.create_element ("common");
                                c4g.append_child (c5g);
@@ -522,13 +554,13 @@ class CssSelectorTest : GXmlTest {
                                var c1 = d.create_element ("child");
                                r.append_child (c1);
                                var c2 = d.create_element ("child");
-                               c2.set_attribute ("prop", "subval");
+                               c2.set_attribute ("prop-name", "subval");
                                r.append_child (c2);
                                var c3 = d.create_element ("child");
-                               c3.set_attribute ("prop", "techval");
+                               c3.set_attribute ("prop-name", "techval");
                                r.append_child (c3);
                                var c4 = d.create_element ("child");
-                               c4.set_attribute ("prop", "secondaryvalue");
+                               c4.set_attribute ("prop-name", "secondaryvalue");
                                r.append_child (c4);
                                var c5 = d.create_element ("second");
                                c3.append_child (c5);
@@ -553,13 +585,13 @@ class CssSelectorTest : GXmlTest {
                                var c1g = d2.create_element ("child");
                                r2.append_child (c1g);
                                var c2g = d2.create_element ("child");
-                               c2g.set_attribute ("prop", "subval");
+                               c2g.set_attribute ("prop-name", "subval");
                                r2.append_child (c2g);
                                var c3g = d2.create_element ("child");
-                               c3g.set_attribute ("prop", "techval");
+                               c3g.set_attribute ("prop-name", "techval");
                                r2.append_child (c3g);
                                var c4g = d2.create_element ("child");
-                               c4g.set_attribute ("prop", "secondaryvalue");
+                               c4g.set_attribute ("prop-name", "secondaryvalue");
                                r2.append_child (c4g);
                                var c5g = d2.create_element ("second");
                                c3g.append_child (c5g);
@@ -596,13 +628,13 @@ class CssSelectorTest : GXmlTest {
                                var c1 = d.create_element ("child");
                                r.append_child (c1);
                                var c2 = d.create_element ("child");
-                               c2.set_attribute ("prop", "subval");
+                               c2.set_attribute ("prop-name", "subval");
                                r.append_child (c2);
                                var c3 = d.create_element ("child");
-                               c3.set_attribute ("prop", "techval");
+                               c3.set_attribute ("prop-name", "techval");
                                r.append_child (c3);
                                var c4 = d.create_element ("child");
-                               c4.set_attribute ("prop", "secondaryvalue");
+                               c4.set_attribute ("prop-name", "secondaryvalue");
                                r.append_child (c4);
                                var c5 = d.create_element ("second");
                                c3.append_child (c5);
@@ -624,13 +656,13 @@ class CssSelectorTest : GXmlTest {
                                var c1g = d2.create_element ("child");
                                r2.append_child (c1g);
                                var c2g = d2.create_element ("child");
-                               c2g.set_attribute ("prop", "subval");
+                               c2g.set_attribute ("prop-name", "subval");
                                r2.append_child (c2g);
                                var c3g = d2.create_element ("child");
-                               c3g.set_attribute ("prop", "techval");
+                               c3g.set_attribute ("prop-name", "techval");
                                r2.append_child (c3g);
                                var c4g = d2.create_element ("child");
-                               c4g.set_attribute ("prop", "secondaryvalue");
+                               c4g.set_attribute ("prop-name", "secondaryvalue");
                                r2.append_child (c4g);
                                var c5g = d2.create_element ("second");
                                c3g.append_child (c5g);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]