]> arthur.barton.de Git - netatalk.git/blobdiff - etc/spotlight/slmod_rdf_parser.y
Add new Spotlight RPC functions
[netatalk.git] / etc / spotlight / slmod_rdf_parser.y
index 4b6ea18e31a38e9772e76f66f826f02c64076622..9352d7a27973ea043e6b89361deaa964c00b6f11 100644 (file)
@@ -7,6 +7,7 @@
   #include <time.h>
 
   #include <gio/gio.h>
+  #include <tracker.h>
 
   #include <atalk/talloc.h>
   #include <atalk/logger.h>
@@ -38,7 +39,7 @@
 
 %code provides {
   #define SPRAW_TIME_OFFSET 978307200
-  extern int map_spotlight_to_rdf_query(slq_t *slq, gchar **rdf_result, gchar **fts_result);
+  extern int map_spotlight_to_rdf_query(slq_t *slq);
   extern slq_t *srp_slq;
 }
 
@@ -103,7 +104,11 @@ BOOL                             {
          * The default Spotlight search term issued by the Finder (10.8) is:
          * '* == "searchterm" || kMDItemTextContent == "searchterm"'
          * As it isn't mappable to a single Tracker RDF query, we silently
-         * map this to just a filename search
+         * map ANY FTS query expression being part of an OR compound
+         * expression to a simple filename search.
+         * FTS queries are thus only possible by explicitly requesting
+         * file content FTS search in the Finder on the client (resulting
+         * in a 'kMDItemTextContent == "searchterm"' query).
          */
         if (strcmp($1, "") == 0)
             $$ = talloc_asprintf(srp_slq, $3);
@@ -163,7 +168,19 @@ static const char *map_daterange(const char *dateattr, time_t date1, time_t date
 
     for (p = spotlight_rdf_map; p->srm_spotlight_attr; p++) {
         if (strcmp(dateattr, p->srm_spotlight_attr) == 0) {
-            /* do something */
+                result = talloc_asprintf(srp_slq,
+                                         "<rdfq:and>\n"
+                                         "  <rdfq:greaterThan>\n"
+                                         "    <rdfq:Property name=\"%s\" />\n"
+                                         "    <rdf:Date>%s</rdf:Date>\n"
+                                         "  </rdfq:greaterThan>\n"
+                                         "  <rdfq:lessThan>\n"
+                                         "    <rdfq:Property name=\"%s\" />\n"
+                                         "    <rdf:Date>%s</rdf:Date>\n"
+                                         "  </rdfq:lessThan>\n"
+                                         "</rdfq:and>\n",
+                                         p->srm_rdf_attr, buf1,
+                                         p->srm_rdf_attr, buf2);
             break;
         }
     }
@@ -174,6 +191,32 @@ EC_CLEANUP:
     return result;
 }
 
+static char *map_type_search(const char *attr, char op, const char *val)
+{
+    char *result = NULL;
+
+    for (struct MDTypeMap *p = MDTypeMap; p->mdtm_value; p++) {
+        if (strcmp(p->mdtm_value, val) == 0) {
+            if (!p->mdtm_type)
+                return NULL;
+            if (val[0] == '9') {
+                srp_slq->slq_service = SERVICE_FOLDERS;
+                return "";
+            }
+            result = talloc_asprintf(srp_slq,
+                                     "<rdfq:%s>\n"
+                                     "  <rdfq:Property name=\"File:Mime\" />\n"
+                                     "  <rdf:String>%s</rdf:String>\n"
+                                     "</rdfq:%s>\n",
+                                     p->mdtm_rdfop,
+                                     p->mdtm_type,
+                                     p->mdtm_rdfop);
+            break;
+        }
+    }
+    return result;
+}
+
 static const char *map_expr(const char *attr, char op, const char *val)
 {
     EC_INIT;
@@ -188,14 +231,21 @@ static const char *map_expr(const char *attr, char op, const char *val)
     for (p = spotlight_rdf_map; p->srm_spotlight_attr; p++) {
         if (p->srm_rdf_attr && strcmp(p->srm_spotlight_attr, attr) == 0) {
             switch (p->srm_type) {
-#if 0
-            case srmt_bool:
-                /* do something */
-                break;
             case srmt_num:
-                /* do something */
+                q = bformat("^%s$", val);
+                search = bfromcstr("*");
+                replace = bfromcstr(".*");
+                bfindreplace(q, search, replace, 0);
+                result = talloc_asprintf(srp_slq,
+                                         "<rdfq:regex>\n"
+                                         "  <rdfq:Property name=\"%s\" />\n"
+                                         "  <rdf:String>%s</rdf:String>\n"
+                                         "</rdfq:regex>\n",
+                                         p->srm_rdf_attr,
+                                         bdata(q));
+                bdestroy(q);
                 break;
-#endif
+
             case srmt_str:
                 q = bformat("^%s$", val);
                 search = bfromcstr("*");
@@ -203,9 +253,10 @@ static const char *map_expr(const char *attr, char op, const char *val)
                 bfindreplace(q, search, replace, 0);
                 result = talloc_asprintf(srp_slq,
                                          "<rdfq:regex>\n"
-                                         "  <rdfq:Property name=\"File:Name\" />\n"
+                                         "  <rdfq:Property name=\"%s\" />\n"
                                          "  <rdf:String>%s</rdf:String>\n"
                                          "</rdfq:regex>\n",
+                                         p->srm_rdf_attr,
                                          bdata(q));
                 bdestroy(q);
                 break;
@@ -223,14 +274,38 @@ static const char *map_expr(const char *attr, char op, const char *val)
                 result = "";
                 break;
 
-#if 0
             case srmt_date:
                 t = atoi(val) + SPRAW_TIME_OFFSET;
                 EC_NULL( tmp = localtime(&t) );
                 strftime(buf1, sizeof(buf1), "%Y-%m-%dT%H:%M:%SZ", tmp);
-                /* do something */
+
+                switch (op) {
+                case '=':
+                    rdfop = "equals";
+                case '<':
+                    rdfop = "lessThan";
+                case '>':
+                    rdfop = "greaterThan";
+                default:
+                    yyerror("unknown date comparison");
+                    EC_FAIL;
+                }
+                result = talloc_asprintf(srp_slq,
+                                         "<rdfq:%s>\n"
+                                         "  <rdfq:Property name=\"%s\" />\n"
+                                         "  <rdf:Date>%s</rdf:Date>\n"
+                                         "</rdfq:%s>\n",
+                                         rdfop,
+                                         p->srm_rdf_attr,
+                                         buf1,
+                                         rdfop);
+
                 break;
-#endif
+
+            case srmt_type:
+                result = map_type_search(attr, op, val);
+                break;
+
             default:
                 yyerror("unknown Spotlight attribute type");
                 EC_FAIL;
@@ -267,17 +342,15 @@ int yywrap()
  * Map a Spotlight RAW query string to a RDF query
  *
  * @param[in]     slq            Spotlight query handle
- * @param[out]    sparql_result  Mapped RDF query, string is allocated in
- *                               talloc context of slq
  * @return        0 on success, -1 on error
  **/
-int map_spotlight_to_rdf_query(slq_t *slq, gchar **rdf_result, gchar **fts_result)
+int map_spotlight_to_rdf_query(slq_t *slq)
 {
     EC_INIT;
     YY_BUFFER_STATE s = NULL;
     srp_result = NULL;
     srp_fts = NULL;
-
+    slq->slq_service = SERVICE_FILES;
     srp_slq = slq;
     s = yy_scan_string(slq->slq_qstring);
 
@@ -287,11 +360,8 @@ EC_CLEANUP:
     if (s)
         yy_delete_buffer(s);
     if (ret == 0) {
-        *rdf_result = srp_result;
-        *fts_result = srp_fts;
-    } else {
-        *rdf_result = NULL;
-        *fts_result = NULL;
+        slq->slq_trackerquery = srp_result;
+        slq->slq_fts = srp_fts;
     }
     EC_EXIT;
 }