From 7bc4883dfb2e83588a3575a256bf466b4a46c4f2 Mon Sep 17 00:00:00 2001 From: Adam Dickmeiss Date: Fri, 10 Oct 2025 13:26:38 +0200 Subject: [PATCH 1/2] Retain escape sequences in lexer, fixes #5 \\ is preserved in Lexer, leaving it to later stages to decide what masking is to be used. --- .../java/org/z3950/zing/cql/CQLGenerator.java | 2 +- src/main/java/org/z3950/zing/cql/CQLLexer.java | 16 ++++++---------- .../java/org/z3950/zing/cql/CQLTermNode.java | 2 +- src/test/resources/regression/06/03.xcql | 2 +- src/test/resources/regression/06/06.xcql | 2 +- src/test/resources/regression/12/01.xcql | 2 +- 6 files changed, 11 insertions(+), 15 deletions(-) diff --git a/src/main/java/org/z3950/zing/cql/CQLGenerator.java b/src/main/java/org/z3950/zing/cql/CQLGenerator.java index 2f21563..0b291a4 100644 --- a/src/main/java/org/z3950/zing/cql/CQLGenerator.java +++ b/src/main/java/org/z3950/zing/cql/CQLGenerator.java @@ -204,7 +204,7 @@ private String generate_base_relation() throws MissingParameterException { private String generate_term() { switch (rnd.nextInt(10)) { case 0: return "cat"; - case 1: return "\"cat\""; + case 1: return "\\\"cat\\\""; case 2: return "comp.os.linux"; case 3: return "xml:element"; case 4: return ""; diff --git a/src/main/java/org/z3950/zing/cql/CQLLexer.java b/src/main/java/org/z3950/zing/cql/CQLLexer.java index 4294b6f..ff5aee3 100644 --- a/src/main/java/org/z3950/zing/cql/CQLLexer.java +++ b/src/main/java/org/z3950/zing/cql/CQLLexer.java @@ -69,19 +69,15 @@ else if (comp.equals("<>")) { //remember quote char char mark = c; qi++; - boolean escaped = false; buf.setLength(0); //reset buffer - while (qi < ql) { - if (!escaped && qs.charAt(qi) == mark) //terminator - break; - if (escaped && strchr("*?^\\", qs.charAt(qi))) //no escaping for d-quote - buf.append("\\"); - if (!escaped && qs.charAt(qi) == '\\') { //escape-char - escaped = true; + while (qi < ql && qs.charAt(qi) != mark) { + if (qs.charAt(qi) == '\\') { //escape-char + if (qi == ql - 1) { + break; //unterminated + } + buf.append(qs.charAt(qi)); qi++; - continue; } - escaped = false; //reset escape buf.append(qs.charAt(qi)); qi++; } diff --git a/src/main/java/org/z3950/zing/cql/CQLTermNode.java b/src/main/java/org/z3950/zing/cql/CQLTermNode.java index 02a8229..a13a271 100644 --- a/src/main/java/org/z3950/zing/cql/CQLTermNode.java +++ b/src/main/java/org/z3950/zing/cql/CQLTermNode.java @@ -229,7 +229,7 @@ static String maybeQuote(String str) { str.indexOf('/') != -1 || str.indexOf('(') != -1 || str.indexOf(')') != -1) { - str = '"' + str.replace("\"", "\\\"") + '"'; + str = '"' + str + '"'; } return str; diff --git a/src/test/resources/regression/06/03.xcql b/src/test/resources/regression/06/03.xcql index 9db40ae..68b2dd5 100644 --- a/src/test/resources/regression/06/03.xcql +++ b/src/test/resources/regression/06/03.xcql @@ -3,5 +3,5 @@ = - ^cat says "fish" + ^cat says \"fish\" diff --git a/src/test/resources/regression/06/06.xcql b/src/test/resources/regression/06/06.xcql index 9d38695..2a0cd96 100644 --- a/src/test/resources/regression/06/06.xcql +++ b/src/test/resources/regression/06/06.xcql @@ -3,5 +3,5 @@ = - ^cat*fishdog"horse? + ^cat*fishdog\"horse? diff --git a/src/test/resources/regression/12/01.xcql b/src/test/resources/regression/12/01.xcql index c9fc4b6..b826cba 100644 --- a/src/test/resources/regression/12/01.xcql +++ b/src/test/resources/regression/12/01.xcql @@ -3,5 +3,5 @@ = - term\*\?\^ + te\rm\*\?\^ From f09d98ef85f59c30902da1d0dad9659dbd7b5bde Mon Sep 17 00:00:00 2001 From: Adam Dickmeiss Date: Tue, 21 Oct 2025 12:07:02 +0200 Subject: [PATCH 2/2] Consider the unlikely bare double quote --- src/main/java/org/z3950/zing/cql/CQLGenerator.java | 2 +- src/main/java/org/z3950/zing/cql/CQLTermNode.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/z3950/zing/cql/CQLGenerator.java b/src/main/java/org/z3950/zing/cql/CQLGenerator.java index 0b291a4..f22a7af 100644 --- a/src/main/java/org/z3950/zing/cql/CQLGenerator.java +++ b/src/main/java/org/z3950/zing/cql/CQLGenerator.java @@ -204,7 +204,7 @@ private String generate_base_relation() throws MissingParameterException { private String generate_term() { switch (rnd.nextInt(10)) { case 0: return "cat"; - case 1: return "\\\"cat\\\""; + case 1: return "\"cat\\\""; // A term with both bare quotes and escaped quotes case 2: return "comp.os.linux"; case 3: return "xml:element"; case 4: return ""; diff --git a/src/main/java/org/z3950/zing/cql/CQLTermNode.java b/src/main/java/org/z3950/zing/cql/CQLTermNode.java index a13a271..6fa042d 100644 --- a/src/main/java/org/z3950/zing/cql/CQLTermNode.java +++ b/src/main/java/org/z3950/zing/cql/CQLTermNode.java @@ -229,7 +229,7 @@ static String maybeQuote(String str) { str.indexOf('/') != -1 || str.indexOf('(') != -1 || str.indexOf(')') != -1) { - str = '"' + str + '"'; + str = '"' + str.replaceAll("(?