From 98618bb6cb45adce580cab024ba8535c5397ae87 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A9rome=20Perrin?= <jerome@nexedi.com>
Date: Tue, 19 Feb 2008 08:09:47 +0000
Subject: [PATCH] fix quote escaping

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@19366 20353a03-c40f-0410-a6d1-a30d3c3de9de
---
 product/ZSQLCatalog/SearchKey/DefaultKey.py  |  4 +-
 product/ZSQLCatalog/SearchKey/FullTextKey.py | 15 +++---
 product/ZSQLCatalog/SearchKey/KeyWordKey.py  |  4 --
 product/ZSQLCatalog/SearchKey/SearchKey.py   |  3 +-
 product/ZSQLCatalog/tests/testZSQLCatalog.py | 53 +++++++++++++++++---
 5 files changed, 59 insertions(+), 20 deletions(-)

diff --git a/product/ZSQLCatalog/SearchKey/DefaultKey.py b/product/ZSQLCatalog/SearchKey/DefaultKey.py
index e02225b2cc..ab097b1c6c 100644
--- a/product/ZSQLCatalog/SearchKey/DefaultKey.py
+++ b/product/ZSQLCatalog/SearchKey/DefaultKey.py
@@ -26,8 +26,8 @@
 #
 ##############################################################################
 
+from DocumentTemplate.DT_Var import sql_quote
 from SearchKey import SearchKey
-from pprint import pprint
 
 class DefaultKey(SearchKey):
   """ DefaultKey key is an ERP5 portal_catalog search key which is used to render
@@ -106,7 +106,7 @@ class DefaultKey(SearchKey):
     """ Return a quoted string of the value. """
     if isinstance(value, (int, long,)):
       return str(value)
-    return "'%s'" %value
+    return "'%s'" % sql_quote(value)
 
 
 ##  def buildSQLExpressionFromSearchString(self, key, value, format, mode, range_value, stat__):
diff --git a/product/ZSQLCatalog/SearchKey/FullTextKey.py b/product/ZSQLCatalog/SearchKey/FullTextKey.py
index a575d1a23a..25fa873fc5 100644
--- a/product/ZSQLCatalog/SearchKey/FullTextKey.py
+++ b/product/ZSQLCatalog/SearchKey/FullTextKey.py
@@ -44,8 +44,8 @@ class FullTextKey(SearchKey):
 
   # SQL expressions patterns
   relevance = '%s_relevance'
-  where_match_against = "MATCH %s AGAINST ('%s' %s)"
-  select_match_against_as = "MATCH %s AGAINST ('%s' %s) AS %s"
+  where_match_against = "MATCH %s AGAINST (%s %s)"
+  select_match_against_as = "MATCH %s AGAINST (%s %s) AS %s"
 
   t_PLUS = r'(\+)'
   t_MINUS = r'(\-)'
@@ -87,11 +87,14 @@ class FullTextKey(SearchKey):
       relevance_key1 = self.relevance %key
       relevance_key2 = None
     select_expression_list = []
-    where_expression = self.where_match_against %(key, value, mode)
+    where_expression = self.where_match_against % (key,
+                            self.quoteSQLString(value, ''), mode)
     if not stat__:
       # stat__ is an internal implementation artifact to prevent adding
       # select_expression for countFolder
-      select_expression_list = [self.select_match_against_as %(key, value, mode, relevance_key1),]
-      if  relevance_key2 is not None:
-        select_expression_list.append(self.select_match_against_as %(key, value, mode, relevance_key2))
+      select_expression_list = [self.select_match_against_as % (key,
+                    self.quoteSQLString(value, ''), mode, relevance_key1),]
+      if relevance_key2 is not None:
+        select_expression_list.append(self.select_match_against_as % (
+          key, self.quoteSQLString(value, ''), mode, relevance_key2))
     return where_expression, select_expression_list
diff --git a/product/ZSQLCatalog/SearchKey/KeyWordKey.py b/product/ZSQLCatalog/SearchKey/KeyWordKey.py
index a88bc144c8..9a12ace6da 100644
--- a/product/ZSQLCatalog/SearchKey/KeyWordKey.py
+++ b/product/ZSQLCatalog/SearchKey/KeyWordKey.py
@@ -125,10 +125,6 @@ class KeyWordKey(SearchKey):
       value = value[1:]
     t.value = value
     return t
-    
-  def quoteSQLString(self, value, format):
-    """ Return a quoted string of the value. """
-    return "'%s'" %value
   
   def getOperatorForTokenList(self, tokens):
     """ Generic implementation that will return respective 
