Add multi-user support.
[platform/core/pim/libaccounts-svc.git] / src / account-capability-parser.c
1 /*
2  *  account
3  *
4  * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Wonyoung Lee <wy1115.lee@samsung.com>, Sungchan Kim <sungchan81.kim@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <account.h>
26 #include <glib.h>
27 #include <account-private.h>
28 #include <libxml/xmlmemory.h>
29 #include <libxml/parser.h>
30 #include <app.h>
31 #include <tzplatform_config.h>
32
33 #ifndef ACCOUNT_API
34 #define ACCOUNT_API __attribute__ ((visibility("default")))
35 #endif
36
37 #define ACCOUNT_XML_DIR         tzplatform_mkpath(TZ_SYS_SHARE, "account")
38 #define ACCOUNT_XML_OPT_DIR     tzplatform_mkpath(TZ_USER_SHARE, "account")
39 #define BUFSIZE 1024
40
41 static void _account_parse_doc(xmlDocPtr doc, xmlNodePtr cur,
42                                                         char *capability_filter, bool *supported)
43 {
44         xmlChar *key;
45         cur = cur->xmlChildrenNode;
46         while ((cur != NULL) && (*supported != true)) {
47                 if ((!xmlStrcmp(cur->name, (const xmlChar *)"capability"))) {
48                         key = xmlNodeGetContent(cur);
49                         ACCOUNT_DEBUG("Capability String is : %s\n", key);
50                         if (!strcmp(capability_filter, (char *)key)) {
51                                 *supported = true;
52                         }
53                         xmlFree(key);
54                 }
55         cur = cur->next;
56         }
57         return;
58 }
59
60 static bool _account_check_file_exists(char *f_path)
61 {
62         FILE *file;
63         if ((file = fopen(f_path, "r")) != NULL) {
64                 fclose(file);
65                 return TRUE;
66         }
67         return FALSE;
68 }
69
70 ACCOUNT_API int account_get_application_capability_support(char *package_name,
71                                                                 char *capability_filter, bool *supported)
72 {
73         if (!package_name) {
74                 ACCOUNT_ERROR("package_name can not be NULL \n");
75                 return ACCOUNT_ERROR_INVALID_PARAMETER;
76         }
77         if (!capability_filter) {
78                 ACCOUNT_ERROR("capability_filter can not be NULL \n");
79                 return ACCOUNT_ERROR_INVALID_PARAMETER;
80         }
81         if (!supported) {
82                 ACCOUNT_ERROR("supported pointer can not be NULL \n");
83                 return ACCOUNT_ERROR_INVALID_PARAMETER;
84         }
85         char    xml_file_path[BUFSIZE] = {0, };
86         xmlDocPtr doc = NULL;
87         xmlNodePtr cur = NULL;
88         *supported = false;
89
90         ACCOUNT_MEMSET(xml_file_path, 0, sizeof(xml_file_path));
91         ACCOUNT_SNPRINTF(xml_file_path, BUFSIZE, "%s/%s.account.xml",
92                                                         ACCOUNT_XML_DIR, package_name);
93
94         ACCOUNT_INFO("xml_file_path = %s \n",xml_file_path);
95
96         if (!_account_check_file_exists(xml_file_path)) {
97                 ACCOUNT_ERROR("XML file not found for %s \n", package_name);
98
99                 /*Check if file exists in /opt directory*/
100                 ACCOUNT_MEMSET(xml_file_path, 0, sizeof(xml_file_path));
101                 ACCOUNT_SNPRINTF(xml_file_path, BUFSIZE, "%s/%s.account.xml",
102                                                                 ACCOUNT_XML_OPT_DIR, package_name);
103
104                 ACCOUNT_INFO("xml_file_path = %s \n",xml_file_path);
105
106                 if (!_account_check_file_exists(xml_file_path)) {
107                         ACCOUNT_ERROR("XML file not found for %s \n", package_name);
108                 return ACCOUNT_ERROR_XML_FILE_NOT_FOUND;
109         }
110         }
111
112         doc = xmlParseFile(xml_file_path);
113         if (doc == NULL ) {
114                 ACCOUNT_ERROR("Document not parsed successfully. \n");
115                 return ACCOUNT_ERROR_XML_PARSE_FAILED;
116         }
117
118         cur = xmlDocGetRootElement(doc);
119         if (cur == NULL) {
120                 ACCOUNT_ERROR("empty document\n");
121                 xmlFreeDoc(doc);
122                 return ACCOUNT_ERROR_XML_PARSE_FAILED;
123         }
124
125         if (xmlStrcmp(cur->name, (const xmlChar *) "account")) {
126                 ACCOUNT_ERROR("document of the wrong type, root node != account");
127                 xmlFreeDoc(doc);
128                 return ACCOUNT_ERROR_XML_PARSE_FAILED;
129         }
130         _account_parse_doc(doc, cur, capability_filter, supported);
131         xmlFreeDoc(doc);
132
133         return ACCOUNT_ERROR_NONE;
134 }
135
136 ACCOUNT_API int account_get_application_multiple_account_support(
137                                                                 char *package_name,
138                                                                 bool *supported)
139 {
140         if (!package_name) {
141                 ACCOUNT_ERROR("package_name can not be NULL \n");
142                 return ACCOUNT_ERROR_INVALID_PARAMETER;
143         }
144         if (!supported) {
145                 ACCOUNT_ERROR("supported pointer can not be NULL \n");
146                 return ACCOUNT_ERROR_INVALID_PARAMETER;
147         }
148         char    xml_file_path[BUFSIZE] = {0, };
149         xmlDocPtr doc = NULL;
150         xmlNodePtr cur = NULL;
151         xmlChar *attr = NULL;
152         *supported = false;
153
154         ACCOUNT_MEMSET(xml_file_path, 0, sizeof(xml_file_path));
155         ACCOUNT_SNPRINTF(xml_file_path, BUFSIZE, "%s/%s.account.xml",
156                                                         ACCOUNT_XML_DIR, package_name);
157
158         ACCOUNT_VERBOSE("xml_file_path = %s \n",xml_file_path);
159
160         if (!_account_check_file_exists(xml_file_path)) {
161                 ACCOUNT_ERROR("XML file not found for %s \n", package_name);
162
163                 /*Check if file exists in /opt directory*/
164                 ACCOUNT_MEMSET(xml_file_path, 0, sizeof(xml_file_path));
165                 ACCOUNT_SNPRINTF(xml_file_path, BUFSIZE, "%s/%s.account.xml",
166                                                                 ACCOUNT_XML_OPT_DIR, package_name);
167
168                 ACCOUNT_VERBOSE("xml_file_path = %s \n",xml_file_path);
169
170                 if (!_account_check_file_exists(xml_file_path)) {
171                         ACCOUNT_ERROR("XML file not found for %s \n", package_name);
172                 return ACCOUNT_ERROR_XML_FILE_NOT_FOUND;
173         }
174         }
175
176         doc = xmlParseFile(xml_file_path);
177         if (doc == NULL ) {
178                 ACCOUNT_ERROR("Document not parsed successfully. \n");
179                 return ACCOUNT_ERROR_XML_PARSE_FAILED;
180         }
181
182         cur = xmlDocGetRootElement(doc);
183         if (cur == NULL) {
184                 ACCOUNT_ERROR("empty document\n");
185                 xmlFreeDoc(doc);
186                 return ACCOUNT_ERROR_XML_PARSE_FAILED;
187         }
188
189         if (xmlStrcmp(cur->name, (const xmlChar *) "account")) {
190                 ACCOUNT_ERROR("document of the wrong type, root node != account");
191                 xmlFreeDoc(doc);
192                 return ACCOUNT_ERROR_XML_PARSE_FAILED;
193         }
194         attr = xmlGetProp(cur, (const xmlChar *)"multiple");
195         ACCOUNT_INFO("Multiple = %s \n",(char *)attr);
196
197         if (attr == NULL)
198                 *supported = false;
199         else if (!strcmp("false", (char *)attr))
200                 *supported = false;
201         else if (!strcmp("true", (char *)attr))
202                 *supported = true;
203         else
204                 *supported = false;
205
206         xmlFreeDoc(doc);
207
208         return ACCOUNT_ERROR_NONE;
209 }
210
211 ACCOUNT_API int account_get_application_icon_path(const char *package_name,
212                                                                                         char **icon_path)
213 {
214         if (!package_name) {
215                 ACCOUNT_ERROR("package_name can not be NULL \n");
216                 return ACCOUNT_ERROR_INVALID_PARAMETER;
217         }
218         if (!icon_path) {
219                 ACCOUNT_ERROR("icon_path pointer can not be NULL \n");
220                 return ACCOUNT_ERROR_INVALID_PARAMETER;
221         }
222         char    xml_file_path[BUFSIZE] = {0, };
223         xmlDocPtr doc = NULL;
224         xmlNodePtr cur = NULL;
225         xmlChar *attr = NULL;
226         *icon_path = NULL;
227
228         ACCOUNT_MEMSET(xml_file_path, 0, sizeof(xml_file_path));
229         ACCOUNT_SNPRINTF(xml_file_path, BUFSIZE, "%s/%s.account.xml",
230                                                         ACCOUNT_XML_DIR, package_name);
231
232         ACCOUNT_INFO("xml_file_path = %s \n",xml_file_path);
233
234         if (!_account_check_file_exists(xml_file_path)) {
235                 ACCOUNT_ERROR("XML file not found for %s \n", package_name);
236
237                 /*Check if file exists in /opt directory*/
238                 ACCOUNT_MEMSET(xml_file_path, 0, sizeof(xml_file_path));
239                 ACCOUNT_SNPRINTF(xml_file_path, BUFSIZE, "%s/%s.account.xml",
240                                                                 ACCOUNT_XML_OPT_DIR, package_name);
241
242                 ACCOUNT_INFO("xml_file_path = %s \n",xml_file_path);
243
244                 if (!_account_check_file_exists(xml_file_path)) {
245                         ACCOUNT_ERROR("XML file not found for %s \n", package_name);
246                 return ACCOUNT_ERROR_XML_FILE_NOT_FOUND;
247         }
248         }
249
250         doc = xmlParseFile(xml_file_path);
251         if (doc == NULL ) {
252                 ACCOUNT_ERROR("Document not parsed successfully. \n");
253                 return ACCOUNT_ERROR_XML_PARSE_FAILED;
254         }
255
256         cur = xmlDocGetRootElement(doc);
257         if (cur == NULL) {
258                 ACCOUNT_ERROR("empty document\n");
259                 xmlFreeDoc(doc);
260                 return ACCOUNT_ERROR_XML_PARSE_FAILED;
261         }
262
263         if (xmlStrcmp(cur->name, (const xmlChar *) "account")) {
264                 ACCOUNT_ERROR("document of the wrong type, root node != account");
265                 xmlFreeDoc(doc);
266                 return ACCOUNT_ERROR_XML_PARSE_FAILED;
267         }
268         attr = xmlGetProp(cur, (const xmlChar *)"icon_path");
269         ACCOUNT_DEBUG("icon_path = %s \n",(char *)attr);
270
271         if (attr == NULL)
272                 *icon_path = NULL;
273         else
274                 *icon_path = strdup((char *)attr);
275
276         xmlFreeDoc(doc);
277
278         return ACCOUNT_ERROR_NONE;
279 }
280
281 static bool __service_iter_func(service_h service, const char* pkg_name,
282                                                                 void *data)
283 {
284         if (!pkg_name) {
285                 ACCOUNT_ERROR("__service_iter_func: pkg name NULL \n");
286                 return TRUE;
287         }
288         GList **pkg_list = (GList **)data;
289         char *pkgname = NULL;
290         pkgname = strdup(pkg_name);
291         *pkg_list = g_list_append(*pkg_list, pkgname);
292         return TRUE;
293 }
294
295 ACCOUNT_API int account_query_service_list_by_capability(service_list_cb callback,
296                                                                         const char* capability_type,
297                                                                         void *user_data)
298 {
299         int ret = SERVICE_ERROR_NONE;
300         GList *pkg_list = NULL;
301         service_h service = NULL;
302         GList *iter = NULL;
303         char *list_item = NULL;
304         char *capability_filter = NULL;
305         bool supported = false;
306         char *icon_path = NULL;
307         bool multiple = false;
308         int error_code = ACCOUNT_ERROR_NONE;
309
310         ACCOUNT_RETURN_VAL((capability_type != NULL), {}, ACCOUNT_ERROR_INVALID_PARAMETER, ("CAPABILITY TYPE IS NULL"));
311         ACCOUNT_RETURN_VAL((callback != NULL), {}, ACCOUNT_ERROR_INVALID_PARAMETER, ("CALL BACK IS NULL"));
312
313         ACCOUNT_VERBOSE("account_query_service_list_by_capability START \n");
314         ret = service_create(&service);
315         if (ret != SERVICE_ERROR_NONE) {
316                 ACCOUNT_ERROR("Owner Check : service_create fail ret=%d\n", ret);
317                 return ret;
318         } else {
319                 ACCOUNT_VERBOSE("service_list_by: service_create SUCCESS!!!!!! ret=%d\n", ret);
320         }
321         ret = service_set_operation(service, ACCOUNT_OPERATION_SIGNIN);
322         if (ret != SERVICE_ERROR_NONE) {
323                 ACCOUNT_ERROR("service_list_by : service_set_operation fail ret=%d\n", ret);
324                 service_destroy(service);
325                 return ret;
326         } else {
327                 ACCOUNT_VERBOSE("service_list_by : service_set_operation SUCCESS!!!!!! ret=%d\n",
328                                                         ret);
329         }
330         ret = service_foreach_app_matched(service, __service_iter_func, &pkg_list);
331         if (ret != SERVICE_ERROR_NONE) {
332                 ACCOUNT_ERROR("service_list_by : service_foreach_app_matched fail ret=%d\n",
333                                                         ret);
334                 service_destroy(service);
335                 return ret;
336         } else {
337                 ACCOUNT_VERBOSE("service_list_by : service_foreach_app_matched SUCCESS!!!!!! ret=%d\n",
338                                                         ret);
339         }
340
341         ret = service_destroy(service);
342         if (ret != SERVICE_ERROR_NONE) {
343                 ACCOUNT_ERROR("service_list_by : service_destroy fail ret=%d\n", ret);
344                 for (iter = pkg_list; iter != NULL; iter = g_list_next(iter)) {
345                         list_item = (char *)iter->data;
346                         g_free(list_item);
347                 }
348                 g_list_free(pkg_list);
349                 return ret;
350         } else {
351                 ACCOUNT_VERBOSE("service_list_by : service_destroy SUCCESS!!!!!! ret=%d\n", ret);
352         }
353
354         capability_filter = strdup(capability_type);
355
356         for (iter = pkg_list; iter != NULL; iter = g_list_next(iter)) {
357                 list_item = (char *)iter->data;
358                 error_code = account_get_application_capability_support(list_item,
359                                                                                                                 capability_filter,
360                                                                                                                 &supported);
361
362                 if ((error_code != ACCOUNT_ERROR_NONE)
363                         && (error_code != ACCOUNT_ERROR_XML_FILE_NOT_FOUND)) {
364                         ACCOUNT_ERROR("service_list_by : account_get_application_capability_support fail error_code=%d\n", error_code);
365                         for (iter = pkg_list; iter != NULL; iter = g_list_next(iter)) {
366                                 list_item = (char *)iter->data;
367                                 g_free(list_item);
368                         }
369                         g_list_free(pkg_list);
370                         _ACCOUNT_FREE(capability_filter);
371                         return error_code;
372                 }
373
374                 if (supported) {
375                         error_code = account_get_application_icon_path(list_item, &icon_path);
376                         if (error_code != ACCOUNT_ERROR_NONE) {
377                                 ACCOUNT_ERROR("service_list_by : account_get_application_capability_support fail error_code=%d\n", error_code);
378                                 for (iter = pkg_list; iter != NULL; iter = g_list_next(iter)) {
379                                         list_item = (char *)iter->data;
380                                         g_free(list_item);
381                                 }
382                                 g_list_free(pkg_list);
383                                 _ACCOUNT_FREE(capability_filter);
384                                 return error_code;
385                         }
386                         error_code = account_get_application_multiple_account_support(list_item, &multiple);
387                         if (error_code != ACCOUNT_ERROR_NONE) {
388                                 ACCOUNT_ERROR("service_list_by : account_get_application_capability_support fail error_code=%d\n", error_code);
389                                 for (iter = pkg_list; iter != NULL; iter = g_list_next(iter)) {
390                                         list_item = (char *)iter->data;
391                                         g_free(list_item);
392                                 }
393                                 g_list_free(pkg_list);
394                                 _ACCOUNT_FREE(capability_filter);
395                                 return error_code;
396                         }
397                         callback(list_item, icon_path, multiple, user_data);
398                 }
399         }
400         /* free list */
401         for (iter = pkg_list; iter != NULL; iter = g_list_next(iter)) {
402                 list_item = (char *)iter->data;
403                 g_free(list_item);
404         }
405         g_list_free(pkg_list);
406         _ACCOUNT_FREE(capability_filter);
407         return ACCOUNT_ERROR_NONE;
408 }