From a631329ea5ca8d8546d2b930559b75fa855aa725 Mon Sep 17 00:00:00 2001 From: Daniel Spofford Date: Sat, 2 May 2015 21:41:25 -0500 Subject: [PATCH 1/4] Do not split on spaces inside simple and double quotes Use a regex to identify search terms more reliably than spliting on a space. Does NOT respect escaping simple or double quotes within a term since JS does not support look-behinds in regexs. --- lib/search-query-parser.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/search-query-parser.js b/lib/search-query-parser.js index d5bd2f1..a81aca1 100644 --- a/lib/search-query-parser.js +++ b/lib/search-query-parser.js @@ -27,8 +27,14 @@ exports.parse = function (string, options) { else { // Our object to store the query object var query = {text: []}; - // Get a list of search term. Reverse to ensure proper order when pop()'ing. - var terms = string.split(' ').reverse(); + // Get a list of search terms respecting single and double quotes + var terms = string.match(/(\S+:(".+?"|'.+?'))|(\S+:\S+)|\S+/g); + // Rip out the quotes + for (var i = 0; i < terms.length; i++) { + terms[i] = terms[i].replace(/['"]+/g, ''); + }; + // Reverse to ensure proper order when pop()'ing. + terms.reverse(); // For each search term while (term = terms.pop()) { // Advanced search terms syntax has key and value From 5090897e18d101ac27fcd275ada74390cc56a92e Mon Sep 17 00:00:00 2001 From: Daniel Spofford Date: Sun, 3 May 2015 00:11:00 -0500 Subject: [PATCH 2/4] Respect escaped characters while also respecting quoted spaces --- lib/search-query-parser.js | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/lib/search-query-parser.js b/lib/search-query-parser.js index a81aca1..f38ffe3 100644 --- a/lib/search-query-parser.js +++ b/lib/search-query-parser.js @@ -28,10 +28,29 @@ exports.parse = function (string, options) { // Our object to store the query object var query = {text: []}; // Get a list of search terms respecting single and double quotes - var terms = string.match(/(\S+:(".+?"|'.+?'))|(\S+:\S+)|\S+/g); - // Rip out the quotes + var terms = string.match(/(\S+:'(?:[^'\\]|\\.)*')|(\S+:"(?:[^"\\]|\\.)*")|\S+|\S+:\S+/g); for (var i = 0; i < terms.length; i++) { - terms[i] = terms[i].replace(/['"]+/g, ''); + if(terms[i].indexOf(':') !== -1) { + var split = terms[i].split(':'), + key = split[0], + val = split[1]; + // Strip surrounding quotes + val = val.replace(/^\"|\"$|^\'|\'$/g, ''); + // Strip backslashes respecting escapes + val = (val + '').replace(/\\(.?)/g, function (s, n1) { + switch (n1) { + case '\\': + return '\\'; + case '0': + return '\u0000'; + case '': + return ''; + default: + return n1; + } + }); + terms[i] = key + ':' + val; + } }; // Reverse to ensure proper order when pop()'ing. terms.reverse(); From 5a37692e67230315e209bbaabbf29e297cdf4a8a Mon Sep 17 00:00:00 2001 From: Daniel Spofford Date: Mon, 4 May 2015 09:54:17 -0500 Subject: [PATCH 3/4] Correctly handle semicolons within search term values --- lib/search-query-parser.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/search-query-parser.js b/lib/search-query-parser.js index f38ffe3..d1f2a4d 100644 --- a/lib/search-query-parser.js +++ b/lib/search-query-parser.js @@ -30,10 +30,11 @@ exports.parse = function (string, options) { // Get a list of search terms respecting single and double quotes var terms = string.match(/(\S+:'(?:[^'\\]|\\.)*')|(\S+:"(?:[^"\\]|\\.)*")|\S+|\S+:\S+/g); for (var i = 0; i < terms.length; i++) { - if(terms[i].indexOf(':') !== -1) { + var sepIndex = terms[i].indexOf(':'); + if(sepIndex !== -1) { var split = terms[i].split(':'), - key = split[0], - val = split[1]; + key = terms[i].slice(0, sepIndex), + val = terms[i].slice(sepIndex + 1); // Strip surrounding quotes val = val.replace(/^\"|\"$|^\'|\'$/g, ''); // Strip backslashes respecting escapes From 8396eac0973b7b586d3e2bf29d0e59ab32e187b3 Mon Sep 17 00:00:00 2001 From: Daniel Spofford Date: Wed, 21 Oct 2015 21:19:26 -0500 Subject: [PATCH 4/4] Add tests for quoted search terms with spaces and escaped quotes in them --- test/test.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test/test.js b/test/test.js index 414ab0b..14385a6 100644 --- a/test/test.js +++ b/test/test.js @@ -201,4 +201,26 @@ describe('Search query syntax parser', function () { }); + it('should not split on spaces inside single and double quotes', function () { + var searchQuery = 'name:"Bob Saget" description:\'Banana Sandwiche\''; + var options = {keywords: ['name', 'description']}; + var parsedSearchQuery = searchquery.parse(searchQuery, options); + + parsedSearchQuery.should.be.an.Object; + parsedSearchQuery.should.have.property('name', 'Bob Saget'); + parsedSearchQuery.should.have.property('description', 'Banana Sandwiche'); + }); + + + it('should correctly handle escaped single and double quotes', function () { + var searchQuery = 'case1:"This \\"is\\" \'a\' test" case2:\'This "is" \\\'a\\\' test\''; + var options = {keywords: ['case1', 'case2']}; + var parsedSearchQuery = searchquery.parse(searchQuery, options); + + parsedSearchQuery.should.be.an.Object; + parsedSearchQuery.should.have.property('case1', 'This "is" \'a\' test'); + parsedSearchQuery.should.have.property('case2', 'This "is" \'a\' test'); + }); + + });