diff --git a/product/ZSQLCatalog/SearchKey/SearchKey.py b/product/ZSQLCatalog/SearchKey/SearchKey.py
index 2d913fc4f3..1babb85546 100644
--- a/product/ZSQLCatalog/SearchKey/SearchKey.py
+++ b/product/ZSQLCatalog/SearchKey/SearchKey.py
@@ -26,6 +26,7 @@
 #
 ##############################################################################
 
+from DocumentTemplate.DT_Var import sql_quote
 from Products.ZSQLCatalog.Query.SimpleQuery import SimpleQuery as Query
 from Products.ZSQLCatalog.Query.ComplexQuery import ComplexQuery
 from Products.ZSQLCatalog.SQLCatalog import getSearchKeyInstance
@@ -108,7 +109,7 @@ class SearchKey:
 
   def quoteSQLString(self, value, format):
     """ Return a quoted string of the value. """
-    return "'%s'" %value
+    return "'%s'" % sql_quote(str(value))
 
   # SQL generation
   def buildSQLExpression(self, key, value, 
diff --git a/product/ZSQLCatalog/tests/testZSQLCatalog.py b/product/ZSQLCatalog/tests/testZSQLCatalog.py
index 408b325eb9..a63e0de647 100644
--- a/product/ZSQLCatalog/tests/testZSQLCatalog.py
+++ b/product/ZSQLCatalog/tests/testZSQLCatalog.py
@@ -108,13 +108,6 @@ class TestQuery(unittest.TestCase):
                             datetime_search_keys = [],
                             full_text_search_keys=[]))
 
-  def testQuotedString(self):
-    q = Query(title='Foo d\'Bar')
-    self.assertEquals(
-          dict(where_expression="title = 'Foo d''Bar'",
-               select_expression_list=[]),
-          q.asSQLExpression(keyword_search_keys=[], full_text_search_keys=[]))
-
   def testQueryMultipleKeys(self):
     # using multiple keys is invalid and raises
     # KeyError: 'Query must have only one key'
@@ -315,6 +308,52 @@ class TestQuery(unittest.TestCase):
                             datetime_search_keys = [],
                             full_text_search_keys=[])['where_expression'])
 
+  def testQuotedStringDefaultKey(self):
+    q = Query(title='Foo d\'Ba')
+    self.assertEquals(
+              dict(where_expression="((((title = 'Foo d''Ba'))))",
+                   select_expression_list=[]),
+                q.asSQLExpression())
+
+  def testQuotedStringKeywordKey(self):
+    q = Query(title='Foo d\'Ba', type='keyword')
+    self.assertEquals(
+              dict(where_expression="((((title LIKE '%Foo d''Ba%'))))",
+                   select_expression_list=[]),
+                q.asSQLExpression())
+
+  def testQuotedStringFullTextKey(self):
+    q = Query(title='Foo d\'Ba', type='fulltext')
+    self.assertEquals(
+        dict(where_expression="MATCH title AGAINST ('Foo d''Ba' )",
+             select_expression_list=["MATCH title AGAINST ('Foo d''Ba' )"
+                                     " AS title_relevance"]),
+          q.asSQLExpression())
+
+  def testQuotedStringDateKey(self):
+    q = Query(title='Foo d\'Ba', type='date')
+    self.assertEquals(
+        # I don't know exactly what we should expect here.
+              dict(where_expression="1",
+                   select_expression_list=[]),
+                q.asSQLExpression())
+
+  def testQuotedStringFloatKey(self):
+    q = Query(title='Foo d\'Ba', type='float')
+    self.assertEquals(
+        # I don't know exactly what we should expect here.
+        # At least it's safe.
+              dict(where_expression="1",
+                   select_expression_list=[]),
+                q.asSQLExpression())
+
+  def testQuotedStringIntKey(self):
+    q = Query(title='Foo d\'Ba', type='int')
+    self.assertEquals(
+              dict(where_expression="((((title = 'Foo d''Ba'))))",
+                   select_expression_list=[]),
+                q.asSQLExpression())
+
 
 def test_suite():
   suite = unittest.TestSuite()
-- 
2.30.9