97d44c309417b9a8c7de52c456e8cea98eb0ddbe
[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
32 #ifndef ACCOUNT_API
33 #define ACCOUNT_API __attribute__ ((visibility("default")))
34 #endif
35
36 #define ACCOUNT_XML_DIR "/usr/share/account"
37 #define ACCOUNT_XML_OPT_DIR "/opt/usr/share/account"
38 #define BUFSIZE 1024
39
40 static void _account_parse_doc(xmlDocPtr doc, xmlNodePtr cur,
41                                                         char *capability_filter, bool *supported)
42 {
43         xmlChar *key;
44         cur = cur->xmlChildrenNode;
45         while ((cur != NULL) && (*supported != true)) {
46                 if ((!xmlStrcmp(cur->name, (const xmlChar *)"capability"))) {
47                         key = xmlNodeGetContent(cur);
48                         ACCOUNT_DEBUG("Capability String is : %s\n", key);
49                         if (!strcmp(capability_filter, (char *)key)) {
50                                 *supported = true;
51                         }
52                         xmlFree(key);
53                 }
54         cur = cur->next;
55         }
56         return;
57 }
58
59 static bool _account_check_file_exists(char *f_path)
60 {
61         FILE *file;
62         if ((file = fopen(f_path, "r")) != NULL) {
63                 fclose(file);
64                 return TRUE;
65         }
66         return FALSE;
67 }
68
69 ACCOUNT_API int account_get_application_capability_support(char *package_name,
70                                                                 char *capability_filter, bool *supported)
71 {
72         if (!package_name) {
73                 ACCOUNT_ERROR("package_name can not be NULL \n");
74                 return ACCOUNT_ERROR_INVALID_PARAMETER;
75         }
76         if (!capability_filter) {
77                 ACCOUNT_ERROR("capability_filter can not be NULL \n");
78                 return ACCOUNT_ERROR_INVALID_PARAMETER;
79         }
80         if (!supported) {
81                 ACCOUNT_ERROR("supported pointer can not be NULL \n");
82                 return ACCOUNT_ERROR_INVALID_PARAMETER;
83         }
84         char    xml_file_path[BUFSIZE] = {0, };
85         xmlDocPtr doc = NULL;
86         xmlNodePtr cur = NULL;
87         *supported = false;
88
89         ACCOUNT_MEMSET(xml_file_path, 0, sizeof(xml_file_path));
90         ACCOUNT_SNPRINTF(xml_file_path, BUFSIZE, "%s/%s.account.xml",
91                                                         ACCOUNT_XML_DIR, package_name);
92
93         ACCOUNT_INFO("xml_file_path = %s \n",xml_file_path);
94
95         if (!_account_check_file_exists(xml_file_path)) {
96                 ACCOUNT_ERROR("XML file not found for %s \n", package_name);
97
98                 /*Check if file exists in /opt directory*/
99                 ACCOUNT_MEMSET(xml_file_path, 0, sizeof(xml_file_path));
100                 ACCOUNT_SNPRINTF(xml_file_path, BUFSIZE, "%s/%s.account.xml",
101                                                                 ACCOUNT_XML_OPT_DIR, package_name);
102
103                 ACCOUNT_INFO("xml_file_path = %s \n",xml_file_path);
104
105                 if (!_account_check_file_exists(xml_file_path)) {
106                         ACCOUNT_ERROR("XML file not found for %s \n", package_name);
107                 return ACCOUNT_ERROR_XML_FILE_NOT_FOUND;
108         }
109         }
110
111         doc = xmlParseFile(xml_file_path);
112         if (doc == NULL ) {
113                 ACCOUNT_ERROR("Document not parsed successfully. \n");
114                 return ACCOUNT_ERROR_XML_PARSE_FAILED;
115         }
116
117         cur = xmlDocGetRootElement(doc);
118         if (cur == NULL) {
119                 ACCOUNT_ERROR("empty document\n");
120                 xmlFreeDoc(doc);
121                 return ACCOUNT_ERROR_XML_PARSE_FAILED;
122         }
123
124         if (xmlStrcmp(cur->name, (const xmlChar *) "account")) {
125                 ACCOUNT_ERROR("document of the wrong type, root node != account");
126                 xmlFreeDoc(doc);
127                 return ACCOUNT_ERROR_XML_PARSE_FAILED;
128         }
129         _account_parse_doc(doc, cur, capability_filter, supported);
130         xmlFreeDoc(doc);
131
132         return ACCOUNT_ERROR_NONE;
133 }
134
135 ACCOUNT_API int account_get_application_multiple_account_support(
136                                                                 char *package_name,
137                                                                 bool *supported)
138 {
139         if (!package_name) {
140                 ACCOUNT_ERROR("package_name can not be NULL \n");
141                 return ACCOUNT_ERROR_INVALID_PARAMETER;
142         }
143         if (!supported) {
144                 ACCOUNT_ERROR("supported pointer can not be NULL \n");
145                 return ACCOUNT_ERROR_INVALID_PARAMETER;
146         }
147         char    xml_file_path[BUFSIZE] = {0, };
148         xmlDocPtr doc = NULL;
149         xmlNodePtr cur = NULL;
150         xmlChar *attr = NULL;
151         *supported = false;
152
153         ACCOUNT_MEMSET(xml_file_path, 0, sizeof(xml_file_path));
154         ACCOUNT_SNPRINTF(xml_file_path, BUFSIZE, "%s/%s.account.xml",
155                                                         ACCOUNT_XML_DIR, package_name);
156
157         ACCOUNT_VERBOSE("xml_file_path = %s \n",xml_file_path);
158
159         if (!_account_check_file_exists(xml_file_path)) {
160                 ACCOUNT_ERROR("XML file not found for %s \n", package_name);
161
162                 /*Check if file exists in /opt directory*/
163                 ACCOUNT_MEMSET(xml_file_path, 0, sizeof(xml_file_path));
164                 ACCOUNT_SNPRINTF(xml_file_path, BUFSIZE, "%s/%s.account.xml",
165                                                                 ACCOUNT_XML_OPT_DIR, package_name);
166
167                 ACCOUNT_VERBOSE("xml_file_path = %s \n",xml_file_path);
168
169                 if (!_account_check_file_exists(xml_file_path)) {
170                         ACCOUNT_ERROR("XML file not found for %s \n", package_name);
171                 return ACCOUNT_ERROR_XML_FILE_NOT_FOUND;
172         }
173         }
174
175         doc = xmlParseFile(xml_file_path);
176         if (doc == NULL ) {
177                 ACCOUNT_ERROR("Document not parsed successfully. \n");
178                 return ACCOUNT_ERROR_XML_PARSE_FAILED;
179         }
180
181         cur = xmlDocGetRootElement(doc);
182         if (cur == NULL) {
183                 ACCOUNT_ERROR("empty document\n");
184                 xmlFreeDoc(doc);
185                 return ACCOUNT_ERROR_XML_PARSE_FAILED;
186         }
187
188         if (xmlStrcmp(cur->name, (const xmlChar *) "account")) {
189                 ACCOUNT_ERROR("document of the wrong type, root node != account");
190                 xmlFreeDoc(doc);
191                 return ACCOUNT_ERROR_XML_PARSE_FAILED;
192         }
193         attr = xmlGetProp(cur, (const xmlChar *)"multiple");
194         ACCOUNT_INFO("Multiple = %s \n",(char *)attr);
195
196         if (attr == NULL)
197                 *supported = false;
198         else if (!strcmp("false", (char *)attr))
199                 *supported = false;
200         else if (!strcmp("true", (char *)attr))
201                 *supported = true;
202         else
203                 *supported = false;
204
205         xmlFreeDoc(doc);
206
207         return ACCOUNT_ERROR_NONE;
208 }
209
210 ACCOUNT_API int account_get_application_icon_path(const char *package_name,
211                                                                                         char **icon_path)
212 {
213         if (!package_name) {
214                 ACCOUNT_ERROR("package_name can not be NULL \n");
215                 return ACCOUNT_ERROR_INVALID_PARAMETER;
216         }
217         if (!icon_path) {
218                 ACCOUNT_ERROR("icon_path pointer can not be NULL \n");
219                 return ACCOUNT_ERROR_INVALID_PARAMETER;
220         }
221         char    xml_file_path[BUFSIZE] = {0, };
222         xmlDocPtr doc = NULL;
223         xmlNodePtr cur = NULL;
224         xmlChar *attr = NULL;
225         *icon_path = NULL;
226
227         ACCOUNT_MEMSET(xml_file_path, 0, sizeof(xml_file_path));
228         ACCOUNT_SNPRINTF(xml_file_path, BUFSIZE, "%s/%s.account.xml",
229                                                         ACCOUNT_XML_DIR, package_name);
230
231         ACCOUNT_INFO("xml_file_path = %s \n",xml_file_path);
232
233         if (!_account_check_file_exists(xml_file_path)) {
234                 ACCOUNT_ERROR("XML file not found for %s \n", package_name);
235
236                 /*Check if file exists in /opt directory*/
237                 ACCOUNT_MEMSET(xml_file_path, 0, sizeof(xml_file_path));
238                 ACCOUNT_SNPRINTF(xml_file_path, BUFSIZE, "%s/%s.account.xml",
239                                                                 ACCOUNT_XML_OPT_DIR, package_name);
240
241                 ACCOUNT_INFO("xml_file_path = %s \n",xml_file_path);
242
243                 if (!_account_check_file_exists(xml_file_path)) {
244                         ACCOUNT_ERROR("XML file not found for %s \n", package_name);
245                 return ACCOUNT_ERROR_XML_FILE_NOT_FOUND;
246         }
247         }
248
249         doc = xmlParseFile(xml_file_path);
250         if (doc == NULL ) {
251                 ACCOUNT_ERROR("Document not parsed successfully. \n");
252                 return ACCOUNT_ERROR_XML_PARSE_FAILED;
253         }
254
255         cur = xmlDocGetRootElement(doc);
256         if (cur == NULL) {
257                 ACCOUNT_ERROR("empty document\n");
258                 xmlFreeDoc(doc);
259                 return ACCOUNT_ERROR_XML_PARSE_FAILED;
260         }
261
262         if (xmlStrcmp(cur->name, (const xmlChar *) "account")) {
263                 ACCOUNT_ERROR("document of the wrong type, root node != account");
264                 xmlFreeDoc(doc);
265                 return ACCOUNT_ERROR_XML_PARSE_FAILED;
266         }
267         attr = xmlGetProp(cur, (const xmlChar *)"icon_path");
268         ACCOUNT_DEBUG("icon_path = %s \n",(char *)attr);
269
270         if (attr == NULL)
271                 *icon_path = NULL;
272         else
273                 *icon_path = strdup((char *)attr);
274
275         xmlFreeDoc(doc);
276
277         return ACCOUNT_ERROR_NONE;
278 }
279
280 static bool __service_iter_func(service_h service, const char* pkg_name,
281                                                                 void *data)
282 {
283         if (!pkg_name) {
284                 ACCOUNT_ERROR("__service_iter_func: pkg name NULL \n");
285                 return TRUE;
286         }
287         GList **pkg_list = (GList **)data;
288         char *pkgname = NULL;
289         pkgname = strdup(pkg_name);
290         *pkg_list = g_list_append(*pkg_list, pkgname);
291         return TRUE;
292 }
293
294 ACCOUNT_API int account_query_service_list_by_capability(service_list_cb callback,
295                                                                         const char* capability_type,
296                                                                         void *user_data)
297 {
298         int ret = SERVICE_ERROR_NONE;
299         GList *pkg_list = NULL;
300         service_h service = NULL;
301         GList *iter = NULL;
302         char *list_item = NULL;
303         char *capability_filter = NULL;
304         bool supported = false;
305         char *icon_path = NULL;
306         bool multiple = false;
307         int error_code = ACCOUNT_ERROR_NONE;
308
309         ACCOUNT_RETURN_VAL((capability_type != NULL), {}, ACCOUNT_ERROR_INVALID_PARAMETER, ("CAPABILITY TYPE IS NULL"));
310         ACCOUNT_RETURN_VAL((callback != NULL), {}, ACCOUNT_ERROR_INVALID_PARAMETER, ("CALL BACK IS NULL"));
311
312         ACCOUNT_VERBOSE("account_query_service_list_by_capability START \n");
313         ret = service_create(&service);
314         if (ret != SERVICE_ERROR_NONE) {
315                 ACCOUNT_ERROR("Owner Check : service_create fail ret=%d\n", ret);
316                 return ret;
317         } else {
318                 ACCOUNT_VERBOSE("service_list_by: service_create SUCCESS!!!!!! ret=%d\n", ret);
319         }
320         ret = service_set_operation(service, ACCOUNT_OPERATION_SIGNIN);
321         if (ret != SERVICE_ERROR_NONE) {
322                 ACCOUNT_ERROR("service_list_by : service_set_operation fail ret=%d\n", ret);
323                 service_destroy(service);
324                 return ret;
325         } else {
326                 ACCOUNT_VERBOSE("service_list_by : service_set_operation SUCCESS!!!!!! ret=%d\n",
327                                                         ret);
328         }
329         ret = service_foreach_app_matched(service, __service_iter_func, &pkg_list);
330         if (ret != SERVICE_ERROR_NONE) {
331                 ACCOUNT_ERROR("service_list_by : service_foreach_app_matched fail ret=%d\n",
332                                                         ret);
333                 service_destroy(service);
334                 return ret;
335         } else {
336                 ACCOUNT_VERBOSE("service_list_by : service_foreach_app_matched SUCCESS!!!!!! ret=%d\n",
337                                                         ret);
338         }
339
340         ret = service_destroy(service);
341         if (ret != SERVICE_ERROR_NONE) {
342                 ACCOUNT_ERROR("service_list_by : service_destroy fail ret=%d\n", ret);
343                 for (iter = pkg_list; iter != NULL; iter = g_list_next(iter)) {
344                         list_item = (char *)iter->data;
345                         g_free(list_item);
346                 }
347                 g_list_free(pkg_list);
348                 return ret;
349         } else {
350                 ACCOUNT_VERBOSE("service_list_by : service_destroy SUCCESS!!!!!! ret=%d\n", ret);
351         }
352
353         capability_filter = strdup(capability_type);
354
355         for (iter = pkg_list; iter != NULL; iter = g_list_next(iter)) {
356                 list_item = (char *)iter->data;
357                 error_code = account_get_application_capability_support(list_item,
358                                                                                                                 capability_filter,
359                                                                                                                 &supported);
360
361                 if ((error_code != ACCOUNT_ERROR_NONE)
362                         && (error_code != ACCOUNT_ERROR_XML_FILE_NOT_FOUND)) {
363                         ACCOUNT_ERROR("service_list_by : account_get_application_capability_support fail error_code=%d\n", error_code);
364                         for (iter = pkg_list; iter != NULL; iter = g_list_next(iter)) {
365                                 list_item = (char *)iter->data;
366                                 g_free(list_item);
367                         }
368                         g_list_free(pkg_list);
369                         _ACCOUNT_FREE(capability_filter);
370                         return error_code;
371                 }
372
373                 if (supported) {
374                         error_code = account_get_application_icon_path(list_item, &icon_path);
375                         if (error_code != ACCOUNT_ERROR_NONE) {
376                                 ACCOUNT_ERROR("service_list_by : account_get_application_capability_support fail error_code=%d\n", error_code);
377                                 for (iter = pkg_list; iter != NULL; iter = g_list_next(iter)) {
378                                         list_item = (char *)iter->data;
379                                         g_free(list_item);
380                                 }
381                                 g_list_free(pkg_list);
382                                 _ACCOUNT_FREE(capability_filter);
383                                 return error_code;
384                         }
385                         error_code = account_get_application_multiple_account_support(list_item, &multiple);
386                         if (error_code != ACCOUNT_ERROR_NONE) {
387                                 ACCOUNT_ERROR("service_list_by : account_get_application_capability_support fail error_code=%d\n", error_code);
388                                 for (iter = pkg_list; iter != NULL; iter = g_list_next(iter)) {
389                                         list_item = (char *)iter->data;
390                                         g_free(list_item);
391                                 }
392                                 g_list_free(pkg_list);
393                                 _ACCOUNT_FREE(capability_filter);
394                                 return error_code;
395                         }
396                         callback(list_item, icon_path, multiple, user_data);
397                 }
398         }
399         /* free list */
400         for (iter = pkg_list; iter != NULL; iter = g_list_next(iter)) {
401                 list_item = (char *)iter->data;
402                 g_free(list_item);
403         }
404         g_list_free(pkg_list);
405         _ACCOUNT_FREE(capability_filter);
406         return ACCOUNT_ERROR_NONE;
407 }