[tracker/tracker-0.6] Fix corner cases in the RDF parser wrt '%', '[' and '*' chars. Fully fixes NB#123030.



commit 11f5e6d1394a85d551787b320754f109f09993a8
Author: Carlos Garnacho <carlosg gnome org>
Date:   Fri Jun 19 13:31:23 2009 +0200

    Fix corner cases in the RDF parser wrt '%', '[' and '*' chars. Fully fixes NB#123030.
    
    * if the RDF parser finds '*' globs, it's now translated to a LIKE clause, so we do not
      have to escape '[' to "[[]". This also makes RDF glob search caseless for ASCII.
    * Add a boolean parameter to tracker_escape_db_string() to escape '%' or not, based
      on what's the string going to be used for. Literal comparisons do not need these
      escaped, and will look for the wrong string if it is.

 src/libtracker-common/tracker-utils.c     |   12 ++++--
 src/libtracker-common/tracker-utils.h     |    3 +-
 src/libtracker-data/tracker-data-update.c |   14 ++++---
 src/libtracker-data/tracker-rdf-query.c   |   66 ++++++++++++++++++-----------
 src/libtracker-db/tracker-db-manager.c    |    4 +-
 5 files changed, 61 insertions(+), 38 deletions(-)
---
diff --git a/src/libtracker-common/tracker-utils.c b/src/libtracker-common/tracker-utils.c
index b1bb538..b36f0d3 100644
--- a/src/libtracker-common/tracker-utils.c
+++ b/src/libtracker-common/tracker-utils.c
@@ -104,7 +104,8 @@ tracker_string_replace (const gchar *haystack,
 
 gchar *
 tracker_escape_db_string (const gchar *str,
-			  gboolean     add_quotes)
+			  gboolean     add_quotes,
+			  gboolean     escape_percent)
 {
 	gchar *escaped, *p;
 	guint len;
@@ -131,9 +132,12 @@ tracker_escape_db_string (const gchar *str,
 		switch (*str) {
 		case '\'':
 		case '%':
-			/* These chars need to be twice in the escaped string */
-			*p = *str;
-			p++;
+			if (*str != '%' || escape_percent) {
+				/* These chars need to be twice in the escaped string */
+				*p = *str;
+				p++;
+			}
+
 			/* Fall through */
 		default:
 			*p = *str;
diff --git a/src/libtracker-common/tracker-utils.h b/src/libtracker-common/tracker-utils.h
index 48ef635..a3529a6 100644
--- a/src/libtracker-common/tracker-utils.h
+++ b/src/libtracker-common/tracker-utils.h
@@ -36,7 +36,8 @@ gchar *  tracker_string_replace		    (const gchar   *haystack,
 gchar *  tracker_string_remove		    (gchar	   *haystack,
 					     const gchar   *needle);
 gchar *  tracker_escape_db_string           (const gchar   *str,
-					     gboolean       add_quotes);
+					     gboolean       add_quotes,
+					     gboolean       escape_percent);
 gchar *  tracker_seconds_estimate_to_string (gdouble	    seconds_elapsed,
 					     gboolean	    short_string,
 					     guint	    items_done,
diff --git a/src/libtracker-data/tracker-data-update.c b/src/libtracker-data/tracker-data-update.c
index 2c4cbe3..61bca90 100644
--- a/src/libtracker-data/tracker-data-update.c
+++ b/src/libtracker-data/tracker-data-update.c
@@ -755,7 +755,7 @@ tracker_data_update_replace_service (const gchar *udi,
 	}
 
 	file_mtime = atoi (modified);
-	escaped_path = tracker_escape_db_string (path, FALSE);
+	escaped_path = tracker_escape_db_string (path, FALSE, TRUE);
 
 	basename = g_path_get_basename (escaped_path);
 	dirname = g_path_get_dirname (escaped_path);
@@ -932,13 +932,15 @@ tracker_data_update_metadata_context_add (TrackerDataUpdateMetadataContext *cont
 					  const gchar                      *value,
 					  const gchar                      *function)
 {
+	gchar *escaped;
+
+	escaped = tracker_escape_db_string (value, TRUE, TRUE);
+
 	if (G_UNLIKELY (function)) {
-		gchar *escaped;
 		gchar *wrapped;
 
-		escaped = tracker_escape_db_string (value, TRUE);
-		wrapped = g_strdup_printf ("%s(%s)", 
-					   function, 
+		wrapped = g_strdup_printf ("%s(%s)",
+					   function,
 					   escaped);
 		g_free (escaped);
 
@@ -948,7 +950,7 @@ tracker_data_update_metadata_context_add (TrackerDataUpdateMetadataContext *cont
 	} else {
 		g_hash_table_replace (context->data,
 				      g_strdup (column),
-				      tracker_escape_db_string (value, TRUE));
+				      escaped);
 	}
 }
 
diff --git a/src/libtracker-data/tracker-rdf-query.c b/src/libtracker-data/tracker-rdf-query.c
index 3b70948..1d1cfe3 100644
--- a/src/libtracker-data/tracker-rdf-query.c
+++ b/src/libtracker-data/tracker-rdf-query.c
@@ -742,12 +742,27 @@ start_element_handler (GMarkupParseContext  *context,
 	}
 }
 
+static void
+replace_wildcards (gchar *str)
+{
+	gchar *c;
+
+	/* Replace glob-like wildcards
+	 * with % so we can use LIKE clauses
+	 */
+	for (c = str; *c; c++) {
+		if (*c == '*') {
+			*c = '%';
+		}
+	}
+}
+
 static gboolean
 build_sql (ParserData *data)
 {
 	TrackerFieldData  *field_data;
 	ParseState	   state;
-	gchar		  *avalue, *value, *sub;
+	gchar		  *avalue, *value, *sub, *val;
 	const gchar	  *where_field;
 	GString		  *str;
 	gchar		 **s;
@@ -764,9 +779,10 @@ build_sql (ParserData *data)
 	state = peek_state (data);
 
 	avalue = tracker_escape_db_string (data->current_value, 
-					   state != STATE_END_DATE &&
-					   state != STATE_END_INTEGER &&
-					   state != STATE_END_FLOAT);
+					   (state != STATE_END_DATE &&
+					    state != STATE_END_INTEGER &&
+					    state != STATE_END_FLOAT),
+					   FALSE);
 
 	field_data = add_metadata_field (data, data->current_field, FALSE, TRUE, FALSE);
 
@@ -809,9 +825,12 @@ build_sql (ParserData *data)
 	case OP_EQUALS:
 		sub = strchr (data->current_value, '*');
 		if (sub) {
-			g_string_append_printf (str, " (%s glob '%s') ",
-						where_field,
-						data->current_value);
+			val = tracker_escape_db_string (data->current_value, FALSE, TRUE);
+			replace_wildcards (val);
+
+			g_string_append_printf (str, " (%s like '%s') ",
+						where_field, val);
+			g_free (val);
 		} else {
 			/* FIXME This check is too fragile */
 			if ( !strlen(value) || (strcmp(value, "''") == 0) ) {
@@ -821,8 +840,7 @@ build_sql (ParserData *data)
 							where_field);
 			} else {
 				g_string_append_printf (str, " (%s = %s) ",
-							where_field,
-							value);
+							where_field, value);
 			}
 		}
 		break;
@@ -852,31 +870,35 @@ build_sql (ParserData *data)
 		break;
 
 	case OP_CONTAINS:
+		val = tracker_escape_db_string (data->current_value, FALSE, TRUE);
 		sub = strchr (data->current_value, '*');
 
 		if (sub) {
+			replace_wildcards (val);
 			g_string_append_printf (str, " (%s like '%%%%%s%%%%') ",
-						where_field,
-						data->current_value);
+						where_field, val);
 		} else {
 			g_string_append_printf (str, " (%s like '%%%%%s%%%%') ",
-						where_field,
-						data->current_value);
+						where_field, val);
 		}
