blob: 0743629cba8b49177a5fd121bbffacd09820bfcc [file] [log] [blame]
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -03001/*
2 * Phonebook access through D-Bus vCard and call history service
3 *
4 * Copyright (C) 2010 Nokia Corporation
5 *
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 *
21 */
22
Cristian Rodríguez2e772c22012-12-23 18:59:25 -080023#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -030027#include <string.h>
28#include <stdlib.h>
Vinicius Costa Gomes6a77a7b2010-06-10 11:51:37 -030029#include <time.h>
30#include <stdio.h>
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -030031#include <errno.h>
32#include <glib.h>
33#include <dbus/dbus.h>
Radoslaw Jablonskid12ed5f2011-02-03 11:43:23 +020034#include <libtracker-sparql/tracker-sparql.h>
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -030035
Marcel Holtmann7a72ebe2015-03-01 01:38:12 -080036#include "obexd/src/log.h"
37#include "obexd/src/obex.h"
38#include "obexd/src/service.h"
39#include "obexd/src/mimetype.h"
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -030040#include "phonebook.h"
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -030041#include "vcard.h"
42
43#define TRACKER_SERVICE "org.freedesktop.Tracker1"
44#define TRACKER_RESOURCES_PATH "/org/freedesktop/Tracker1/Resources"
45#define TRACKER_RESOURCES_INTERFACE "org.freedesktop.Tracker1.Resources"
46
Vinicius Costa Gomes4d2577c2010-05-31 15:00:42 -030047#define TRACKER_DEFAULT_CONTACT_ME "http://www.semanticdesktop.org/ontologies/2007/03/22/nco#default-contact-me"
Radoslaw Jablonski894363b2010-12-02 18:02:08 +020048#define AFFILATION_HOME "Home"
49#define AFFILATION_WORK "Work"
Bartosz Szatkowskic1faa662010-11-15 13:01:36 +010050#define ADDR_FIELD_AMOUNT 7
Radoslaw Jablonski457e4f52011-01-07 11:03:38 +020051#define PULL_QUERY_COL_AMOUNT 23
Radoslaw Jablonski0c004302010-10-26 11:29:52 +030052#define COUNT_QUERY_COL_AMOUNT 1
Bartosz Szatkowskic1faa662010-11-15 13:01:36 +010053
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +020054#define COL_PHONE_AFF 0 /* work/home phone numbers */
Bartosz Szatkowskic1faa662010-11-15 13:01:36 +010055#define COL_FULL_NAME 1
56#define COL_FAMILY_NAME 2
57#define COL_GIVEN_NAME 3
58#define COL_ADDITIONAL_NAME 4
59#define COL_NAME_PREFIX 5
60#define COL_NAME_SUFFIX 6
Radoslaw Jablonski457e4f52011-01-07 11:03:38 +020061#define COL_ADDR_AFF 7 /* addresses from affilation */
62#define COL_BIRTH_DATE 8
63#define COL_NICKNAME 9
64#define COL_URL 10
65#define COL_PHOTO 11
66#define COL_ORG_ROLE 12
67#define COL_UID 13
68#define COL_TITLE 14
69#define COL_AFF_TYPE 15
70#define COL_ORG_NAME 16
71#define COL_ORG_DEPARTMENT 17
72#define COL_EMAIL_AFF 18 /* email's from affilation (work/home) */
73#define COL_DATE 19
74#define COL_SENT 20
75#define COL_ANSWERED 21
76#define CONTACTS_ID_COL 22
Rafal Michalski11970bc2011-02-28 13:03:52 +010077#define CONTACT_ID_PREFIX "urn:uuid:"
Bartosz Szatkowski9e87d212011-07-13 16:20:04 +020078#define CALL_ID_PREFIX "message:"
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -030079
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +020080#define FAX_NUM_TYPE "http://www.semanticdesktop.org/ontologies/2007/03/22/nco#FaxNumber"
81#define MOBILE_NUM_TYPE "http://www.semanticdesktop.org/ontologies/2007/03/22/nco#CellPhoneNumber"
82
83#define MAIN_DELIM "\30" /* Main delimiter between phones, addresses, emails*/
84#define SUB_DELIM "\31" /* Delimiter used in telephone number strings*/
Rafal Michalski34d1a732011-08-22 12:32:57 +020085#define ADDR_DELIM "\37" /* Delimiter used for address data fields */
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +020086#define MAX_FIELDS 100 /* Max amount of fields to be concatenated at once*/
Radoslaw Jablonski84799cd2011-02-14 11:19:51 +020087#define VCARDS_PART_COUNT 50 /* amount of vcards sent at once to PBAP core */
88#define QUERY_OFFSET_FORMAT "%s OFFSET %d"
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +020089
Vinicius Costa Gomes13a97df2010-05-17 20:49:18 -030090#define CONTACTS_QUERY_ALL \
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +020091"SELECT " \
Radoslaw Jablonski41f45782011-01-04 14:23:56 +020092"(SELECT GROUP_CONCAT(fn:concat(rdf:type(?aff_number)," \
93"\"\31\", nco:phoneNumber(?aff_number)), \"\30\")" \
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +020094"WHERE {" \
Radoslaw Jablonski41f45782011-01-04 14:23:56 +020095" ?_role nco:hasPhoneNumber ?aff_number" \
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +020096"}) " \
97"nco:fullname(?_contact) " \
98"nco:nameFamily(?_contact) " \
99"nco:nameGiven(?_contact) " \
100"nco:nameAdditional(?_contact) " \
101"nco:nameHonorificPrefix(?_contact) " \
102"nco:nameHonorificSuffix(?_contact) " \
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +0200103"(SELECT GROUP_CONCAT(fn:concat(" \
Rafal Michalski34d1a732011-08-22 12:32:57 +0200104"tracker:coalesce(nco:pobox(?aff_addr), \"\"), \"\37\"," \
105"tracker:coalesce(nco:extendedAddress(?aff_addr), \"\"), \"\37\"," \
106"tracker:coalesce(nco:streetAddress(?aff_addr), \"\"), \"\37\"," \
107"tracker:coalesce(nco:locality(?aff_addr), \"\"), \"\37\"," \
108"tracker:coalesce(nco:region(?aff_addr), \"\"), \"\37\"," \
109"tracker:coalesce(nco:postalcode(?aff_addr), \"\"), \"\37\"," \
Radoslaw Jablonski1e73e0a2011-01-05 11:48:15 +0200110"tracker:coalesce(nco:country(?aff_addr), \"\"), " \
111"\"\31\", rdfs:label(?_role) ), " \
112"\"\30\") " \
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +0200113"WHERE {" \
114"?_role nco:hasPostalAddress ?aff_addr" \
115"}) " \
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +0200116"nco:birthDate(?_contact) " \
Slawomir Bochenskie24d6192011-11-14 15:31:52 +0100117"(SELECT " \
118" ?nick " \
119" WHERE { " \
120" { " \
121" ?_contact nco:nickname ?nick " \
122" } UNION { " \
123" ?_contact nco:hasAffiliation ?role . " \
124" ?role nco:hasIMAddress ?im . " \
125" ?im nco:imNickname ?nick " \
126" } " \
127" } " \
128") " \
Radoslaw Jablonski495db2b2011-01-13 13:53:12 +0200129"(SELECT GROUP_CONCAT(fn:concat( " \
Rafal Michalski7ffd0a22011-11-04 15:00:51 +0100130 "?url_val, \"\31\", tracker:coalesce(rdfs:label(?_role), \"\") "\
Radoslaw Jablonski495db2b2011-01-13 13:53:12 +0200131 "), \"\30\") " \
132 "WHERE {" \
133 "?_role nco:url ?url_val . " \
134"})" \
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +0200135"nie:url(nco:photo(?_contact)) " \
136"nco:role(?_role) " \
137"nco:contactUID(?_contact) " \
138"nco:title(?_role) " \
139"rdfs:label(?_role) " \
140"nco:fullname(nco:org(?_role))" \
141"nco:department(?_role) " \
Radoslaw Jablonski7e7ab3e2011-01-07 10:19:57 +0200142"(SELECT GROUP_CONCAT(fn:concat(?emailaddress,\"\31\"," \
Bartosz Szatkowski7576ca82011-08-05 13:01:30 +0200143 "tracker:coalesce(rdfs:label(?_role), \"\"))," \
Radoslaw Jablonski7e7ab3e2011-01-07 10:19:57 +0200144 "\"\30\") " \
145 "WHERE { " \
146 "?_role nco:hasEmailAddress " \
147 " [ nco:emailAddress ?emailaddress ] " \
148 "}) " \
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +0200149"\"NOTACALL\" \"false\" \"false\" " \
150"?_contact " \
151"WHERE {" \
Lukasz Pawlikeb108c62011-02-28 16:19:43 +0100152" ?_contact a nco:PersonContact ." \
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +0200153" OPTIONAL {?_contact nco:hasAffiliation ?_role .}" \
154"}" \
Lukasz Pawlikeb108c62011-02-28 16:19:43 +0100155"ORDER BY tracker:id(?_contact)"
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -0300156
Vinicius Costa Gomes13a97df2010-05-17 20:49:18 -0300157#define CONTACTS_QUERY_ALL_LIST \
Vinicius Costa Gomesf0e2e1d2010-06-07 19:42:38 -0300158 "SELECT ?c nco:nameFamily(?c) " \
Vinicius Costa Gomes13a97df2010-05-17 20:49:18 -0300159 "nco:nameGiven(?c) nco:nameAdditional(?c) " \
160 "nco:nameHonorificPrefix(?c) nco:nameHonorificSuffix(?c) " \
Slawomir Bochenskie24d6192011-11-14 15:31:52 +0100161 "(SELECT " \
162 "?nick " \
163 "WHERE { " \
164 "{ " \
165 "?c nco:nickname ?nick " \
166 "} UNION { " \
167 "?c nco:hasAffiliation ?role . " \
168 "?role nco:hasIMAddress ?im . " \
169 "?im nco:imNickname ?nick " \
170 "} " \
171 "} " \
172 ") " \
Bartosz Szatkowski5f944a22011-07-13 16:20:03 +0200173 "nco:phoneNumber(?h) " \
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -0300174 "WHERE { " \
Vinicius Costa Gomes1e057ba2010-06-09 15:39:18 -0300175 "?c a nco:PersonContact . " \
Vinicius Costa Gomesf0e2e1d2010-06-07 19:42:38 -0300176 "OPTIONAL { ?c nco:hasPhoneNumber ?h . } " \
Radoslaw Jablonski9c3dda92010-07-22 15:06:11 +0300177 "OPTIONAL { " \
178 "?c nco:hasAffiliation ?a . " \
179 "?a nco:hasPhoneNumber ?h . " \
180 "} " \
Radoslaw Jablonskie5018a72010-08-09 14:17:03 +0300181 "} GROUP BY ?c"
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -0300182
Slawomir Bochenskiba56a432011-05-18 15:05:10 +0200183#define CALLS_CONSTRAINTS(CONSTRAINT) \
184" WHERE { " \
185 "?_call a nmo:Call . " \
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +0200186 "?_unb_contact a nco:Contact . " \
Slawomir Bochenskiba56a432011-05-18 15:05:10 +0200187 "?_unb_contact nco:hasPhoneNumber ?_cpn . " \
Slawomir Bochenskibe4faac2011-06-14 09:09:00 +0200188CONSTRAINT \
Slawomir Bochenskiba56a432011-05-18 15:05:10 +0200189 "OPTIONAL { " \
Slawomir Bochenskidf0740c2011-08-12 15:18:48 +0200190 "{ SELECT ?_contact ?_no ?_role ?_number " \
Slawomir Bochenskiba56a432011-05-18 15:05:10 +0200191 "count(?_contact) as ?cnt " \
192 "WHERE { " \
193 "?_contact a nco:PersonContact . " \
194 "{ " \
195 "?_contact nco:hasAffiliation ?_role . "\
196 "?_role nco:hasPhoneNumber ?_number . " \
197 "} UNION { " \
198 "?_contact nco:hasPhoneNumber ?_number" \
199 "} " \
200 "?_number maemo:localPhoneNumber ?_no . " \
Slawomir Bochenskidf0740c2011-08-12 15:18:48 +0200201 "} GROUP BY ?_no } " \
Slawomir Bochenskiba56a432011-05-18 15:05:10 +0200202 "FILTER(?cnt = 1) " \
Slawomir Bochenskidf0740c2011-08-12 15:18:48 +0200203 "?_cpn maemo:localPhoneNumber ?_no . " \
Radoslaw Jablonski05993682010-10-21 15:26:39 +0300204 "} " \
Slawomir Bochenskiba56a432011-05-18 15:05:10 +0200205"} "
Vinicius Costa Gomes18432562010-04-14 19:56:22 -0300206
Slawomir Bochenskiba56a432011-05-18 15:05:10 +0200207#define CALLS_LIST(CONSTRAINT) \
Bartosz Szatkowski9e87d212011-07-13 16:20:04 +0200208"SELECT ?_call nco:nameFamily(?_contact) " \
Slawomir Bochenskiba56a432011-05-18 15:05:10 +0200209 "nco:nameGiven(?_contact) nco:nameAdditional(?_contact) " \
210 "nco:nameHonorificPrefix(?_contact) " \
211 "nco:nameHonorificSuffix(?_contact) " \
Slawomir Bochenskie24d6192011-11-14 15:31:52 +0100212 "(SELECT " \
213 "?nick " \
214 "WHERE { " \
215 "{ " \
216 "?_contact nco:nickname ?nick " \
217 "} UNION { " \
218 "?_contact nco:hasAffiliation ?role . " \
219 "?role nco:hasIMAddress ?im . " \
220 "?im nco:imNickname ?nick " \
221 "} " \
222 "} " \
223 ") " \
Bartosz Szatkowski5f944a22011-07-13 16:20:03 +0200224 "nco:phoneNumber(?_cpn) " \
Slawomir Bochenskiba56a432011-05-18 15:05:10 +0200225CALLS_CONSTRAINTS(CONSTRAINT) \
226"ORDER BY DESC(nmo:sentDate(?_call)) "
227
228#define CALLS_QUERY(CONSTRAINT) \
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +0200229"SELECT " \
Radoslaw Jablonski41f45782011-01-04 14:23:56 +0200230"(SELECT fn:concat(rdf:type(?role_number)," \
231 "\"\31\", nco:phoneNumber(?role_number))" \
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +0200232 "WHERE {" \
Radoslaw Jablonskiafe2e6a2011-01-11 15:35:51 +0200233 "{" \
234 " ?_role nco:hasPhoneNumber ?role_number " \
235 " FILTER (?role_number = ?_number)" \
236 "} UNION { " \
237 "?_unb_contact nco:hasPhoneNumber ?role_number . " \
Slawomir Bochenskiba56a432011-05-18 15:05:10 +0200238 " FILTER (!bound(?_role)) " \
Radoslaw Jablonskiafe2e6a2011-01-11 15:35:51 +0200239 "}" \
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +0200240"} GROUP BY nco:phoneNumber(?role_number) ) " \
241 "nco:fullname(?_contact) " \
242 "nco:nameFamily(?_contact) " \
243 "nco:nameGiven(?_contact) " \
244 "nco:nameAdditional(?_contact) " \
245 "nco:nameHonorificPrefix(?_contact) " \
246 "nco:nameHonorificSuffix(?_contact) " \
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +0200247"(SELECT GROUP_CONCAT(fn:concat(" \
Rafal Michalski34d1a732011-08-22 12:32:57 +0200248 "tracker:coalesce(nco:pobox(?aff_addr), \"\"), \"\37\"," \
249 "tracker:coalesce(nco:extendedAddress(?aff_addr), \"\"), \"\37\","\
250 "tracker:coalesce(nco:streetAddress(?aff_addr), \"\"), \"\37\","\
251 "tracker:coalesce(nco:locality(?aff_addr), \"\"), \"\37\"," \
252 "tracker:coalesce(nco:region(?aff_addr), \"\"), \"\37\"," \
253 "tracker:coalesce(nco:postalcode(?aff_addr), \"\"), \"\37\"," \
Radoslaw Jablonski1e73e0a2011-01-05 11:48:15 +0200254 "tracker:coalesce(nco:country(?aff_addr), \"\"), " \
255 "\"\31\", rdfs:label(?c_role) ), " \
256 "\"\30\") " \
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +0200257 "WHERE {" \
Radoslaw Jablonski1e73e0a2011-01-05 11:48:15 +0200258 "?_contact nco:hasAffiliation ?c_role . " \
259 "?c_role nco:hasPostalAddress ?aff_addr" \
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +0200260 "}) " \
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +0200261 "nco:birthDate(?_contact) " \
Slawomir Bochenskie24d6192011-11-14 15:31:52 +0100262"(SELECT " \
263 "?nick " \
264 "WHERE { " \
265 " { " \
266 " ?_contact nco:nickname ?nick " \
267 " } UNION { " \
268 " ?_contact nco:hasAffiliation ?role . " \
269 " ?role nco:hasIMAddress ?im . " \
270 " ?im nco:imNickname ?nick " \
271 " } " \
272 " } " \
273 ") " \
Rafal Michalski7ffd0a22011-11-04 15:00:51 +0100274"(SELECT GROUP_CONCAT(fn:concat(?url_value, \"\31\", " \
275 "tracker:coalesce(rdfs:label(?c_role), \"\")), \"\30\") " \
Radoslaw Jablonski495db2b2011-01-13 13:53:12 +0200276 "WHERE {" \
277 "?_contact nco:hasAffiliation ?c_role . " \
278 "?c_role nco:url ?url_value . " \
Radoslaw Jablonski495db2b2011-01-13 13:53:12 +0200279"})" \
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +0200280 "nie:url(nco:photo(?_contact)) " \
281 "nco:role(?_role) " \
282 "nco:contactUID(?_contact) " \
283 "nco:title(?_role) " \
284 "rdfs:label(?_role) " \
285 "nco:fullname(nco:org(?_role)) " \
286 "nco:department(?_role) " \
Radoslaw Jablonski7e7ab3e2011-01-07 10:19:57 +0200287"(SELECT GROUP_CONCAT(fn:concat(?emailaddress,\"\31\"," \
Bartosz Szatkowski7576ca82011-08-05 13:01:30 +0200288 "tracker:coalesce(rdfs:label(?c_role), \"\"))," \
Radoslaw Jablonski7e7ab3e2011-01-07 10:19:57 +0200289 "\"\30\") " \
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -0300290 "WHERE { " \
Radoslaw Jablonski7e7ab3e2011-01-07 10:19:57 +0200291 "?_contact nco:hasAffiliation ?c_role . " \
292 "?c_role nco:hasEmailAddress " \
293 " [ nco:emailAddress ?emailaddress ] " \
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +0200294 "}) " \
295 "nmo:receivedDate(?_call) " \
296 "nmo:isSent(?_call) " \
297 "nmo:isAnswered(?_call) " \
Slawomir Bochenski69caa022011-05-24 10:02:52 +0200298 "?_call " \
Slawomir Bochenskiba56a432011-05-18 15:05:10 +0200299CALLS_CONSTRAINTS(CONSTRAINT) \
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +0200300"ORDER BY DESC(nmo:sentDate(?_call)) "
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -0300301
Slawomir Bochenskiba56a432011-05-18 15:05:10 +0200302#define MISSED_CONSTRAINT \
303"?_call nmo:from ?_unb_contact . " \
304"?_call nmo:isSent false . " \
305"?_call nmo:isAnswered false . "
Vinicius Costa Gomes18432562010-04-14 19:56:22 -0300306
Slawomir Bochenskiba56a432011-05-18 15:05:10 +0200307#define INCOMING_CONSTRAINT \
308"?_call nmo:from ?_unb_contact . " \
309"?_call nmo:isSent false . " \
310"?_call nmo:isAnswered true . "
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -0300311
Slawomir Bochenskiba56a432011-05-18 15:05:10 +0200312#define OUTGOING_CONSTRAINT \
313"?_call nmo:to ?_unb_contact . " \
314"?_call nmo:isSent true . "
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -0300315
Slawomir Bochenskiba56a432011-05-18 15:05:10 +0200316#define COMBINED_CONSTRAINT \
317"{ " \
318" ?_call nmo:from ?_unb_contact . " \
319" ?_call nmo:isSent false " \
320"} UNION { " \
321" ?_call nmo:to ?_unb_contact . " \
322" ?_call nmo:isSent true " \
323"} "
Vinicius Costa Gomes18432562010-04-14 19:56:22 -0300324
Bartosz Szatkowski9e87d212011-07-13 16:20:04 +0200325#define CALL_URI_CONSTRAINT \
326COMBINED_CONSTRAINT \
327"FILTER (?_call = <%s>) "
328
Slawomir Bochenskiba56a432011-05-18 15:05:10 +0200329#define MISSED_CALLS_QUERY CALLS_QUERY(MISSED_CONSTRAINT)
330#define MISSED_CALLS_LIST CALLS_LIST(MISSED_CONSTRAINT)
331#define INCOMING_CALLS_QUERY CALLS_QUERY(INCOMING_CONSTRAINT)
332#define INCOMING_CALLS_LIST CALLS_LIST(INCOMING_CONSTRAINT)
333#define OUTGOING_CALLS_QUERY CALLS_QUERY(OUTGOING_CONSTRAINT)
334#define OUTGOING_CALLS_LIST CALLS_LIST(OUTGOING_CONSTRAINT)
335#define COMBINED_CALLS_QUERY CALLS_QUERY(COMBINED_CONSTRAINT)
336#define COMBINED_CALLS_LIST CALLS_LIST(COMBINED_CONSTRAINT)
Bartosz Szatkowski9e87d212011-07-13 16:20:04 +0200337#define CONTACT_FROM_CALL_QUERY CALLS_QUERY(CALL_URI_CONSTRAINT)
Vinicius Costa Gomes18432562010-04-14 19:56:22 -0300338
Vinicius Costa Gomes13a97df2010-05-17 20:49:18 -0300339#define CONTACTS_QUERY_FROM_URI \
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +0200340"SELECT " \
Radoslaw Jablonski41f45782011-01-04 14:23:56 +0200341"(SELECT GROUP_CONCAT(fn:concat(rdf:type(?aff_number)," \
342"\"\31\", nco:phoneNumber(?aff_number)), \"\30\")" \
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +0200343"WHERE {" \
Radoslaw Jablonski41f45782011-01-04 14:23:56 +0200344" ?_role nco:hasPhoneNumber ?aff_number" \
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +0200345"}) " \
346"nco:fullname(<%s>) " \
347"nco:nameFamily(<%s>) " \
348"nco:nameGiven(<%s>) " \
349"nco:nameAdditional(<%s>) " \
350"nco:nameHonorificPrefix(<%s>) " \
351"nco:nameHonorificSuffix(<%s>) " \
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +0200352"(SELECT GROUP_CONCAT(fn:concat(" \
Rafal Michalski34d1a732011-08-22 12:32:57 +0200353"tracker:coalesce(nco:pobox(?aff_addr), \"\"), \"\37\"," \
354"tracker:coalesce(nco:extendedAddress(?aff_addr), \"\"), \"\37\"," \
355"tracker:coalesce(nco:streetAddress(?aff_addr), \"\"), \"\37\"," \
356"tracker:coalesce(nco:locality(?aff_addr), \"\"), \"\37\"," \
357"tracker:coalesce(nco:region(?aff_addr), \"\"), \"\37\"," \
358"tracker:coalesce(nco:postalcode(?aff_addr), \"\"), \"\37\"," \
Radoslaw Jablonski1e73e0a2011-01-05 11:48:15 +0200359"tracker:coalesce(nco:country(?aff_addr), \"\"), " \
360"\"\31\", rdfs:label(?_role) ), " \
361"\"\30\") " \
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +0200362"WHERE {" \
363"?_role nco:hasPostalAddress ?aff_addr" \
364"}) " \
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +0200365"nco:birthDate(<%s>) " \
Slawomir Bochenskie24d6192011-11-14 15:31:52 +0100366"(SELECT " \
367" ?nick " \
368" WHERE { " \
369" { " \
370" ?_contact nco:nickname ?nick " \
371" } UNION { " \
372" ?_contact nco:hasAffiliation ?role . " \
373" ?role nco:hasIMAddress ?im . " \
374" ?im nco:imNickname ?nick " \
375" } " \
376" FILTER (?_contact = <%s>)" \
377" } " \
378") " \
Radoslaw Jablonski495db2b2011-01-13 13:53:12 +0200379"(SELECT GROUP_CONCAT(fn:concat( " \
Rafal Michalski7ffd0a22011-11-04 15:00:51 +0100380 "?url_val, \"\31\", tracker:coalesce(rdfs:label(?_role), \"\") "\
Radoslaw Jablonski495db2b2011-01-13 13:53:12 +0200381 "), \"\30\") " \
382 "WHERE {" \
383 "?_role nco:url ?url_val . " \
384"})" \
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +0200385"nie:url(nco:photo(<%s>)) " \
386"nco:role(?_role) " \
387"nco:contactUID(<%s>) " \
388"nco:title(?_role) " \
389"rdfs:label(?_role) " \
390"nco:fullname(nco:org(?_role))" \
391"nco:department(?_role) " \
Radoslaw Jablonski7e7ab3e2011-01-07 10:19:57 +0200392"(SELECT GROUP_CONCAT(fn:concat(?emailaddress,\"\31\"," \
Bartosz Szatkowski7576ca82011-08-05 13:01:30 +0200393 "tracker:coalesce(rdfs:label(?_role), \"\"))," \
Radoslaw Jablonski7e7ab3e2011-01-07 10:19:57 +0200394 "\"\30\") " \
395 "WHERE { " \
396 "?_role nco:hasEmailAddress " \
397 " [ nco:emailAddress ?emailaddress ] " \
398 "}) " \
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +0200399"\"NOTACALL\" \"false\" \"false\" " \
400"<%s> " \
401"WHERE {" \
Rafal Michalski13f57962011-01-26 13:33:06 +0100402" <%s> a nco:PersonContact ." \
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +0200403" OPTIONAL {<%s> nco:hasAffiliation ?_role .}" \
Rafal Michalski13f57962011-01-26 13:33:06 +0100404"}"
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -0300405
Rafal Michalski6bc7e012010-10-25 11:04:58 +0200406#define CONTACTS_OTHER_QUERY_FROM_URI \
Rafal Michalski091560b2011-01-12 16:15:38 +0100407 "SELECT fn:concat(\"TYPE_OTHER\", \"\31\", nco:phoneNumber(?t))"\
408 "\"\" \"\" \"\" \"\" \"\" \"\" \"\" \"\" " \
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +0200409 "\"\" \"\" \"\" \"\" \"\" \"\" \"\" \"\" \"\" \"\" " \
Rafal Michalski091560b2011-01-12 16:15:38 +0100410 " \"NOTACALL\" \"false\" \"false\" <%s> " \
Rafal Michalski6bc7e012010-10-25 11:04:58 +0200411 "WHERE { " \
412 "<%s> a nco:Contact . " \
Rafal Michalskid57b8fa2010-11-29 14:51:56 +0100413 "OPTIONAL { <%s> nco:hasPhoneNumber ?t . } " \
Rafal Michalski6bc7e012010-10-25 11:04:58 +0200414 "} "
415
Radoslaw Jablonski0c004302010-10-26 11:29:52 +0300416#define CONTACTS_COUNT_QUERY \
417 "SELECT COUNT(?c) " \
418 "WHERE {" \
419 "?c a nco:PersonContact ." \
Radoslaw Jablonski0c004302010-10-26 11:29:52 +0300420 "}"
421
422#define MISSED_CALLS_COUNT_QUERY \
423 "SELECT COUNT(?call) WHERE {" \
424 "?c a nco:Contact ;" \
425 "nco:hasPhoneNumber ?h ." \
426 "?call a nmo:Call ;" \
427 "nmo:isSent false ;" \
428 "nmo:from ?c ;" \
429 "nmo:isAnswered false ." \
430 "}"
431
432#define INCOMING_CALLS_COUNT_QUERY \
433 "SELECT COUNT(?call) WHERE {" \
434 "?c a nco:Contact ;" \
435 "nco:hasPhoneNumber ?h ." \
436 "?call a nmo:Call ;" \
437 "nmo:isSent false ;" \
438 "nmo:from ?c ;" \
439 "nmo:isAnswered true ." \
440 "}"
441
442#define OUTGOING_CALLS_COUNT_QUERY \
443 "SELECT COUNT(?call) WHERE {" \
444 "?c a nco:Contact ;" \
445 "nco:hasPhoneNumber ?h ." \
446 "?call a nmo:Call ;" \
447 "nmo:isSent true ;" \
448 "nmo:to ?c ." \
449 "}"
450
451#define COMBINED_CALLS_COUNT_QUERY \
452 "SELECT COUNT(?call) WHERE {" \
453 "{" \
454 "?c a nco:Contact ;" \
455 "nco:hasPhoneNumber ?h ." \
456 "?call a nmo:Call ;" \
457 "nmo:isSent true ;" \
458 "nmo:to ?c ." \
459 "}UNION {" \
460 "?c a nco:Contact ;" \
461 "nco:hasPhoneNumber ?h ." \
462 "?call a nmo:Call ;" \
463 "nmo:from ?c ." \
464 "}" \
465 "}"
466
Slawomir Bochenski2b3644a2011-08-24 12:12:23 +0200467#define NEW_MISSED_CALLS_COUNT_QUERY \
468 "SELECT COUNT(?call) WHERE {" \
469 "?c a nco:Contact ;" \
470 "nco:hasPhoneNumber ?h ." \
471 "?call a nmo:Call ;" \
472 "nmo:isSent false ;" \
473 "nmo:from ?c ;" \
474 "nmo:isAnswered false ;" \
475 "nmo:isRead false ." \
476 "}"
Dmitriy Paliyf82b81e2011-01-02 19:20:40 +0200477
Radoslaw Jablonski3f347cf2011-02-14 11:19:46 +0200478typedef int (*reply_list_foreach_t) (const char **reply, int num_fields,
Johan Hedberg21e62142010-10-29 10:39:41 -0400479 void *user_data);
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -0300480
Radoslaw Jablonski8c10c122011-01-13 09:39:01 +0200481typedef void (*add_field_t) (struct phonebook_contact *contact,
482 const char *value, int type);
483
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -0300484struct pending_reply {
485 reply_list_foreach_t callback;
486 void *user_data;
487 int num_fields;
488};
489
Radoslaw Jablonski402eb672010-08-10 10:23:20 +0300490struct contact_data {
491 char *id;
492 struct phonebook_contact *contact;
493};
494
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -0300495struct phonebook_data {
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -0300496 phonebook_cb cb;
497 void *user_data;
498 int index;
Vinicius Costa Gomes13a97df2010-05-17 20:49:18 -0300499 gboolean vcardentry;
Vinicius Costa Gomes9bd2e412010-04-16 18:13:23 -0300500 const struct apparam_field *params;
Radoslaw Jablonski402eb672010-08-10 10:23:20 +0300501 GSList *contacts;
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -0300502 phonebook_cache_ready_cb ready_cb;
503 phonebook_entry_cb entry_cb;
Dmitriy Paliyf82b81e2011-01-02 19:20:40 +0200504 int newmissedcalls;
Radoslaw Jablonskid12ed5f2011-02-03 11:43:23 +0200505 GCancellable *query_canc;
Radoslaw Jablonski71695872011-02-14 11:19:50 +0200506 char *req_name;
Radoslaw Jablonski84799cd2011-02-14 11:19:51 +0200507 int vcard_part_count;
508 int tracker_index;
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -0300509};
510
511struct phonebook_index {
512 GArray *phonebook;
513 int index;
514};
515
Radoslaw Jablonskid12ed5f2011-02-03 11:43:23 +0200516static TrackerSparqlConnection *connection = NULL;
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -0300517
Vinicius Costa Gomes18432562010-04-14 19:56:22 -0300518static const char *name2query(const char *name)
519{
Harald Schmitta8061412012-07-18 16:53:08 +0200520 if (g_str_equal(name, PB_CONTACTS))
Vinicius Costa Gomes18432562010-04-14 19:56:22 -0300521 return CONTACTS_QUERY_ALL;
Harald Schmitta8061412012-07-18 16:53:08 +0200522 else if (g_str_equal(name, PB_CALLS_INCOMING))
Vinicius Costa Gomes18432562010-04-14 19:56:22 -0300523 return INCOMING_CALLS_QUERY;
Harald Schmitta8061412012-07-18 16:53:08 +0200524 else if (g_str_equal(name, PB_CALLS_OUTGOING))
Vinicius Costa Gomes18432562010-04-14 19:56:22 -0300525 return OUTGOING_CALLS_QUERY;
Harald Schmitta8061412012-07-18 16:53:08 +0200526 else if (g_str_equal(name, PB_CALLS_MISSED))
Vinicius Costa Gomes18432562010-04-14 19:56:22 -0300527 return MISSED_CALLS_QUERY;
Harald Schmitta8061412012-07-18 16:53:08 +0200528 else if (g_str_equal(name, PB_CALLS_COMBINED))
Vinicius Costa Gomes18432562010-04-14 19:56:22 -0300529 return COMBINED_CALLS_QUERY;
530
531 return NULL;
532}
533
Radoslaw Jablonski0c004302010-10-26 11:29:52 +0300534static const char *name2count_query(const char *name)
535{
Harald Schmitta8061412012-07-18 16:53:08 +0200536 if (g_str_equal(name, PB_CONTACTS))
Radoslaw Jablonski0c004302010-10-26 11:29:52 +0300537 return CONTACTS_COUNT_QUERY;
Harald Schmitta8061412012-07-18 16:53:08 +0200538 else if (g_str_equal(name, PB_CALLS_INCOMING))
Radoslaw Jablonski0c004302010-10-26 11:29:52 +0300539 return INCOMING_CALLS_COUNT_QUERY;
Harald Schmitta8061412012-07-18 16:53:08 +0200540 else if (g_str_equal(name, PB_CALLS_OUTGOING))
Radoslaw Jablonski0c004302010-10-26 11:29:52 +0300541 return OUTGOING_CALLS_COUNT_QUERY;
Harald Schmitta8061412012-07-18 16:53:08 +0200542 else if (g_str_equal(name, PB_CALLS_MISSED))
Radoslaw Jablonski0c004302010-10-26 11:29:52 +0300543 return MISSED_CALLS_COUNT_QUERY;
Harald Schmitta8061412012-07-18 16:53:08 +0200544 else if (g_str_equal(name, PB_CALLS_COMBINED))
Radoslaw Jablonski0c004302010-10-26 11:29:52 +0300545 return COMBINED_CALLS_COUNT_QUERY;
546
547 return NULL;
548}
549
Vinicius Costa Gomes18432562010-04-14 19:56:22 -0300550static gboolean folder_is_valid(const char *folder)
551{
Claudio Takahasi696b9042010-05-27 15:04:41 -0300552 if (folder == NULL)
553 return FALSE;
554
Vinicius Costa Gomes18432562010-04-14 19:56:22 -0300555 if (g_str_equal(folder, "/"))
556 return TRUE;
Harald Schmitta8061412012-07-18 16:53:08 +0200557 else if (g_str_equal(folder, PB_TELECOM_FOLDER))
Vinicius Costa Gomes18432562010-04-14 19:56:22 -0300558 return TRUE;
Harald Schmitta8061412012-07-18 16:53:08 +0200559 else if (g_str_equal(folder, PB_CONTACTS_FOLDER))
Vinicius Costa Gomes18432562010-04-14 19:56:22 -0300560 return TRUE;
Harald Schmitta8061412012-07-18 16:53:08 +0200561 else if (g_str_equal(folder, PB_CALLS_INCOMING_FOLDER))
Vinicius Costa Gomes18432562010-04-14 19:56:22 -0300562 return TRUE;
Harald Schmitta8061412012-07-18 16:53:08 +0200563 else if (g_str_equal(folder, PB_CALLS_OUTGOING_FOLDER))
Vinicius Costa Gomes18432562010-04-14 19:56:22 -0300564 return TRUE;
Harald Schmitta8061412012-07-18 16:53:08 +0200565 else if (g_str_equal(folder, PB_CALLS_MISSED_FOLDER))
Vinicius Costa Gomes18432562010-04-14 19:56:22 -0300566 return TRUE;
Harald Schmitta8061412012-07-18 16:53:08 +0200567 else if (g_str_equal(folder, PB_CALLS_COMBINED_FOLDER))
Vinicius Costa Gomes18432562010-04-14 19:56:22 -0300568 return TRUE;
569
570 return FALSE;
571}
572
573static const char *folder2query(const char *folder)
574{
Harald Schmitta8061412012-07-18 16:53:08 +0200575 if (g_str_equal(folder, PB_CONTACTS_FOLDER))
Vinicius Costa Gomes18432562010-04-14 19:56:22 -0300576 return CONTACTS_QUERY_ALL_LIST;
Harald Schmitta8061412012-07-18 16:53:08 +0200577 else if (g_str_equal(folder, PB_CALLS_INCOMING_FOLDER))
Vinicius Costa Gomes18432562010-04-14 19:56:22 -0300578 return INCOMING_CALLS_LIST;
Harald Schmitta8061412012-07-18 16:53:08 +0200579 else if (g_str_equal(folder, PB_CALLS_OUTGOING_FOLDER))
Vinicius Costa Gomes18432562010-04-14 19:56:22 -0300580 return OUTGOING_CALLS_LIST;
Harald Schmitta8061412012-07-18 16:53:08 +0200581 else if (g_str_equal(folder, PB_CALLS_MISSED_FOLDER))
Vinicius Costa Gomes18432562010-04-14 19:56:22 -0300582 return MISSED_CALLS_LIST;
Harald Schmitta8061412012-07-18 16:53:08 +0200583 else if (g_str_equal(folder, PB_CALLS_COMBINED_FOLDER))
Vinicius Costa Gomes18432562010-04-14 19:56:22 -0300584 return COMBINED_CALLS_LIST;
585
586 return NULL;
587}
588
Radoslaw Jablonskid12ed5f2011-02-03 11:43:23 +0200589static const char **string_array_from_cursor(TrackerSparqlCursor *cursor,
590 int array_len)
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -0300591{
Radoslaw Jablonskid12ed5f2011-02-03 11:43:23 +0200592 const char **result;
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -0300593 int i;
594
Radoslaw Jablonskid12ed5f2011-02-03 11:43:23 +0200595 result = g_new0(const char *, array_len);
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -0300596
Radoslaw Jablonskid12ed5f2011-02-03 11:43:23 +0200597 for (i = 0; i < array_len; ++i) {
598 TrackerSparqlValueType type;
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -0300599
Radoslaw Jablonskid12ed5f2011-02-03 11:43:23 +0200600 type = tracker_sparql_cursor_get_value_type(cursor, i);
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -0300601
Radoslaw Jablonskid12ed5f2011-02-03 11:43:23 +0200602 if (type == TRACKER_SPARQL_VALUE_TYPE_BLANK_NODE ||
603 type == TRACKER_SPARQL_VALUE_TYPE_UNBOUND)
604 /* For null/unbound type filling result part with ""*/
605 result[i] = "";
606 else
607 /* Filling with string representation of content*/
608 result[i] = tracker_sparql_cursor_get_string(cursor, i,
609 NULL);
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -0300610 }
611
612 return result;
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -0300613}
614
Radoslaw Jablonskid12ed5f2011-02-03 11:43:23 +0200615static void update_cancellable(struct phonebook_data *pdata,
616 GCancellable *canc)
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -0300617{
Radoslaw Jablonskid12ed5f2011-02-03 11:43:23 +0200618 if (pdata->query_canc)
619 g_object_unref(pdata->query_canc);
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -0300620
Radoslaw Jablonskid12ed5f2011-02-03 11:43:23 +0200621 pdata->query_canc = canc;
Dmitriy Paliy3b05d5e2010-12-09 12:05:18 +0200622}
623
Radoslaw Jablonskid12ed5f2011-02-03 11:43:23 +0200624static void async_query_cursor_next_cb(GObject *source, GAsyncResult *result,
625 gpointer user_data)
Dmitriy Paliy3b05d5e2010-12-09 12:05:18 +0200626{
627 struct pending_reply *pending = user_data;
Radoslaw Jablonskid12ed5f2011-02-03 11:43:23 +0200628 TrackerSparqlCursor *cursor = TRACKER_SPARQL_CURSOR(source);
629 GCancellable *cancellable;
630 GError *error = NULL;
631 gboolean success;
632 const char **node;
Radoslaw Jablonski3f347cf2011-02-14 11:19:46 +0200633 int err;
Dmitriy Paliy3b05d5e2010-12-09 12:05:18 +0200634
Radoslaw Jablonskid12ed5f2011-02-03 11:43:23 +0200635 success = tracker_sparql_cursor_next_finish(
636 TRACKER_SPARQL_CURSOR(source),
637 result, &error);
Dmitriy Paliy3b05d5e2010-12-09 12:05:18 +0200638
Radoslaw Jablonskid12ed5f2011-02-03 11:43:23 +0200639 if (!success) {
640 if (error) {
641 DBG("cursor_next error: %s", error->message);
642 g_error_free(error);
643 } else
644 /* When tracker_sparql_cursor_next_finish ends with
645 * failure and no error is set, that means end of
646 * results returned by query */
647 pending->callback(NULL, 0, pending->user_data);
648
649 goto failed;
650 }
651
652 node = string_array_from_cursor(cursor, pending->num_fields);
Radoslaw Jablonski3f347cf2011-02-14 11:19:46 +0200653 err = pending->callback(node, pending->num_fields, pending->user_data);
Radoslaw Jablonskid12ed5f2011-02-03 11:43:23 +0200654 g_free(node);
655
Radoslaw Jablonski3f347cf2011-02-14 11:19:46 +0200656 /* Fetch next result only if processing current chunk ended with
657 * success. Sometimes during processing data, we are able to determine
658 * if there is no need to get more data from tracker - by example
659 * stored amount of data parts is big enough for sending and we might
660 * want to suspend processing or just some error occurred. */
661 if (!err) {
662 cancellable = g_cancellable_new();
663 update_cancellable(pending->user_data, cancellable);
664 tracker_sparql_cursor_next_async(cursor, cancellable,
Radoslaw Jablonskid12ed5f2011-02-03 11:43:23 +0200665 async_query_cursor_next_cb,
666 pending);
Radoslaw Jablonski3f347cf2011-02-14 11:19:46 +0200667 return;
668 }
Radoslaw Jablonskid12ed5f2011-02-03 11:43:23 +0200669
670failed:
671 g_object_unref(cursor);
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -0300672 g_free(pending);
673}
674
Radoslaw Jablonski438be132011-02-14 11:19:45 +0200675static int query_tracker(const char *query, int num_fields,
676 reply_list_foreach_t callback, void *user_data)
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -0300677{
678 struct pending_reply *pending;
Radoslaw Jablonskid12ed5f2011-02-03 11:43:23 +0200679 GCancellable *cancellable;
680 TrackerSparqlCursor *cursor;
681 GError *error = NULL;
682
683 DBG("");
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -0300684
685 if (connection == NULL)
Radoslaw Jablonskid12ed5f2011-02-03 11:43:23 +0200686 connection = tracker_sparql_connection_get_direct(
687 NULL, &error);
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -0300688
Radoslaw Jablonskid12ed5f2011-02-03 11:43:23 +0200689 if (!connection) {
690 if (error) {
691 DBG("direct-connection error: %s", error->message);
692 g_error_free(error);
693 }
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -0300694
Radoslaw Jablonski438be132011-02-14 11:19:45 +0200695 return -EINTR;
Radoslaw Jablonskid12ed5f2011-02-03 11:43:23 +0200696 }
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -0300697
Radoslaw Jablonskid12ed5f2011-02-03 11:43:23 +0200698 cancellable = g_cancellable_new();
699 update_cancellable(user_data, cancellable);
700 cursor = tracker_sparql_connection_query(connection, query,
701 cancellable, &error);
702
703 if (cursor == NULL) {
704 if (error) {
705 DBG("connection_query error: %s", error->message);
706 g_error_free(error);
707 }
708
709 g_object_unref(cancellable);
710
Radoslaw Jablonski438be132011-02-14 11:19:45 +0200711 return -EINTR;
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -0300712 }
713
714 pending = g_new0(struct pending_reply, 1);
715 pending->callback = callback;
716 pending->user_data = user_data;
717 pending->num_fields = num_fields;
718
Radoslaw Jablonskid12ed5f2011-02-03 11:43:23 +0200719 /* Now asynchronously going through each row of results - callback
720 * async_query_cursor_next_cb will be called ALWAYS, even if async
721 * request was canceled */
722 tracker_sparql_cursor_next_async(cursor, cancellable,
723 async_query_cursor_next_cb,
724 pending);
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -0300725
Radoslaw Jablonski438be132011-02-14 11:19:45 +0200726 return 0;
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -0300727}
728
Vinicius Costa Gomes6a77a7b2010-06-10 11:51:37 -0300729static char *iso8601_utc_to_localtime(const char *datetime)
730{
731 time_t time;
732 struct tm tm, *local;
733 char localdate[32];
Vinicius Costa Gomes6a77a7b2010-06-10 11:51:37 -0300734 int nr;
735
736 memset(&tm, 0, sizeof(tm));
737
Slawomir Bochenskiafeb4ea2011-12-08 10:41:21 +0100738 nr = sscanf(datetime, "%04u-%02u-%02uT%02u:%02u:%02u",
Vinicius Costa Gomes6a77a7b2010-06-10 11:51:37 -0300739 &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
Slawomir Bochenskiafeb4ea2011-12-08 10:41:21 +0100740 &tm.tm_hour, &tm.tm_min, &tm.tm_sec);
Vinicius Costa Gomes6a77a7b2010-06-10 11:51:37 -0300741 if (nr < 6) {
742 /* Invalid time format */
Luiz Augusto von Dentz9af3fed2010-10-19 14:53:56 +0300743 error("sscanf(): %s (%d)", strerror(errno), errno);
Vinicius Costa Gomes6a77a7b2010-06-10 11:51:37 -0300744 return g_strdup("");
745 }
746
747 /* Time already in localtime */
Slawomir Bochenskiafeb4ea2011-12-08 10:41:21 +0100748 if (!g_str_has_suffix(datetime, "Z")) {
Luiz Augusto von Dentz9af3fed2010-10-19 14:53:56 +0300749 strftime(localdate, sizeof(localdate), "%Y%m%dT%H%M%S", &tm);
750 return g_strdup(localdate);
751 }
Vinicius Costa Gomes6a77a7b2010-06-10 11:51:37 -0300752
753 tm.tm_year -= 1900; /* Year since 1900 */
754 tm.tm_mon--; /* Months since January, values 0-11 */
755
756 time = mktime(&tm);
757 time -= timezone;
758
759 local = localtime(&time);
760
Luiz Augusto von Dentz41d54f42010-10-13 16:15:56 +0300761 strftime(localdate, sizeof(localdate), "%Y%m%dT%H%M%S", local);
Vinicius Costa Gomes6a77a7b2010-06-10 11:51:37 -0300762
763 return g_strdup(localdate);
764}
765
Vinicius Costa Gomes8c1d1ad2010-06-09 15:37:11 -0300766static void set_call_type(struct phonebook_contact *contact,
767 const char *datetime, const char *is_sent,
768 const char *is_answered)
769{
770 gboolean sent, answered;
771
772 if (g_strcmp0(datetime, "NOTACALL") == 0) {
773 contact->calltype = CALL_TYPE_NOT_A_CALL;
774 return;
775 }
776
Vinicius Costa Gomesa6b0b552010-06-10 10:04:40 -0300777 sent = g_str_equal(is_sent, "true");
778 answered = g_str_equal(is_answered, "true");
Vinicius Costa Gomes8c1d1ad2010-06-09 15:37:11 -0300779
Johan Hedberg1a912cc2010-06-15 08:21:13 +0300780 if (sent == FALSE) {
Vinicius Costa Gomes8c1d1ad2010-06-09 15:37:11 -0300781 if (answered == FALSE)
782 contact->calltype = CALL_TYPE_MISSED;
783 else
784 contact->calltype = CALL_TYPE_INCOMING;
Johan Hedberg1a912cc2010-06-15 08:21:13 +0300785 } else
Vinicius Costa Gomes8c1d1ad2010-06-09 15:37:11 -0300786 contact->calltype = CALL_TYPE_OUTGOING;
787
Vinicius Costa Gomes6a77a7b2010-06-10 11:51:37 -0300788 /* Tracker gives time in the ISO 8601 format, UTC time */
789 contact->datetime = iso8601_utc_to_localtime(datetime);
Vinicius Costa Gomes8c1d1ad2010-06-09 15:37:11 -0300790}
791
Radoslaw Jablonski29c35f52011-04-27 13:52:00 +0300792static gboolean contact_matches(struct contact_data *c_data, const char *id,
793 const char *datetime)
794{
795 char *localtime;
796 int cmp_ret;
797
798 if (g_strcmp0(c_data->id, id) != 0)
799 return FALSE;
800
801 /* id is equal and not call history entry => contact matches */
802 if (c_data->contact->calltype == CALL_TYPE_NOT_A_CALL)
803 return TRUE;
804
805 /* for call history entries have to compare also timestamps of calls */
806 localtime = iso8601_utc_to_localtime(datetime);
807 cmp_ret = g_strcmp0(c_data->contact->datetime, localtime);
808 g_free(localtime);
809
810 return (cmp_ret == 0) ? TRUE : FALSE;
811}
812
813static struct phonebook_contact *find_contact(GSList *contacts, const char *id,
814 const char *datetime)
Radoslaw Jablonski402eb672010-08-10 10:23:20 +0300815{
816 GSList *l;
Radoslaw Jablonski402eb672010-08-10 10:23:20 +0300817
818 for (l = contacts; l; l = l->next) {
Johan Hedberg21e62142010-10-29 10:39:41 -0400819 struct contact_data *c_data = l->data;
Radoslaw Jablonski29c35f52011-04-27 13:52:00 +0300820
821 if (contact_matches(c_data, id, datetime))
Radoslaw Jablonski402eb672010-08-10 10:23:20 +0300822 return c_data->contact;
823 }
824
825 return NULL;
826}
827
Radoslaw Jablonskid51596d2011-01-13 09:39:00 +0200828static struct phonebook_field *find_field(GSList *fields, const char *value,
Radoslaw Jablonski402eb672010-08-10 10:23:20 +0300829 int type)
830{
Rafal Michalskib2652ad2010-10-27 09:20:00 +0200831 GSList *l;
Radoslaw Jablonski402eb672010-08-10 10:23:20 +0300832
Radoslaw Jablonskid51596d2011-01-13 09:39:00 +0200833 for (l = fields; l; l = l->next) {
834 struct phonebook_field *field = l->data;
Radoslaw Jablonski402eb672010-08-10 10:23:20 +0300835 /* Returning phonebook number if phone values and type values
836 * are equal */
Radoslaw Jablonskid51596d2011-01-13 09:39:00 +0200837 if (g_strcmp0(field->text, value) == 0 && field->type == type)
838 return field;
Radoslaw Jablonski402eb672010-08-10 10:23:20 +0300839 }
840
841 return NULL;
842}
843
844static void add_phone_number(struct phonebook_contact *contact,
845 const char *phone, int type)
846{
Radoslaw Jablonski427d45b2011-01-13 09:38:59 +0200847 struct phonebook_field *number;
Radoslaw Jablonski402eb672010-08-10 10:23:20 +0300848
849 if (phone == NULL || strlen(phone) == 0)
850 return;
851
852 /* Not adding number if there is already added with the same value */
Radoslaw Jablonskid51596d2011-01-13 09:39:00 +0200853 if (find_field(contact->numbers, phone, type))
Radoslaw Jablonski402eb672010-08-10 10:23:20 +0300854 return;
855
Radoslaw Jablonski427d45b2011-01-13 09:38:59 +0200856 number = g_new0(struct phonebook_field, 1);
857 number->text = g_strdup(phone);
Radoslaw Jablonski402eb672010-08-10 10:23:20 +0300858 number->type = type;
859
860 contact->numbers = g_slist_append(contact->numbers, number);
861}
862
Lukasz Pawlik82dbd7c2010-08-23 15:45:25 +0200863static void add_email(struct phonebook_contact *contact, const char *address,
864 int type)
Radoslaw Jablonski2eb218a2010-08-19 09:49:47 +0300865{
Radoslaw Jablonski427d45b2011-01-13 09:38:59 +0200866 struct phonebook_field *email;
Lukasz Pawlik82dbd7c2010-08-23 15:45:25 +0200867
868 if (address == NULL || strlen(address) == 0)
Radoslaw Jablonski2eb218a2010-08-19 09:49:47 +0300869 return;
870
871 /* Not adding email if there is already added with the same value */
Radoslaw Jablonskid51596d2011-01-13 09:39:00 +0200872 if (find_field(contact->emails, address, type))
Radoslaw Jablonski2eb218a2010-08-19 09:49:47 +0300873 return;
874
Radoslaw Jablonski427d45b2011-01-13 09:38:59 +0200875 email = g_new0(struct phonebook_field, 1);
876 email->text = g_strdup(address);
Lukasz Pawlik82dbd7c2010-08-23 15:45:25 +0200877 email->type = type;
878
879 contact->emails = g_slist_append(contact->emails, email);
Radoslaw Jablonski2eb218a2010-08-19 09:49:47 +0300880}
881
Rafal Michalskia4b60352011-08-22 12:32:56 +0200882static gboolean addr_matches(struct phonebook_addr *a, struct phonebook_addr *b)
883{
884 GSList *la, *lb;
885
886 if (a->type != b->type)
887 return FALSE;
888
889 for (la = a->fields, lb = b->fields; la && lb;
890 la = la->next, lb = lb->next) {
891 char *field_a = la->data;
892 char *field_b = lb->data;
893
894 if (g_strcmp0(field_a, field_b) != 0)
895 return FALSE;
896 }
897
898 return TRUE;
899}
900
901/* generates phonebook_addr struct from tracker address data string. */
902static struct phonebook_addr *gen_addr(const char *address, int type)
903{
904 struct phonebook_addr *addr;
905 GSList *fields = NULL;
906 char **addr_parts;
907 int i;
908
909 /* This test handles cases when address points to empty string
910 * (or address is NULL pointer) or string containing only six
911 * separators. It indicates that none of address fields is present
912 * and there is no sense to create dummy phonebook_addr struct */
913 if (address == NULL || strlen(address) < ADDR_FIELD_AMOUNT)
914 return NULL;
915
Rafal Michalski34d1a732011-08-22 12:32:57 +0200916 addr_parts = g_strsplit(address, ADDR_DELIM, ADDR_FIELD_AMOUNT);
Rafal Michalskia4b60352011-08-22 12:32:56 +0200917
918 for (i = 0; i < ADDR_FIELD_AMOUNT; ++i)
919 fields = g_slist_append(fields, g_strdup(addr_parts[i]));
920
921 g_strfreev(addr_parts);
922
923 addr = g_new0(struct phonebook_addr, 1);
924 addr->fields = fields;
925 addr->type = type;
926
927 return addr;
928}
929
Rafal Michalskic20efca2010-09-01 13:07:12 +0200930static void add_address(struct phonebook_contact *contact,
931 const char *address, int type)
932{
Rafal Michalskia4b60352011-08-22 12:32:56 +0200933 struct phonebook_addr *addr;
934 GSList *l;
Rafal Michalskic20efca2010-09-01 13:07:12 +0200935
Rafal Michalskia4b60352011-08-22 12:32:56 +0200936 addr = gen_addr(address, type);
937 if (addr == NULL)
Rafal Michalskic20efca2010-09-01 13:07:12 +0200938 return;
939
Rafal Michalskia4b60352011-08-22 12:32:56 +0200940 /* Not adding address if there is already added with the same value.
941 * These type of checks have to be done because sometimes tracker
942 * returns results for contact data in more than 1 row - then the same
943 * address may be returned more than once in query results */
944 for (l = contact->addresses; l; l = l->next) {
945 struct phonebook_addr *tmp = l->data;
Rafal Michalskic20efca2010-09-01 13:07:12 +0200946
Rafal Michalskia4b60352011-08-22 12:32:56 +0200947 if (addr_matches(tmp, addr)) {
948 phonebook_addr_free(addr);
949 return;
950 }
951 }
Rafal Michalskic20efca2010-09-01 13:07:12 +0200952
953 contact->addresses = g_slist_append(contact->addresses, addr);
954}
955
Radoslaw Jablonski495db2b2011-01-13 13:53:12 +0200956static void add_url(struct phonebook_contact *contact, const char *url_val,
957 int type)
958{
959 struct phonebook_field *url;
960
961 if (url_val == NULL || strlen(url_val) == 0)
962 return;
963
964 /* Not adding url if there is already added with the same value */
965 if (find_field(contact->urls, url_val, type))
966 return;
967
968 url = g_new0(struct phonebook_field, 1);
969
970 url->text = g_strdup(url_val);
971 url->type = type;
972
973 contact->urls = g_slist_append(contact->urls, url);
974}
975
Radoslaw Jablonski402eb672010-08-10 10:23:20 +0300976static GString *gen_vcards(GSList *contacts,
977 const struct apparam_field *params)
978{
979 GSList *l;
980 GString *vcards;
Radoslaw Jablonski402eb672010-08-10 10:23:20 +0300981
982 vcards = g_string_new(NULL);
983
984 /* Generating VCARD string from contacts and freeing used contacts */
985 for (l = contacts; l; l = l->next) {
Johan Hedberg21e62142010-10-29 10:39:41 -0400986 struct contact_data *c_data = l->data;
Radoslaw Jablonski402eb672010-08-10 10:23:20 +0300987 phonebook_add_contact(vcards, c_data->contact,
988 params->filter, params->format);
Radoslaw Jablonski402eb672010-08-10 10:23:20 +0300989 }
990
991 return vcards;
992}
993
Radoslaw Jablonski3f347cf2011-02-14 11:19:46 +0200994static int pull_contacts_size(const char **reply, int num_fields,
Radoslaw Jablonskid12ed5f2011-02-03 11:43:23 +0200995 void *user_data)
Radoslaw Jablonski0c004302010-10-26 11:29:52 +0300996{
997 struct phonebook_data *data = user_data;
998
999 if (num_fields < 0) {
Radoslaw Jablonski8042fbf2011-02-14 11:19:49 +02001000 data->cb(NULL, 0, num_fields, 0, TRUE, data->user_data);
Radoslaw Jablonski3f347cf2011-02-14 11:19:46 +02001001 return -EINTR;
Radoslaw Jablonski0c004302010-10-26 11:29:52 +03001002 }
1003
1004 if (reply != NULL) {
1005 data->index = atoi(reply[0]);
Radoslaw Jablonski3f347cf2011-02-14 11:19:46 +02001006 return 0;
Radoslaw Jablonski0c004302010-10-26 11:29:52 +03001007 }
1008
Radoslaw Jablonski8042fbf2011-02-14 11:19:49 +02001009 data->cb(NULL, 0, data->index, data->newmissedcalls, TRUE,
1010 data->user_data);
Radoslaw Jablonski0c004302010-10-26 11:29:52 +03001011
Radoslaw Jablonski3f347cf2011-02-14 11:19:46 +02001012 return 0;
Dmitriy Paliy3b05d5e2010-12-09 12:05:18 +02001013 /*
Dmitriy Paliyf82b81e2011-01-02 19:20:40 +02001014 * phonebook_data is freed in phonebook_req_finalize. Useful in
1015 * cases when call is terminated.
Dmitriy Paliy3b05d5e2010-12-09 12:05:18 +02001016 */
Radoslaw Jablonski0c004302010-10-26 11:29:52 +03001017}
1018
Lukasz Pawlik65e2e082010-10-29 16:04:26 +02001019static void add_affiliation(char **field, const char *value)
1020{
1021 if (strlen(*field) > 0 || value == NULL || strlen(value) == 0)
1022 return;
1023
1024 g_free(*field);
1025
1026 *field = g_strdup(value);
1027}
1028
Radoslaw Jablonskid12ed5f2011-02-03 11:43:23 +02001029static void contact_init(struct phonebook_contact *contact,
1030 const char **reply)
Bartosz Szatkowski08024562010-11-18 12:04:26 +01001031{
Slawomir Bochenskie24d6192011-11-14 15:31:52 +01001032 if (reply[COL_FAMILY_NAME][0] == '\0' &&
1033 reply[COL_GIVEN_NAME][0] == '\0' &&
1034 reply[COL_ADDITIONAL_NAME][0] == '\0' &&
1035 reply[COL_NAME_PREFIX][0] == '\0' &&
1036 reply[COL_NAME_SUFFIX][0] == '\0') {
1037 if (reply[COL_FULL_NAME][0] != '\0')
1038 contact->family = g_strdup(reply[COL_FULL_NAME]);
1039 else
1040 contact->family = g_strdup(reply[COL_NICKNAME]);
1041 } else {
1042 contact->family = g_strdup(reply[COL_FAMILY_NAME]);
1043 contact->given = g_strdup(reply[COL_GIVEN_NAME]);
1044 contact->additional = g_strdup(reply[COL_ADDITIONAL_NAME]);
1045 contact->prefix = g_strdup(reply[COL_NAME_PREFIX]);
1046 contact->suffix = g_strdup(reply[COL_NAME_SUFFIX]);
1047 }
Bartosz Szatkowski08024562010-11-18 12:04:26 +01001048 contact->fullname = g_strdup(reply[COL_FULL_NAME]);
Bartosz Szatkowski08024562010-11-18 12:04:26 +01001049 contact->birthday = g_strdup(reply[COL_BIRTH_DATE]);
1050 contact->nickname = g_strdup(reply[COL_NICKNAME]);
Bartosz Szatkowski08024562010-11-18 12:04:26 +01001051 contact->photo = g_strdup(reply[COL_PHOTO]);
1052 contact->company = g_strdup(reply[COL_ORG_NAME]);
1053 contact->department = g_strdup(reply[COL_ORG_DEPARTMENT]);
1054 contact->role = g_strdup(reply[COL_ORG_ROLE]);
1055 contact->uid = g_strdup(reply[COL_UID]);
1056 contact->title = g_strdup(reply[COL_TITLE]);
1057
1058 set_call_type(contact, reply[COL_DATE], reply[COL_SENT],
1059 reply[COL_ANSWERED]);
1060}
1061
Radoslaw Jablonski894363b2010-12-02 18:02:08 +02001062static enum phonebook_number_type get_phone_type(const char *affilation)
1063{
1064 if (g_strcmp0(AFFILATION_HOME, affilation) == 0)
1065 return TEL_TYPE_HOME;
1066 else if (g_strcmp0(AFFILATION_WORK, affilation) == 0)
1067 return TEL_TYPE_WORK;
1068
1069 return TEL_TYPE_OTHER;
1070}
1071
Radoslaw Jablonskid12ed5f2011-02-03 11:43:23 +02001072static void add_aff_number(struct phonebook_contact *contact,
1073 const char *pnumber, const char *aff_type)
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +02001074{
1075 char **num_parts;
1076 char *type, *number;
1077
1078 /* For phone taken directly from contacts data, phone number string
1079 * is represented as number type and number string - those strings are
1080 * separated by SUB_DELIM string */
1081 num_parts = g_strsplit(pnumber, SUB_DELIM, 2);
1082
1083 if (!num_parts)
1084 return;
1085
1086 if (num_parts[0])
1087 type = num_parts[0];
1088 else
1089 goto failed;
1090
1091 if (num_parts[1])
1092 number = num_parts[1];
1093 else
1094 goto failed;
1095
1096 if (g_strrstr(type, FAX_NUM_TYPE))
1097 add_phone_number(contact, number, TEL_TYPE_FAX);
1098 else if (g_strrstr(type, MOBILE_NUM_TYPE))
1099 add_phone_number(contact, number, TEL_TYPE_MOBILE);
1100 else
Radoslaw Jablonski41f45782011-01-04 14:23:56 +02001101 /* if this is no fax/mobile phone, then adding phone number
1102 * type based on type of the affilation field */
1103 add_phone_number(contact, number, get_phone_type(aff_type));
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +02001104
1105failed:
1106 g_strfreev(num_parts);
1107}
1108
Bartosz Szatkowski08024562010-11-18 12:04:26 +01001109static void contact_add_numbers(struct phonebook_contact *contact,
Radoslaw Jablonskid12ed5f2011-02-03 11:43:23 +02001110 const char **reply)
Bartosz Szatkowski08024562010-11-18 12:04:26 +01001111{
Radoslaw Jablonski41f45782011-01-04 14:23:56 +02001112 char **aff_numbers;
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +02001113 int i;
1114
Radoslaw Jablonski41f45782011-01-04 14:23:56 +02001115 /* Filling phone numbers from contact's affilation */
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +02001116 aff_numbers = g_strsplit(reply[COL_PHONE_AFF], MAIN_DELIM, MAX_FIELDS);
1117
1118 if (aff_numbers)
Syam Sidhardhan37247032011-06-27 03:26:06 +05301119 for (i = 0; aff_numbers[i]; ++i)
Radoslaw Jablonski41f45782011-01-04 14:23:56 +02001120 add_aff_number(contact, aff_numbers[i],
1121 reply[COL_AFF_TYPE]);
Bartosz Szatkowski08024562010-11-18 12:04:26 +01001122
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +02001123 g_strfreev(aff_numbers);
Bartosz Szatkowski08024562010-11-18 12:04:26 +01001124}
1125
Radoslaw Jablonski427d45b2011-01-13 09:38:59 +02001126static enum phonebook_field_type get_field_type(const char *affilation)
Radoslaw Jablonski894363b2010-12-02 18:02:08 +02001127{
1128 if (g_strcmp0(AFFILATION_HOME, affilation) == 0)
Radoslaw Jablonski427d45b2011-01-13 09:38:59 +02001129 return FIELD_TYPE_HOME;
Radoslaw Jablonski894363b2010-12-02 18:02:08 +02001130 else if (g_strcmp0(AFFILATION_WORK, affilation) == 0)
Radoslaw Jablonski427d45b2011-01-13 09:38:59 +02001131 return FIELD_TYPE_WORK;
Radoslaw Jablonski894363b2010-12-02 18:02:08 +02001132
Radoslaw Jablonski427d45b2011-01-13 09:38:59 +02001133 return FIELD_TYPE_OTHER;
Radoslaw Jablonski894363b2010-12-02 18:02:08 +02001134}
1135
Radoslaw Jablonskid12ed5f2011-02-03 11:43:23 +02001136static void add_aff_field(struct phonebook_contact *contact,
1137 const char *aff_email, add_field_t add_field_cb)
Radoslaw Jablonski7e7ab3e2011-01-07 10:19:57 +02001138{
1139 char **email_parts;
1140 char *type, *email;
1141
1142 /* Emails from affilation data, are represented as real email
1143 * string and affilation type - those strings are separated by
1144 * SUB_DELIM string */
1145 email_parts = g_strsplit(aff_email, SUB_DELIM, 2);
1146
1147 if (!email_parts)
1148 return;
1149
1150 if (email_parts[0])
1151 email = email_parts[0];
1152 else
1153 goto failed;
1154
1155 if (email_parts[1])
1156 type = email_parts[1];
1157 else
1158 goto failed;
1159
Radoslaw Jablonski8c10c122011-01-13 09:39:01 +02001160 add_field_cb(contact, email, get_field_type(type));
Radoslaw Jablonski7e7ab3e2011-01-07 10:19:57 +02001161
1162failed:
1163 g_strfreev(email_parts);
1164}
1165
Bartosz Szatkowski08024562010-11-18 12:04:26 +01001166static void contact_add_emails(struct phonebook_contact *contact,
Radoslaw Jablonskid12ed5f2011-02-03 11:43:23 +02001167 const char **reply)
Bartosz Szatkowski08024562010-11-18 12:04:26 +01001168{
Radoslaw Jablonski7e7ab3e2011-01-07 10:19:57 +02001169 char **aff_emails;
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +02001170 int i;
1171
1172 /* Emails from affilation */
1173 aff_emails = g_strsplit(reply[COL_EMAIL_AFF], MAIN_DELIM, MAX_FIELDS);
1174
1175 if (aff_emails)
Syam Sidhardhan37247032011-06-27 03:26:06 +05301176 for (i = 0; aff_emails[i] != NULL; ++i)
Radoslaw Jablonski8c10c122011-01-13 09:39:01 +02001177 add_aff_field(contact, aff_emails[i], add_email);
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +02001178
1179 g_strfreev(aff_emails);
Bartosz Szatkowski08024562010-11-18 12:04:26 +01001180}
1181
1182static void contact_add_addresses(struct phonebook_contact *contact,
Radoslaw Jablonskid12ed5f2011-02-03 11:43:23 +02001183 const char **reply)
Bartosz Szatkowski08024562010-11-18 12:04:26 +01001184{
Radoslaw Jablonski1e73e0a2011-01-05 11:48:15 +02001185 char **aff_addr;
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +02001186 int i;
Bartosz Szatkowski08024562010-11-18 12:04:26 +01001187
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +02001188 /* Addresses from affilation */
Rafal Michalski6df190c2011-10-25 13:11:54 +02001189 aff_addr = g_strsplit(reply[COL_ADDR_AFF], MAIN_DELIM, MAX_FIELDS);
Bartosz Szatkowski08024562010-11-18 12:04:26 +01001190
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +02001191 if (aff_addr)
Syam Sidhardhan37247032011-06-27 03:26:06 +05301192 for (i = 0; aff_addr[i] != NULL; ++i)
Radoslaw Jablonski8c10c122011-01-13 09:39:01 +02001193 add_aff_field(contact, aff_addr[i], add_address);
Bartosz Szatkowski08024562010-11-18 12:04:26 +01001194
Radoslaw Jablonskice3d4bf2010-12-16 16:57:03 +02001195 g_strfreev(aff_addr);
Bartosz Szatkowski08024562010-11-18 12:04:26 +01001196}
1197
Radoslaw Jablonskid12ed5f2011-02-03 11:43:23 +02001198static void contact_add_urls(struct phonebook_contact *contact,
1199 const char **reply)
Radoslaw Jablonski495db2b2011-01-13 13:53:12 +02001200{
1201 char **aff_url;
1202 int i;
1203
1204 /* Addresses from affilation */
1205 aff_url = g_strsplit(reply[COL_URL], MAIN_DELIM, MAX_FIELDS);
1206
1207 if (aff_url)
Syam Sidhardhan37247032011-06-27 03:26:06 +05301208 for (i = 0; aff_url[i] != NULL; ++i)
Radoslaw Jablonski495db2b2011-01-13 13:53:12 +02001209 add_aff_field(contact, aff_url[i], add_url);
1210
1211 g_strfreev(aff_url);
1212}
1213
Bartosz Szatkowski08024562010-11-18 12:04:26 +01001214static void contact_add_organization(struct phonebook_contact *contact,
Radoslaw Jablonskid12ed5f2011-02-03 11:43:23 +02001215 const char **reply)
Bartosz Szatkowski08024562010-11-18 12:04:26 +01001216{
1217 /* Adding fields connected by nco:hasAffiliation - they may be in
1218 * separate replies */
1219 add_affiliation(&contact->title, reply[COL_TITLE]);
1220 add_affiliation(&contact->company, reply[COL_ORG_NAME]);
1221 add_affiliation(&contact->department, reply[COL_ORG_DEPARTMENT]);
1222 add_affiliation(&contact->role, reply[COL_ORG_ROLE]);
1223}
1224
Radoslaw Jablonski84799cd2011-02-14 11:19:51 +02001225static void free_data_contacts(struct phonebook_data *data)
1226{
1227 GSList *l;
1228
1229 /* freeing contacts */
1230 for (l = data->contacts; l; l = l->next) {
1231 struct contact_data *c_data = l->data;
1232
1233 g_free(c_data->id);
1234 phonebook_contact_free(c_data->contact);
1235 g_free(c_data);
1236 }
1237
1238 g_slist_free(data->contacts);
1239 data->contacts = NULL;
1240}
1241
1242static void send_pull_part(struct phonebook_data *data,
1243 const struct apparam_field *params, gboolean lastpart)
1244{
1245 GString *vcards;
1246
1247 DBG("");
1248 vcards = gen_vcards(data->contacts, params);
1249 data->cb(vcards->str, vcards->len, g_slist_length(data->contacts),
1250 data->newmissedcalls, lastpart, data->user_data);
1251
Dmitriy Paliy16ca8eb2011-07-07 15:01:40 +03001252 if (!lastpart)
1253 free_data_contacts(data);
Radoslaw Jablonski84799cd2011-02-14 11:19:51 +02001254 g_string_free(vcards, TRUE);
1255}
1256
Radoslaw Jablonski3f347cf2011-02-14 11:19:46 +02001257static int pull_contacts(const char **reply, int num_fields, void *user_data)
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -03001258{
1259 struct phonebook_data *data = user_data;
Vinicius Costa Gomes9bd2e412010-04-16 18:13:23 -03001260 const struct apparam_field *params = data->params;
Vinicius Costa Gomes7f735fb2010-04-19 20:20:42 -03001261 struct phonebook_contact *contact;
Radoslaw Jablonski402eb672010-08-10 10:23:20 +03001262 struct contact_data *contact_data;
Vinicius Costa Gomesf619e752010-06-14 16:44:25 -03001263 int last_index, i;
Radoslaw Jablonski84799cd2011-02-14 11:19:51 +02001264 gboolean cdata_present = FALSE, part_sent = FALSE;
Rafal Michalskia8eb0632010-11-15 11:41:40 +01001265 static char *temp_id = NULL;
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -03001266
Luiz Augusto von Dentzeb832912010-10-14 16:34:03 +03001267 if (num_fields < 0) {
Radoslaw Jablonski8042fbf2011-02-14 11:19:49 +02001268 data->cb(NULL, 0, num_fields, 0, TRUE, data->user_data);
Luiz Augusto von Dentzeb832912010-10-14 16:34:03 +03001269 goto fail;
1270 }
1271
Vinicius Costa Gomese86c39c2010-05-18 22:54:01 -03001272 DBG("reply %p", reply);
Radoslaw Jablonski84799cd2011-02-14 11:19:51 +02001273 data->tracker_index++;
Vinicius Costa Gomese86c39c2010-05-18 22:54:01 -03001274
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -03001275 if (reply == NULL)
1276 goto done;
1277
Radoslaw Jablonski402eb672010-08-10 10:23:20 +03001278 /* Trying to find contact in recently added contacts. It is needed for
1279 * contacts that have more than one telephone number filled */
Radoslaw Jablonski29c35f52011-04-27 13:52:00 +03001280 contact = find_contact(data->contacts, reply[CONTACTS_ID_COL],
1281 reply[COL_DATE]);
Radoslaw Jablonski402eb672010-08-10 10:23:20 +03001282
1283 /* If contact is already created then adding only new phone numbers */
1284 if (contact) {
1285 cdata_present = TRUE;
1286 goto add_numbers;
1287 }
1288
Vinicius Costa Gomes13a97df2010-05-17 20:49:18 -03001289 /* We are doing a PullvCardEntry, no need for those checks */
1290 if (data->vcardentry)
1291 goto add_entry;
1292
Vinicius Costa Gomesf619e752010-06-14 16:44:25 -03001293 /* Last four fields are always present, ignoring them */
Johan Hedberg1a912cc2010-06-15 08:21:13 +03001294 for (i = 0; i < num_fields - 4; i++) {
Vinicius Costa Gomesf619e752010-06-14 16:44:25 -03001295 if (reply[i][0] != '\0')
1296 break;
Johan Hedberg1a912cc2010-06-15 08:21:13 +03001297 }
Vinicius Costa Gomesf619e752010-06-14 16:44:25 -03001298
Johan Hedberg21e62142010-10-29 10:39:41 -04001299 if (i == num_fields - 4 && !g_str_equal(reply[CONTACTS_ID_COL],
1300 TRACKER_DEFAULT_CONTACT_ME))
Radoslaw Jablonski3f347cf2011-02-14 11:19:46 +02001301 return 0;
Vinicius Costa Gomesf619e752010-06-14 16:44:25 -03001302
Rafal Michalskia8eb0632010-11-15 11:41:40 +01001303 if (g_strcmp0(temp_id, reply[CONTACTS_ID_COL])) {
1304 data->index++;
1305 g_free(temp_id);
1306 temp_id = g_strdup(reply[CONTACTS_ID_COL]);
Radoslaw Jablonski84799cd2011-02-14 11:19:51 +02001307
1308 /* Incrementing counter for vcards in current part of data,
1309 * but only if liststartoffset has been already reached */
1310 if (data->index > params->liststartoffset)
1311 data->vcard_part_count++;
1312 }
1313
1314 if (data->vcard_part_count > VCARDS_PART_COUNT) {
1315 DBG("Part of vcard data ready for sending...");
1316 data->vcard_part_count = 0;
1317 /* Sending part of data to PBAP core - more data can be still
1318 * fetched, so marking lastpart as FALSE */
1319 send_pull_part(data, params, FALSE);
1320
1321 /* Later, after adding contact data, need to return -EINTR to
1322 * stop fetching more data for this request. Data will be
1323 * downloaded again from this point, when phonebook_pull_read
1324 * will be called again with current request as a parameter*/
1325 part_sent = TRUE;
Rafal Michalskia8eb0632010-11-15 11:41:40 +01001326 }
Vinicius Costa Gomes9bd2e412010-04-16 18:13:23 -03001327
Vinicius Costa Gomes9bd2e412010-04-16 18:13:23 -03001328 last_index = params->liststartoffset + params->maxlistcount;
1329
Radoslaw Jablonskie669d832011-02-14 11:19:48 +02001330 if (data->index <= params->liststartoffset)
Radoslaw Jablonski3f347cf2011-02-14 11:19:46 +02001331 return 0;
Vinicius Costa Gomes9bd2e412010-04-16 18:13:23 -03001332
Radoslaw Jablonskie669d832011-02-14 11:19:48 +02001333 /* max number of results achieved - need send vcards data that was
1334 * already collected and stop further data processing (these operations
1335 * will be invoked in "done" section) */
1336 if (data->index > last_index && params->maxlistcount > 0) {
1337 DBG("Maxlistcount achieved");
1338 goto done;
1339 }
1340
Vinicius Costa Gomes13a97df2010-05-17 20:49:18 -03001341add_entry:
Vinicius Costa Gomes7f735fb2010-04-19 20:20:42 -03001342 contact = g_new0(struct phonebook_contact, 1);
Bartosz Szatkowski08024562010-11-18 12:04:26 +01001343 contact_init(contact, reply);
Vinicius Costa Gomes8c1d1ad2010-06-09 15:37:11 -03001344
Radoslaw Jablonski402eb672010-08-10 10:23:20 +03001345add_numbers:
Bartosz Szatkowski08024562010-11-18 12:04:26 +01001346 contact_add_numbers(contact, reply);
1347 contact_add_emails(contact, reply);
1348 contact_add_addresses(contact, reply);
Radoslaw Jablonski495db2b2011-01-13 13:53:12 +02001349 contact_add_urls(contact, reply);
Bartosz Szatkowski08024562010-11-18 12:04:26 +01001350 contact_add_organization(contact, reply);
Lukasz Pawlik65e2e082010-10-29 16:04:26 +02001351
Vinicius Costa Gomese86c39c2010-05-18 22:54:01 -03001352 DBG("contact %p", contact);
1353
Radoslaw Jablonski402eb672010-08-10 10:23:20 +03001354 /* Adding contacts data to wrapper struct - this data will be used to
1355 * generate vcard list */
1356 if (!cdata_present) {
1357 contact_data = g_new0(struct contact_data, 1);
1358 contact_data->contact = contact;
1359 contact_data->id = g_strdup(reply[CONTACTS_ID_COL]);
1360 data->contacts = g_slist_append(data->contacts, contact_data);
1361 }
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -03001362
Radoslaw Jablonski84799cd2011-02-14 11:19:51 +02001363 if (part_sent)
1364 return -EINTR;
1365
Radoslaw Jablonski3f347cf2011-02-14 11:19:46 +02001366 return 0;
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -03001367
1368done:
Radoslaw Jablonski84799cd2011-02-14 11:19:51 +02001369 /* Processing is end, this is definitely last part of transmission
1370 * (marking lastpart as TRUE) */
1371 send_pull_part(data, params, TRUE);
Radoslaw Jablonski402eb672010-08-10 10:23:20 +03001372
Luiz Augusto von Dentzeb832912010-10-14 16:34:03 +03001373fail:
Rafal Michalskia8eb0632010-11-15 11:41:40 +01001374 g_free(temp_id);
1375 temp_id = NULL;
Dmitriy Paliy3b05d5e2010-12-09 12:05:18 +02001376
Radoslaw Jablonski3f347cf2011-02-14 11:19:46 +02001377 return -EINTR;
Dmitriy Paliy3b05d5e2010-12-09 12:05:18 +02001378 /*
Dmitriy Paliyf82b81e2011-01-02 19:20:40 +02001379 * phonebook_data is freed in phonebook_req_finalize. Useful in
1380 * cases when call is terminated.
Dmitriy Paliy3b05d5e2010-12-09 12:05:18 +02001381 */
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -03001382}
1383
Radoslaw Jablonski3f347cf2011-02-14 11:19:46 +02001384static int add_to_cache(const char **reply, int num_fields, void *user_data)
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -03001385{
Dmitriy Paliy7f669cc2011-01-02 19:20:38 +02001386 struct phonebook_data *data = user_data;
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -03001387 char *formatted;
Vinicius Costa Gomesabcdcfe2010-06-07 20:23:08 -03001388 int i;
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -03001389
Luiz Augusto von Dentzeb832912010-10-14 16:34:03 +03001390 if (reply == NULL || num_fields < 0)
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -03001391 goto done;
1392
Vinicius Costa Gomesf619e752010-06-14 16:44:25 -03001393 /* the first element is the URI, always not empty */
Johan Hedberg1a912cc2010-06-15 08:21:13 +03001394 for (i = 1; i < num_fields; i++) {
Vinicius Costa Gomesf619e752010-06-14 16:44:25 -03001395 if (reply[i][0] != '\0')
Vinicius Costa Gomesabcdcfe2010-06-07 20:23:08 -03001396 break;
Johan Hedberg1a912cc2010-06-15 08:21:13 +03001397 }
Vinicius Costa Gomesf619e752010-06-14 16:44:25 -03001398
Johan Hedberg1a912cc2010-06-15 08:21:13 +03001399 if (i == num_fields &&
1400 !g_str_equal(reply[0], TRACKER_DEFAULT_CONTACT_ME))
Radoslaw Jablonski3f347cf2011-02-14 11:19:46 +02001401 return 0;
Vinicius Costa Gomesabcdcfe2010-06-07 20:23:08 -03001402
Slawomir Bochenskie24d6192011-11-14 15:31:52 +01001403 if (i == 7)
1404 formatted = g_strdup(reply[7]);
1405 else if (i == 6)
Vinicius Costa Gomesabcdcfe2010-06-07 20:23:08 -03001406 formatted = g_strdup(reply[6]);
Vinicius Costa Gomesf619e752010-06-14 16:44:25 -03001407 else
1408 formatted = g_strdup_printf("%s;%s;%s;%s;%s",
1409 reply[1], reply[2], reply[3], reply[4],
1410 reply[5]);
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -03001411
Vinicius Costa Gomes1cce8a42010-05-12 15:12:17 -03001412 /* The owner vCard must have the 0 handle */
1413 if (strcmp(reply[0], TRACKER_DEFAULT_CONTACT_ME) == 0)
Bartosz Szatkowski5f944a22011-07-13 16:20:03 +02001414 data->entry_cb(reply[0], 0, formatted, "",
1415 reply[6], data->user_data);
Vinicius Costa Gomes1cce8a42010-05-12 15:12:17 -03001416 else
Bartosz Szatkowski5f944a22011-07-13 16:20:03 +02001417 data->entry_cb(reply[0], PHONEBOOK_INVALID_HANDLE, formatted,
1418 "", reply[6], data->user_data);
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -03001419
1420 g_free(formatted);
1421
Radoslaw Jablonski3f347cf2011-02-14 11:19:46 +02001422 return 0;
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -03001423
1424done:
Luiz Augusto von Dentzeb832912010-10-14 16:34:03 +03001425 if (num_fields <= 0)
Dmitriy Paliy7f669cc2011-01-02 19:20:38 +02001426 data->ready_cb(data->user_data);
Vinicius Costa Gomesd6db9d12010-05-11 19:40:31 -03001427
Radoslaw Jablonski3f347cf2011-02-14 11:19:46 +02001428 return -EINTR;
Dmitriy Paliy3b05d5e2010-12-09 12:05:18 +02001429 /*
Dmitriy Paliyf82b81e2011-01-02 19:20:40 +02001430 * phonebook_data is freed in phonebook_req_finalize. Useful in
1431 * cases when call is terminated.
Dmitriy Paliy3b05d5e2010-12-09 12:05:18 +02001432 */
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -03001433}
1434
1435int phonebook_init(void)
1436{
Radoslaw Jablonskid12ed5f2011-02-03 11:43:23 +02001437 g_thread_init(NULL);
1438 g_type_init();
1439
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -03001440 return 0;
1441}
1442
1443void phonebook_exit(void)
1444{
1445}
1446
1447char *phonebook_set_folder(const char *current_folder, const char *new_folder,
Johan Hedberg21e62142010-10-29 10:39:41 -04001448 uint8_t flags, int *err)
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -03001449{
Vinicius Costa Gomes18432562010-04-14 19:56:22 -03001450 char *tmp1, *tmp2, *base, *path = NULL;
1451 gboolean root, child;
Vinicius Costa Gomes11a55392010-06-08 15:51:31 -03001452 int ret = 0;
1453 int len;
Vinicius Costa Gomes18432562010-04-14 19:56:22 -03001454
1455 root = (g_strcmp0("/", current_folder) == 0);
1456 child = (new_folder && strlen(new_folder) != 0);
1457
1458 switch (flags) {
1459 case 0x02:
1460 /* Go back to root */
1461 if (!child) {
1462 path = g_strdup("/");
1463 goto done;
1464 }
1465
1466 path = g_build_filename(current_folder, new_folder, NULL);
1467 break;
1468 case 0x03:
1469 /* Go up 1 level */
1470 if (root) {
1471 /* Already root */
1472 path = g_strdup("/");
1473 goto done;
1474 }
1475
1476 /*
1477 * Removing one level of the current folder. Current folder
1478 * contains AT LEAST one level since it is not at root folder.
1479 * Use glib utility functions to handle invalid chars in the
1480 * folder path properly.
1481 */
1482 tmp1 = g_path_get_basename(current_folder);
1483 tmp2 = g_strrstr(current_folder, tmp1);
1484 len = tmp2 - (current_folder + 1);
1485
1486 g_free(tmp1);
Vinicius Costa Gomes18432562010-04-14 19:56:22 -03001487
1488 if (len == 0)
1489 base = g_strdup("/");
1490 else
1491 base = g_strndup(current_folder, len);
1492
1493 /* Return: one level only */
1494 if (!child) {
1495 path = base;
1496 goto done;
1497 }
1498
1499 path = g_build_filename(base, new_folder, NULL);
1500 g_free(base);
1501
1502 break;
1503 default:
1504 ret = -EBADR;
1505 break;
1506 }
1507
1508done:
Johan Hedberg21e62142010-10-29 10:39:41 -04001509 if (path && !folder_is_valid(path))
1510 ret = -ENOENT;
1511
1512 if (ret < 0) {
Vinicius Costa Gomes18432562010-04-14 19:56:22 -03001513 g_free(path);
1514 path = NULL;
Vinicius Costa Gomes11a55392010-06-08 15:51:31 -03001515 }
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -03001516
1517 if (err)
Vinicius Costa Gomes18432562010-04-14 19:56:22 -03001518 *err = ret;
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -03001519
Vinicius Costa Gomes18432562010-04-14 19:56:22 -03001520 return path;
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -03001521}
1522
Radoslaw Jablonski3f347cf2011-02-14 11:19:46 +02001523static int pull_newmissedcalls(const char **reply, int num_fields,
Radoslaw Jablonskid12ed5f2011-02-03 11:43:23 +02001524 void *user_data)
Dmitriy Paliyf82b81e2011-01-02 19:20:40 +02001525{
1526 struct phonebook_data *data = user_data;
1527 reply_list_foreach_t pull_cb;
1528 int col_amount, err;
1529 const char *query;
Slawomir Bochenski2b3644a2011-08-24 12:12:23 +02001530 int nmissed;
Dmitriy Paliyf82b81e2011-01-02 19:20:40 +02001531
1532 if (num_fields < 0) {
Radoslaw Jablonski8042fbf2011-02-14 11:19:49 +02001533 data->cb(NULL, 0, num_fields, 0, TRUE, data->user_data);
Slawomir Bochenski2b3644a2011-08-24 12:12:23 +02001534
Radoslaw Jablonski3f347cf2011-02-14 11:19:46 +02001535 return -EINTR;
Dmitriy Paliyf82b81e2011-01-02 19:20:40 +02001536 }
1537
Slawomir Bochenski2b3644a2011-08-24 12:12:23 +02001538 if (reply != NULL) {
1539 nmissed = atoi(reply[0]);
1540 data->newmissedcalls =
1541 nmissed <= UINT8_MAX ? nmissed : UINT8_MAX;
1542 DBG("newmissedcalls %d", data->newmissedcalls);
1543
1544 return 0;
1545 }
1546
Dmitriy Paliyf82b81e2011-01-02 19:20:40 +02001547 if (data->params->maxlistcount == 0) {
Harald Schmitta8061412012-07-18 16:53:08 +02001548 query = name2count_query(PB_CALLS_MISSED);
Dmitriy Paliyf82b81e2011-01-02 19:20:40 +02001549 col_amount = COUNT_QUERY_COL_AMOUNT;
1550 pull_cb = pull_contacts_size;
1551 } else {
Harald Schmitta8061412012-07-18 16:53:08 +02001552 query = name2query(PB_CALLS_MISSED);
Dmitriy Paliyf82b81e2011-01-02 19:20:40 +02001553 col_amount = PULL_QUERY_COL_AMOUNT;
1554 pull_cb = pull_contacts;
1555 }
1556
Radoslaw Jablonski438be132011-02-14 11:19:45 +02001557 err = query_tracker(query, col_amount, pull_cb, data);
Radoslaw Jablonski3f347cf2011-02-14 11:19:46 +02001558 if (err < 0) {
Radoslaw Jablonski8042fbf2011-02-14 11:19:49 +02001559 data->cb(NULL, 0, err, 0, TRUE, data->user_data);
Radoslaw Jablonski3f347cf2011-02-14 11:19:46 +02001560
1561 return -EINTR;
1562 }
1563
1564 return 0;
Dmitriy Paliy3b05d5e2010-12-09 12:05:18 +02001565}
1566
Dmitriy Paliy67f5fbc2011-05-19 15:57:43 +03001567void phonebook_req_finalize(void *request)
1568{
1569 struct phonebook_data *data = request;
1570
1571 DBG("");
1572
1573 if (!data)
1574 return;
1575
1576 /* canceling asynchronous operation on tracker if any is active */
1577 if (data->query_canc) {
1578 g_cancellable_cancel(data->query_canc);
1579 g_object_unref(data->query_canc);
1580 }
1581
Dmitriy Paliy67f5fbc2011-05-19 15:57:43 +03001582 free_data_contacts(data);
1583 g_free(data->req_name);
1584 g_free(data);
1585}
1586
Dmitriy Paliy3b05d5e2010-12-09 12:05:18 +02001587void *phonebook_pull(const char *name, const struct apparam_field *params,
1588 phonebook_cb cb, void *user_data, int *err)
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -03001589{
1590 struct phonebook_data *data;
Vinicius Costa Gomes18432562010-04-14 19:56:22 -03001591
Vinicius Costa Gomese86c39c2010-05-18 22:54:01 -03001592 DBG("name %s", name);
1593
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -03001594 data = g_new0(struct phonebook_data, 1);
Vinicius Costa Gomes9bd2e412010-04-16 18:13:23 -03001595 data->params = params;
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -03001596 data->user_data = user_data;
1597 data->cb = cb;
Radoslaw Jablonski71695872011-02-14 11:19:50 +02001598 data->req_name = g_strdup(name);
1599
Radoslaw Jablonski438be132011-02-14 11:19:45 +02001600 if (err)
Radoslaw Jablonski71695872011-02-14 11:19:50 +02001601 *err = 0;
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -03001602
Dmitriy Paliyf82b81e2011-01-02 19:20:40 +02001603 return data;
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -03001604}
1605
Radoslaw Jablonski71695872011-02-14 11:19:50 +02001606int phonebook_pull_read(void *request)
1607{
1608 struct phonebook_data *data = request;
1609 reply_list_foreach_t pull_cb;
1610 const char *query;
Radoslaw Jablonskic3c493f2011-02-16 11:34:15 +02001611 char *offset_query;
Radoslaw Jablonski71695872011-02-14 11:19:50 +02001612 int col_amount;
1613 int ret;
1614
Johan Hedberg92769fb2011-05-20 08:58:57 -07001615 if (!data)
Radoslaw Jablonski71695872011-02-14 11:19:50 +02001616 return -ENOENT;
1617
Slawomir Bochenski2fb51462011-06-14 08:59:51 +02001618 data->newmissedcalls = 0;
1619
Harald Schmitta8061412012-07-18 16:53:08 +02001620 if (g_strcmp0(data->req_name, PB_CALLS_MISSED) == 0 &&
Radoslaw Jablonski3954d812011-05-19 10:29:22 +03001621 data->tracker_index == 0) {
1622 /* new missed calls amount should be counted only once - it
1623 * will be done during generating first part of results of
1624 * missed calls history */
Slawomir Bochenski2b3644a2011-08-24 12:12:23 +02001625 query = NEW_MISSED_CALLS_COUNT_QUERY;
1626 col_amount = COUNT_QUERY_COL_AMOUNT;
Radoslaw Jablonski71695872011-02-14 11:19:50 +02001627 pull_cb = pull_newmissedcalls;
1628 } else if (data->params->maxlistcount == 0) {
1629 query = name2count_query(data->req_name);
1630 col_amount = COUNT_QUERY_COL_AMOUNT;
1631 pull_cb = pull_contacts_size;
1632 } else {
1633 query = name2query(data->req_name);
1634 col_amount = PULL_QUERY_COL_AMOUNT;
1635 pull_cb = pull_contacts;
1636 }
1637
1638 if (query == NULL)
1639 return -ENOENT;
1640
Radoslaw Jablonskic3c493f2011-02-16 11:34:15 +02001641 if (pull_cb == pull_contacts && data->tracker_index > 0) {
1642 /* Adding offset to pull query to download next parts of data
1643 * from tracker (phonebook_pull_read may be called many times
1644 * from PBAP core to fetch data partially) */
1645 offset_query = g_strdup_printf(QUERY_OFFSET_FORMAT, query,
1646 data->tracker_index);
1647 ret = query_tracker(offset_query, col_amount, pull_cb, data);
1648
1649 g_free(offset_query);
1650
1651 return ret;
1652 }
1653
Johan Hedberg92769fb2011-05-20 08:58:57 -07001654 return query_tracker(query, col_amount, pull_cb, data);
Radoslaw Jablonski71695872011-02-14 11:19:50 +02001655}
1656
Dmitriy Paliy3b05d5e2010-12-09 12:05:18 +02001657void *phonebook_get_entry(const char *folder, const char *id,
1658 const struct apparam_field *params,
1659 phonebook_cb cb, void *user_data, int *err)
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -03001660{
1661 struct phonebook_data *data;
1662 char *query;
Radoslaw Jablonski438be132011-02-14 11:19:45 +02001663 int ret;
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -03001664
Vinicius Costa Gomese86c39c2010-05-18 22:54:01 -03001665 DBG("folder %s id %s", folder, id);
1666
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -03001667 data = g_new0(struct phonebook_data, 1);
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -03001668 data->user_data = user_data;
Vinicius Costa Gomes9bd2e412010-04-16 18:13:23 -03001669 data->params = params;
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -03001670 data->cb = cb;
Vinicius Costa Gomes13a97df2010-05-17 20:49:18 -03001671 data->vcardentry = TRUE;
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -03001672
Rafal Michalski138387e2011-01-26 14:26:27 +01001673 if (g_str_has_prefix(id, CONTACT_ID_PREFIX) == TRUE ||
1674 g_strcmp0(id, TRACKER_DEFAULT_CONTACT_ME) == 0)
Rafal Michalski6bc7e012010-10-25 11:04:58 +02001675 query = g_strdup_printf(CONTACTS_QUERY_FROM_URI, id, id, id, id,
Rafal Michalski13f57962011-01-26 13:33:06 +01001676 id, id, id, id, id, id, id, id, id);
Bartosz Szatkowski9e87d212011-07-13 16:20:04 +02001677 else if (g_str_has_prefix(id, CALL_ID_PREFIX) == TRUE)
1678 query = g_strdup_printf(CONTACT_FROM_CALL_QUERY, id);
Rafal Michalski6bc7e012010-10-25 11:04:58 +02001679 else
1680 query = g_strdup_printf(CONTACTS_OTHER_QUERY_FROM_URI,
1681 id, id, id);
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -03001682
Radoslaw Jablonski438be132011-02-14 11:19:45 +02001683 ret = query_tracker(query, PULL_QUERY_COL_AMOUNT, pull_contacts, data);
1684 if (err)
1685 *err = ret;
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -03001686
1687 g_free(query);
1688
Dmitriy Paliyf82b81e2011-01-02 19:20:40 +02001689 return data;
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -03001690}
1691
Dmitriy Paliy3b05d5e2010-12-09 12:05:18 +02001692void *phonebook_create_cache(const char *name, phonebook_entry_cb entry_cb,
1693 phonebook_cache_ready_cb ready_cb, void *user_data, int *err)
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -03001694{
Dmitriy Paliy7f669cc2011-01-02 19:20:38 +02001695 struct phonebook_data *data;
Vinicius Costa Gomes18432562010-04-14 19:56:22 -03001696 const char *query;
Radoslaw Jablonski438be132011-02-14 11:19:45 +02001697 int ret;
Vinicius Costa Gomes18432562010-04-14 19:56:22 -03001698
Vinicius Costa Gomese86c39c2010-05-18 22:54:01 -03001699 DBG("name %s", name);
1700
Vinicius Costa Gomes18432562010-04-14 19:56:22 -03001701 query = folder2query(name);
Dmitriy Paliy3b05d5e2010-12-09 12:05:18 +02001702 if (query == NULL) {
1703 if (err)
1704 *err = -ENOENT;
1705 return NULL;
1706 }
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -03001707
Dmitriy Paliy7f669cc2011-01-02 19:20:38 +02001708 data = g_new0(struct phonebook_data, 1);
1709 data->entry_cb = entry_cb;
1710 data->ready_cb = ready_cb;
1711 data->user_data = user_data;
Johan Hedberg92769fb2011-05-20 08:58:57 -07001712
Slawomir Bochenskie24d6192011-11-14 15:31:52 +01001713 ret = query_tracker(query, 8, add_to_cache, data);
Radoslaw Jablonski438be132011-02-14 11:19:45 +02001714 if (err)
1715 *err = ret;
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -03001716
Dmitriy Paliyf82b81e2011-01-02 19:20:40 +02001717 return data;
Vinicius Costa Gomes98359ac2010-03-17 20:56:43 -03001718}