]> arthur.barton.de Git - netatalk.git/blob - etc/afpd/spotlight_module.c
Dispatch queries to Tracker and get results
[netatalk.git] / etc / afpd / spotlight_module.c
1 /*
2   Copyright (c) 2012 Frank Lahm <franklahm@gmail.com>
3
4   This program is free software; you can redistribute it and/or modify
5   it under the terms of the GNU General Public License as published by
6   the Free Software Foundation; either version 2 of the License, or
7   (at your option) any later version.
8
9   This program is distributed in the hope that it will be useful,
10   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   GNU General Public License for more details.
13 */
14
15 #ifdef HAVE_CONFIG_H
16 #include "config.h"
17 #endif /* HAVE_CONFIG_H */
18
19 #include <string.h>
20
21 #include <tracker-sparql.h>
22
23 #include <atalk/util.h>
24 #include <atalk/errchk.h>
25 #include <atalk/logger.h>
26
27 #include "spotlight.h"
28
29 static TrackerSparqlConnection *connection;
30
31 static int sl_mod_init(void *p)
32 {
33     EC_INIT;
34     GError *error = NULL;
35     const char *msg = p;
36
37     LOG(log_note, logtype_sl, "sl_mod_init: %s", msg);
38     setenv("DBUS_SESSION_BUS_ADDRESS", "unix:path=/tmp/spotlight.ipc", 1);
39
40     g_type_init();
41     connection = tracker_sparql_connection_get(NULL, &error);
42     if (!connection) {
43         LOG(log_error, logtype_sl, "Couldn't obtain a direct connection to the Tracker store: %s",
44             error ? error->message : "unknown error");
45         g_clear_error(&error);
46         EC_FAIL;
47     }
48
49 EC_CLEANUP:
50     EC_EXIT;
51 }
52
53 /*!
54  * Return talloced query from query string
55  * *=="query*"
56  */
57 static const gchar *map_spotlight_to_sparql_query(slq_t *slq)
58 {
59     EC_INIT;
60     const gchar *sparql_query;
61     const char *sparql_query_format = "SELECT nie:url(?f) WHERE { ?f nie:url ?name FILTER regex(?name, \"%s\")}";
62     const char *slquery = slq->slq_qstring;
63     char *word, *p;
64
65     LOG(log_debug, logtype_sl, "query_word_from_sl_query: \"%s\"", slquery);
66
67     EC_NULL_LOG( word = strstr(slquery, "*==") );
68     word += 4; /* skip *== and the left enclosing quote */
69     EC_NULL( word = talloc_strdup(slq, word) );
70     /* Search asterisk */
71     EC_NULL_LOG( p = strchr(word, '*') );
72     *p = 0;
73
74     sparql_query = talloc_asprintf(slq, sparql_query_format, word);
75
76     LOG(log_debug, logtype_sl, "query_word_from_sl_query: \"%s\"", sparql_query);
77
78 EC_CLEANUP:
79     if (ret != 0)
80         sparql_query = NULL;
81     return sparql_query;
82 }
83
84 static void tracker_cb(GObject *source_object, GAsyncResult *res, gpointer user_data)
85 {
86     slq_t *slq = user_data;
87     TrackerSparqlCursor *cursor;
88     GError *error = NULL;
89
90     LOG(log_debug, logtype_sl, "tracker_cb");
91
92     cursor = tracker_sparql_connection_query_finish(connection, res, &error);
93
94     if (error) {
95         LOG(log_error, logtype_sl, "sl_mod_fetch_result: Couldn't query the Tracker Store: '%s'",
96             error ? error->message : "unknown error");
97         g_clear_error(&error);
98         return;
99     }
100
101     slq->slq_tracker_cursor = cursor;
102 }
103
104 static int sl_mod_start_search(void *p)
105 {
106     EC_INIT;
107     slq_t *slq = p; 
108     const gchar *sparql_query;
109     GError *error = NULL;
110
111     LOG(log_debug, logtype_sl, "sl_mod_start_search: Spotlight query string: \"%s\"", slq->slq_qstring);
112
113     EC_NULL_LOG( sparql_query = map_spotlight_to_sparql_query(slq) );
114     LOG(log_debug, logtype_sl, "sl_mod_start_search: SPARQL query: \"%s\"", sparql_query);
115
116 #if 0
117     /* Start the async query */
118     tracker_sparql_connection_query_async(connection, sparql_query, NULL, tracker_cb, slq);
119 #endif
120
121     slq->slq_tracker_cursor = tracker_sparql_connection_query(connection, sparql_query, NULL, &error);
122     if (error) {
123         LOG(log_error, logtype_sl, "Couldn't query the Tracker Store: '%s'",
124             error ? error->message : "unknown error");
125         g_clear_error(&error);
126         EC_FAIL;
127     }
128
129 EC_CLEANUP:
130     EC_EXIT;
131 }
132
133 static int sl_mod_fetch_result(void *p)
134 {
135     EC_INIT;
136     slq_t *slq = p;
137     GError *error = NULL;
138
139     if (slq->slq_tracker_cursor) {
140         int i = 0;
141         while (tracker_sparql_cursor_next(slq->slq_tracker_cursor, NULL, &error)) {
142             LOG(log_debug, logtype_sl, "Result [%d]: %s",
143                 i++, tracker_sparql_cursor_get_string(slq->slq_tracker_cursor, 0, NULL));
144         }
145     } else {
146         LOG(log_debug, logtype_sl, "sl_mod_fetch_result: no results found");
147     }
148
149 EC_CLEANUP:
150     if (slq->slq_tracker_cursor)
151         g_object_unref(slq->slq_tracker_cursor);
152     EC_EXIT;
153 }
154
155 struct sl_module_export sl_mod = {
156     SL_MODULE_VERSION,
157     sl_mod_init,
158     sl_mod_start_search,
159     sl_mod_fetch_result,
160     NULL
161 };