]> arthur.barton.de Git - netatalk.git/blobdiff - etc/afpd/spotlight_module.c
Support for FTS and filename search
[netatalk.git] / etc / afpd / spotlight_module.c
index d38abebbd064a81654eedcf6eee274be9ec73fce..91c761a69046620d7f6139aa35b2a016ee0e2f7e 100644 (file)
@@ -28,6 +28,8 @@
 
 #include "spotlight.h"
 
+#define MAX_SL_RESULTS 20
+
 static TrackerSparqlConnection *connection;
 
 char *tracker_to_unix_path(const char *uri)
@@ -77,21 +79,38 @@ static const gchar *map_spotlight_to_sparql_query(slq_t *slq)
 {
     EC_INIT;
     const gchar *sparql_query;
-    const char *sparql_query_format = "SELECT nie:url(?uri) WHERE {?uri fts:match '%s' . ?uri nie:url ?url FILTER(fn:starts-with(?url, 'file://%s')) }";
+    const char *sparql_query_format;
     const char *slquery = slq->slq_qstring;
     char *word, *p;
 
     LOG(log_debug, logtype_sl, "query_word_from_sl_query: \"%s\"", slquery);
 
-    EC_NULL_LOG( word = strstr(slquery, "*==") );
-    word += 4; /* skip *== and the left enclosing quote */
-    EC_NULL( word = dalloc_strdup(slq, word) );
-    /* Search asterisk */
-    EC_NULL_LOG( p = strchr(word, '*') );
-    p[1] = 0;
-    sparql_query = talloc_asprintf(slq, sparql_query_format, word, slq->slq_vol->v_path);
-
-    LOG(log_debug, logtype_sl, "query_word_from_sl_query: \"%s\"", sparql_query);
+    if ((word = strstr(slquery, "*==")) || (word = strstr(slquery, "kMDItemTextContent=="))) {
+        /* Full text search */
+        sparql_query_format = "SELECT nie:url(?uri) WHERE {?uri nie:url ?url . FILTER(fn:starts-with(?url, 'file://%s')) . ?uri fts:match '%s'}";
+        EC_NULL_LOG( word = strchr(word, '"') );
+        word++;
+        EC_NULL( word = dalloc_strdup(slq, word) );
+        EC_NULL_LOG( p = strchr(word, '"') );
+        *p = 0;
+        sparql_query = talloc_asprintf(slq, sparql_query_format, slq->slq_vol->v_path, word);
+        LOG(log_debug, logtype_sl, "query_word_from_sl_query: \"%s\"", sparql_query);
+    } else if ((word = strstr(slquery, "kMDItemDisplayName=="))) {
+        /* Filename search */
+        sparql_query_format = "SELECT nie:url(?f) WHERE { ?f nie:url ?url . ?f nfo:fileName ?name . FILTER(fn:starts-with(?url, 'file://%s/') && regex(?name, '%s')) }";
+        EC_NULL_LOG( word = strchr(word, '"') );
+        word++;
+        EC_NULL( word = dalloc_strdup(slq, word) );
+        EC_NULL_LOG( p = strchr(word, '"') );
+        if (*(p-1) == '*')
+            *(p-1) = 0;
+        else
+            *p = 0;
+        sparql_query = talloc_asprintf(slq, sparql_query_format, slq->slq_vol->v_path, word);
+        LOG(log_debug, logtype_sl, "query_word_from_sl_query: \"%s\"", sparql_query);
+    } else {
+        EC_FAIL_LOG("Can't parse SL query: '%s'", slquery);
+    }
 
 EC_CLEANUP:
     if (ret != 0)
@@ -194,6 +213,7 @@ static int sl_mod_fetch_result(void *p)
     sl_filemeta_t *fm;
     sl_array_t *fm_array;
     uint64_t uint64;
+    gboolean more;
 
     if (!slq->slq_tracker_cursor) {
         LOG(log_debug, logtype_sl, "sl_mod_fetch_result: no results found");
@@ -217,12 +237,9 @@ static int sl_mod_fetch_result(void *p)
 
     LOG(log_debug, logtype_sl, "sl_mod_fetch_result: now interating Tracker results cursor");
 
-    while (tracker_sparql_cursor_next(slq->slq_tracker_cursor, NULL, &error)) {
+    while (i <= MAX_SL_RESULTS && tracker_sparql_cursor_next(slq->slq_tracker_cursor, NULL, &error)) {
         uri = tracker_sparql_cursor_get_string(slq->slq_tracker_cursor, 0, NULL);
-        LOG(log_debug, logtype_sl, "Result %d: uri: \"%s\"", i, uri);
-
         EC_NULL_LOG( path = tracker_to_unix_path(uri) );
-        LOG(log_debug, logtype_sl, "sl_mod_fetch_result: path(volpath: %s): \"%s\"", slq->slq_vol->v_path, path);
 
         if ((id = cnid_for_path(slq->slq_vol->v_cdb, slq->slq_vol->v_path, path, &did)) == CNID_INVALID) {
             LOG(log_error, logtype_sl, "sl_mod_fetch_result: cnid_for_path error");
@@ -245,15 +262,18 @@ static int sl_mod_fetch_result(void *p)
         EC_FAIL;
     }
 
-    slq->slq_state = SLQ_STATE_DONE;
+    if (i < MAX_SL_RESULTS)
+        slq->slq_state = SLQ_STATE_DONE;
 
     dalloc_add(slq->slq_reply, cnids, sl_cnids_t);
     dalloc_add(slq->slq_reply, fm, sl_filemeta_t);
 
 EC_CLEANUP:
     if (slq->slq_tracker_cursor) {
-        g_object_unref(slq->slq_tracker_cursor);
-        slq->slq_tracker_cursor = NULL;
+        if ((ret != 0) || (slq->slq_state == SLQ_STATE_DONE)) {
+            g_object_unref(slq->slq_tracker_cursor);
+            slq->slq_tracker_cursor = NULL;
+        }
     }
     EC_EXIT;
 }