+
+		g_free (val);
 		break;
 
 	case OP_STARTS:
+		val = tracker_escape_db_string (data->current_value, FALSE, TRUE);
 		sub = strchr (data->current_value, '*');
 
 		if (sub) {
+			replace_wildcards (val);
 			g_string_append_printf (str, " (%s like '%s') ",
-						where_field,
-						data->current_value);
+						where_field, val);
 		} else {
 			g_string_append_printf (str, " (%s like '%s%%%%') ",
-						where_field,
-						data->current_value);
+						where_field, val);
 		}
+
+		g_free (val);
 		break;
 
 	case OP_REGEX:
@@ -1095,13 +1117,7 @@ text_handler (GMarkupParseContext *context,
         case STATE_STRING:
         case STATE_DATE:
         case STATE_FLOAT:
-		{
-			gchar *str;
-
-			str = g_strstrip (g_strndup (text, text_len));
-			data->current_value = tracker_escape_db_string (str, FALSE);
-			g_free (str);
-		}
+		data->current_value = g_strstrip (g_strndup (text, text_len));
                 break;
         default:
                 break;
@@ -1290,7 +1306,7 @@ tracker_rdf_query_to_sql (TrackerDBInterface  *iface,
 			}
 
 			list = g_hash_table_lookup (table, key);
-			list = g_list_prepend (list, tracker_escape_db_string (value, TRUE));
+			list = g_list_prepend (list, tracker_escape_db_string (value, TRUE, FALSE));
 			g_hash_table_insert (table, g_strdup (key), list);
 
 			g_free (full);
diff --git a/src/libtracker-db/tracker-db-manager.c b/src/libtracker-db/tracker-db-manager.c
index 43e9e15..e1e79aa 100644
--- a/src/libtracker-db/tracker-db-manager.c
+++ b/src/libtracker-db/tracker-db-manager.c
@@ -512,7 +512,7 @@ load_metadata_file (TrackerDBInterface *iface,
 			} else {
 				gchar *escaped_value;
 
-				escaped_value = tracker_escape_db_string (new_value, TRUE);
+				escaped_value = tracker_escape_db_string (new_value, TRUE, FALSE);
 
 				tracker_db_interface_execute_query (iface, NULL,
 								    "update MetaDataTypes set  %s = %s where ID = %d",
@@ -675,7 +675,7 @@ load_service_file (TrackerDBInterface *iface,
 
 				value = g_key_file_get_string (key_file, groups[i], keys[j], NULL);
 				new_value = tracker_string_boolean_to_string_gint (value);
-				escaped_value = tracker_escape_db_string (new_value, TRUE);
+				escaped_value = tracker_escape_db_string (new_value, TRUE, FALSE);
 
 				/* Special case "Parent */
 				if (g_ascii_strcasecmp (keys[j], "parent") == 0) {



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