Merge "DPM: Add basic code for device policy manager for BT." into tizen
[platform/core/connectivity/bluetooth-frwk.git] / bt-service / bt-service-obex-server.c
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *              http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 #include <stdio.h>
19 #include <glib.h>
20 #include <dlog.h>
21 #include <string.h>
22 #include <dirent.h>
23 #ifdef TIZEN_MDM_ENABLE
24 #include <bt-service-mdm.h>
25 #endif
26 #include <vconf.h>
27
28 #include <gio/gio.h>
29
30 #include "bluetooth-api.h"
31 #include "bt-internal-types.h"
32
33 #include "bt-service-common.h"
34 #include "bt-service-event.h"
35 #include "bt-service-util.h"
36 #include "bt-service-obex-agent.h"
37 #include "bt-service-obex-server.h"
38 #include "bt-service-agent.h"
39
40 #define DBUS_TIMEOUT 20 * 1000 /* 20 Seconds */
41 #define BT_OBEX_SERVER_AGENT_PATH "/org/obex/server_agent"
42
43 #define BT_OBEX_SERVICE "org.bluez.obex"
44 #define BT_OBEX_MANAGER "org.bluez.obex.AgentManager1"
45 #define BT_OBEX_PATH "/org/bluez/obex"
46
47
48 typedef struct {
49         char *filename;
50         char *file_path;
51         char *path;
52         char *type;
53         char *device_name;
54         int transfer_id;
55         gint64 file_size;
56         char *address;
57 } bt_transfer_info_t;
58
59 typedef struct {
60         GDBusMethodInvocation *reply_context;
61         guint64 file_size;
62         char *filename;
63         char *file_path;
64         char *device_name;
65         char *transfer_path;
66         char *address;
67 } bt_auth_info_t;
68
69 typedef struct {
70         char *dest_path;
71         char *sender;
72         int app_pid;
73 } bt_server_info_t;
74
75 typedef struct {
76         GDBusProxy *proxy;
77         int server_type;
78         int accept_id;
79         bt_auth_info_t *auth_info;
80         bt_server_info_t *native_server;
81         bt_server_info_t *custom_server;
82 } bt_obex_agent_info_t;
83
84 static GSList *transfers;
85 static bt_obex_agent_info_t agent_info;
86
87 int _bt_obex_get_native_pid(void)
88 {
89         return agent_info.native_server->app_pid;
90 }
91
92 static GQuark __bt_obex_error_quark(void)
93 {
94         static GQuark quark = 0;
95         if (!quark)
96                 quark = g_quark_from_static_string("agent");
97
98         return quark;
99 }
100
101 static bt_transfer_info_t *__bt_find_transfer_by_id(int transfer_id)
102 {
103         GSList *l;
104         bt_transfer_info_t *transfer;
105
106         for (l = transfers; l != NULL; l = l->next) {
107                 transfer = l->data;
108
109                 if (transfer == NULL)
110                         continue;
111
112                 if (transfer->transfer_id == transfer_id)
113                         return transfer;
114         }
115
116         return NULL;
117 }
118
119 bt_transfer_info_t *__bt_find_transfer_by_address(const char *address)
120 {
121         BT_DBG("+");
122         GSList *l;
123         bt_transfer_info_t *transfer;
124
125         retv_if(address == NULL, NULL);
126
127         for (l = transfers; l != NULL; l = l->next) {
128                 transfer = l->data;
129
130                 if (transfer == NULL)
131                         continue;
132
133                 if (g_strcmp0(transfer->address, address) == 0)
134                         return transfer;
135         }
136         BT_DBG("-");
137         return NULL;
138 }
139
140 static bt_transfer_info_t *__bt_find_transfer_by_path(const char *transfer_path)
141 {
142         GSList *l;
143         bt_transfer_info_t *transfer;
144
145         retv_if(transfer_path == NULL, NULL);
146
147         for (l = transfers; l != NULL; l = l->next) {
148                 transfer = l->data;
149
150                 if (transfer == NULL)
151                         continue;
152
153                 if (g_strcmp0(transfer->path, transfer_path) == 0)
154                         return transfer;
155         }
156
157         return NULL;
158 }
159
160 static void __bt_free_server_info(bt_server_info_t *server_info)
161 {
162         ret_if(server_info == NULL);
163
164         g_free(server_info->sender);
165         g_free(server_info->dest_path);
166         g_free(server_info);
167 }
168
169 static void __bt_free_auth_info(bt_auth_info_t *auto_info)
170 {
171         ret_if(auto_info == NULL);
172
173         g_free(auto_info->filename);
174         g_free(auto_info->transfer_path);
175         g_free(auto_info->device_name);
176         g_free(auto_info->address);
177         g_free(auto_info);
178 }
179
180 static void __bt_free_transfer_info(bt_transfer_info_t *transfer_info)
181 {
182         ret_if(transfer_info == NULL);
183
184         g_free(transfer_info->path);
185         g_free(transfer_info->filename);
186         g_free(transfer_info->file_path);
187         g_free(transfer_info->type);
188         g_free(transfer_info->device_name);
189         g_free(transfer_info->address);
190         g_free(transfer_info);
191 }
192
193 void _bt_obex_check_pending_transfer(const char *address)
194 {
195         BT_DBG("+");
196         GVariant *param = NULL;
197         bt_transfer_info_t *transfer_info = __bt_find_transfer_by_address(address);
198         if (transfer_info != NULL) {
199                 int result = BLUETOOTH_ERROR_CANCEL;
200                 param = g_variant_new("(isssstii)", result,
201                                         transfer_info->filename,
202                                         transfer_info->type,
203                                         transfer_info->device_name,
204                                         transfer_info->file_path,
205                                         transfer_info->file_size,
206                                         transfer_info->transfer_id,
207                                         agent_info.server_type);
208                 _bt_send_event(BT_OPP_SERVER_EVENT,
209                         BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_COMPLETED,
210                         param);
211                 transfers = g_slist_remove(transfers, transfer_info);
212                 __bt_free_transfer_info(transfer_info);
213         }
214         BT_DBG("-");
215 }
216
217 static char *__bt_get_remote_device_name(const char *bdaddress)
218 {
219         char *device_path = NULL;
220         char *name = NULL;
221         GVariant *value;
222         GVariant *result = NULL;
223         GError *err = NULL;
224         GDBusProxy *device_proxy;
225         GDBusConnection *conn;
226
227         retv_if(bdaddress == NULL, NULL);
228
229         device_path = _bt_get_device_object_path((char *)bdaddress);
230         retv_if(device_path == NULL, NULL);
231
232         conn = _bt_get_system_gconn();
233         retv_if(conn == NULL, NULL);
234         BT_INFO("Device_path %s", device_path);
235         device_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
236                                                 NULL, BT_BLUEZ_NAME,
237                                                 device_path,
238                                                 BT_PROPERTIES_INTERFACE,
239                                                 NULL, &err);
240
241         g_free(device_path);
242         retv_if(device_proxy == NULL, NULL);
243
244         result = g_dbus_proxy_call_sync(device_proxy, "GetAll",
245                         g_variant_new("(s)", BT_DEVICE_INTERFACE),
246                         G_DBUS_CALL_FLAGS_NONE,
247                         DBUS_TIMEOUT, NULL,
248                         &err);
249         if (err) {
250                 BT_ERR("DBus Error : %s", err->message);
251                 g_clear_error(&err);
252                 return NULL;
253         }
254         if (result == NULL) {
255                 BT_ERR("g_dbus_proxy_call_sync function return NULL");
256                 return NULL;
257         }
258         g_variant_get(result, "(@a{sv})", &value);
259         g_variant_unref(result);
260
261         g_object_unref(device_proxy);
262         if (value) {
263                 GVariant *temp_value = g_variant_lookup_value(value, "Alias",
264                         G_VARIANT_TYPE_STRING);
265                 g_variant_get(temp_value, "(s)", &name);
266                 if (temp_value)
267                         g_variant_unref(temp_value);
268                 BT_INFO("Alias Name: %s", name);
269         }
270
271         return name;
272 }
273
274 static int __bt_get_transfer_id(const char *path)
275 {
276         char *tmp = NULL;
277         if (path == NULL)
278                 return -1;
279
280         tmp = strrchr(path, 'r') + 1;
281         retv_if(tmp == NULL, -1);
282
283         return atoi(tmp);
284 }
285
286 static GDBusProxy *__bt_get_transfer_proxy(const char *transfer_path)
287 {
288         GDBusConnection *conn;
289         GDBusProxy *proxy;
290         GError *err = NULL;
291
292         conn = _bt_get_session_gconn();
293         retv_if(conn == NULL, NULL);
294
295         proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
296                                         NULL, BT_OBEX_SERVICE_NAME,
297                                         transfer_path,
298                                         BT_OBEX_TRANSFER_INTERFACE,
299                                         NULL, &err);
300
301         if (err) {
302                 BT_ERR("Error : %s", err->message);
303                 g_clear_error(&err);
304                 return NULL;
305         }
306
307         return proxy;
308 }
309
310 static GDBusProxy *__bt_get_transfer_properties_proxy(const char *transfer_path)
311 {
312         GDBusConnection *conn;
313         GDBusProxy *proxy;
314         GError *err = NULL;
315         conn = _bt_get_session_gconn();
316         retv_if(conn == NULL, NULL);
317
318         proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
319                                         NULL,BT_OBEX_SERVICE_NAME,
320                                         transfer_path,
321                                         BT_PROPERTIES_INTERFACE,
322                                         NULL, &err);
323         if (err) {
324                 BT_ERR("Error : %s", err->message);
325                 g_clear_error(&err);
326                 return NULL;
327         }
328         return proxy;
329 }
330
331 static int __bt_get_transfer_properties(bt_transfer_info_t *transfer_info,
332                                         const char *transfer_path)
333 {
334         GDBusProxy *transfer_proxy;
335         char *bdaddress = NULL;
336         GVariant *result = NULL;
337         GError *err = NULL;
338         GVariantIter *iter = NULL;
339         BT_CHECK_PARAMETER(transfer_info, return);
340         BT_CHECK_PARAMETER(transfer_path, return);
341
342         transfer_proxy = __bt_get_transfer_properties_proxy(transfer_path);
343
344         retv_if(transfer_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
345
346         result = g_dbus_proxy_call_sync(transfer_proxy, "GetAll",
347                         g_variant_new("(s)", BT_OBEX_TRANSFER_INTERFACE),
348                         G_DBUS_CALL_FLAGS_NONE,
349                         DBUS_TIMEOUT, NULL,
350                         &err);
351
352         if (err) {
353                 BT_ERR("DBus Error : %s", err->message);
354                 g_clear_error(&err);
355                 goto fail;
356         }
357         if (result == NULL) {
358                 BT_ERR("g_dbus_proxy_call_sync function return NULL");
359                 goto fail;
360         }
361
362         g_variant_get(result, "(a{sv})", &iter);
363         g_variant_unref(result);
364         if (iter) {
365                 const gchar *key;
366                 GVariant *val;
367                 gsize len = 0;
368                 while (g_variant_iter_loop(iter, "{sv}", &key, &val)) {
369                         if (g_strcmp0(key, "Operation") == 0) {
370                                 transfer_info->type = g_variant_dup_string(val, &len);
371                         } else if (g_strcmp0(key, "Name") == 0) {
372                                 transfer_info->filename = g_variant_dup_string(val, &len);
373                         } else if (g_strcmp0(key, "Size") == 0) {
374                                 transfer_info->file_size = g_variant_get_uint64(val);
375                         } else if (g_strcmp0(key, "Address") == 0) {
376                                 transfer_info->address = g_variant_dup_string(val, &len);
377                                 BT_INFO("addressss %s", transfer_info->address);
378                         } else if (g_strcmp0(key, "Filename") == 0) {
379                                 transfer_info->file_path = g_variant_dup_string(val, &len);
380                                 if (!transfer_info->file_path)
381                                         transfer_info->file_path = g_strdup(transfer_info->filename);
382                         }
383                 }
384                 g_variant_iter_free(iter);
385                 if (transfer_info->type == NULL)
386                         goto fail;
387                 if (transfer_info->address == NULL)
388                         goto fail;
389
390                 transfer_info->device_name = __bt_get_remote_device_name(transfer_info->address);
391
392                 if (!transfer_info->device_name)
393                         transfer_info->device_name = g_strdup(bdaddress);
394                 transfer_info->path = g_strdup(transfer_path);
395                 transfer_info->transfer_id = __bt_get_transfer_id(transfer_path);
396         }
397
398         g_object_unref(transfer_proxy);
399         return BLUETOOTH_ERROR_NONE;
400
401 fail:
402         g_object_unref(transfer_proxy);
403         return BLUETOOTH_ERROR_INTERNAL;
404 }
405
406 static gboolean __bt_authorize_cb(GDBusMethodInvocation *context,
407                                         const char *path,
408                                         gpointer user_data)
409 {
410         char *device_name = NULL;
411         int result = BLUETOOTH_ERROR_NONE;
412         GDBusProxy *transfer_properties_proxy;
413         char * bdaddress = NULL;
414         GVariant *ret;
415         GVariantIter *iter;
416         GVariant *param = NULL;
417         GError *err = NULL;
418
419         BT_DBG(" path [%s] \n", path);
420
421         transfer_properties_proxy = __bt_get_transfer_properties_proxy(path);
422
423         retv_if(transfer_properties_proxy == NULL, FALSE);
424
425         ret = g_dbus_proxy_call_sync(transfer_properties_proxy, "GetAll",
426                         g_variant_new("(s)", BT_OBEX_TRANSFER_INTERFACE),
427                         G_DBUS_CALL_FLAGS_NONE,
428                         DBUS_TIMEOUT, NULL,
429                         &err);
430         if (err) {
431                 BT_ERR("DBus Error : %s", err->message);
432                 g_clear_error(&err);
433                 return FALSE;
434         }
435         if (ret == NULL) {
436                 BT_ERR("g_dbus_proxy_call_sync function return NULL");
437                 return FALSE;
438         }
439         g_variant_get(ret, "(a{sv})", &iter);
440         g_variant_unref(ret);
441         if (iter == NULL) {
442                 g_object_unref(transfer_properties_proxy);
443                 return FALSE;
444         }
445
446 #ifdef TIZEN_MDM_ENABLE
447         mdm_bt_allow_t mode = MDM_BT_ALLOWED;
448 #endif
449
450         __bt_free_auth_info(agent_info.auth_info);
451
452         agent_info.auth_info = g_malloc(sizeof(bt_auth_info_t));
453
454         memset(agent_info.auth_info, 0, sizeof(bt_auth_info_t));
455
456         agent_info.auth_info->reply_context = context;
457
458         agent_info.auth_info->transfer_path = g_strdup(path);
459
460         if (iter) {
461                 const gchar *key;
462                 GVariant *val;
463                 gsize len = 0;
464                 while (g_variant_iter_loop(iter, "{sv}", &key, &val)) {
465                         if (g_strcmp0(key, "Name") == 0) {
466                                 agent_info.auth_info->filename = g_variant_dup_string(val,&len);
467                         } else if (g_strcmp0(key, "Address") == 0) {
468                                 bdaddress = g_variant_dup_string(val, &len);
469                         } else if (g_strcmp0(key, "Size") == 0) {
470                                 agent_info.auth_info->file_size = g_variant_get_uint64(val);
471                         }
472                 }
473                 g_variant_iter_free(iter);
474         }
475
476         device_name = __bt_get_remote_device_name(bdaddress);
477
478         if (!device_name)
479                 device_name = g_strdup(bdaddress);
480
481         agent_info.auth_info->device_name = device_name;
482
483         g_object_unref(transfer_properties_proxy);
484
485         if (agent_info.server_type == BT_CUSTOM_SERVER) {
486                 /* No need to send the event */
487                 _bt_obex_server_accept_authorize(agent_info.auth_info->filename, FALSE);
488                 return TRUE;
489         }
490         param = g_variant_new("(ist)", result,
491                                 agent_info.auth_info->filename,
492                                 agent_info.auth_info->file_size);
493         _bt_send_event(BT_OPP_SERVER_EVENT,
494                 BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_AUTHORIZE,
495                 param);
496
497         return TRUE;
498 }
499
500 void _bt_obex_transfer_started(const char *transfer_path)
501 {
502         bt_transfer_info_t *transfer_info;
503         request_info_t *req_info;
504         GVariant *out_param1 = NULL;
505         GVariant *param = NULL;
506         int result = BLUETOOTH_ERROR_NONE;
507
508         BT_DBG("%s", transfer_path);
509
510         transfer_info = g_malloc0(sizeof(bt_transfer_info_t));
511
512         if (agent_info.auth_info != NULL
513              && g_strcmp0(transfer_path, agent_info.auth_info->transfer_path) == 0) {
514                 transfer_info->filename = g_strdup(agent_info.auth_info->filename);
515                 transfer_info->file_size = agent_info.auth_info->file_size;
516                 transfer_info->type = g_strdup(TRANSFER_PUT);
517                 transfer_info->path = g_strdup(agent_info.auth_info->transfer_path);
518                 transfer_info->device_name = g_strdup(agent_info.auth_info->device_name);
519                 transfer_info->transfer_id = __bt_get_transfer_id(transfer_path);
520                 transfer_info->file_path = agent_info.auth_info->file_path;
521                 transfer_info->address = g_strdup(agent_info.auth_info->address);
522         } else {
523                 if (__bt_get_transfer_properties(transfer_info, transfer_path) < 0) {
524                         BT_ERR("Get Properties failed");
525                         __bt_free_auth_info(agent_info.auth_info);
526                         __bt_free_transfer_info(transfer_info);
527                         agent_info.auth_info = NULL;
528                         return;
529                 }
530                 agent_info.server_type = BT_FTP_SERVER;
531         }
532
533         __bt_free_auth_info(agent_info.auth_info);
534         agent_info.auth_info = NULL;
535
536         if (agent_info.server_type == BT_CUSTOM_SERVER) {
537                 if (agent_info.custom_server == NULL) {
538                         __bt_free_transfer_info(transfer_info);
539                         return;
540                 }
541
542                 req_info = _bt_get_request_info(agent_info.accept_id);
543                 if (req_info == NULL || req_info->context == NULL) {
544                         BT_ERR("info is NULL");
545                         goto done;
546                 }
547
548                 agent_info.accept_id = 0;
549                 result = BLUETOOTH_ERROR_NONE;
550                 GArray *g_out_param1 = NULL;
551                 g_out_param1 = g_array_new(FALSE, FALSE, sizeof(gchar));
552                 if (out_param1 == NULL) {
553                         out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
554                                         g_out_param1->data, g_out_param1->len,
555                                         TRUE, NULL, NULL);
556                 }
557
558                 g_dbus_method_invocation_return_value(req_info->context,
559                                 g_variant_new("(iv)", result, out_param1));
560                 g_array_free(g_out_param1, TRUE);
561                 _bt_delete_request_list(req_info->req_id);
562         }
563 done:
564         transfers = g_slist_append(transfers, transfer_info);
565
566         BT_DBG("Transfer id %d\n", transfer_info->transfer_id);
567         param = g_variant_new("(isstii)", result,
568                                 transfer_info->filename,
569                                 transfer_info->type,
570                                 transfer_info->file_size,
571                                 transfer_info->transfer_id,
572                                 agent_info.server_type);
573         _bt_send_event(BT_OPP_SERVER_EVENT,
574                 BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_STARTED,
575                 param);
576 }
577
578 void _bt_obex_transfer_progress(const char *transfer_path,
579                                         int transferred)
580 {
581         BT_DBG("+");
582         bt_transfer_info_t *transfer_info;
583         int progress = 0;
584         GVariant *param = NULL;
585         int result = BLUETOOTH_ERROR_NONE;
586
587         transfer_info = __bt_find_transfer_by_path(transfer_path);
588         ret_if(transfer_info == NULL);
589
590         progress = (int)(((gdouble)transferred /
591                         (gdouble)transfer_info->file_size) * 100);
592
593         param = g_variant_new("(isstiii)", result,
594                                 transfer_info->filename,
595                                 transfer_info->type,
596                                 transfer_info->file_size,
597                                 transfer_info->transfer_id,
598                                 progress,
599                                 agent_info.server_type);
600         _bt_send_event(BT_OPP_SERVER_EVENT,
601                 BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_PROGRESS,
602                 param);
603         BT_DBG("-");
604 }
605
606 void _bt_obex_transfer_completed(const char *transfer_path, gboolean success)
607 {
608         bt_transfer_info_t *transfer_info;
609         GVariant *param = NULL;
610         int result;
611         BT_DBG("Transfer [%s] Success [%d] \n", transfer_path, success);
612
613         result = (success == TRUE) ? BLUETOOTH_ERROR_NONE
614                                 : BLUETOOTH_ERROR_CANCEL;
615
616         transfer_info = __bt_find_transfer_by_path(transfer_path);
617
618         if (transfer_info == NULL) {
619                 BT_DBG("Very small files receiving case, did not get Active status from obexd");
620                 if (agent_info.auth_info == NULL ||
621                                 g_strcmp0(transfer_path,
622                                 agent_info.auth_info->transfer_path) != 0) {
623                         BT_ERR("auth_info is NULL, returning");
624                         return;
625                 }
626
627                 transfer_info = g_new0(bt_transfer_info_t, 1);
628
629                 transfer_info->filename = g_strdup(agent_info.auth_info->filename);
630                 transfer_info->file_size = agent_info.auth_info->file_size;
631                 transfer_info->type = g_strdup(TRANSFER_PUT);
632                 transfer_info->path = g_strdup(agent_info.auth_info->transfer_path);
633                 transfer_info->device_name = g_strdup(agent_info.auth_info->device_name);
634                 transfer_info->transfer_id = __bt_get_transfer_id(transfer_path);
635                 transfer_info->file_path = agent_info.auth_info->file_path;
636
637                 param = g_variant_new("(isstii)", result,
638                                         transfer_info->filename,
639                                         transfer_info->type,
640                                         transfer_info->file_size,
641                                         transfer_info->transfer_id,
642                                         agent_info.server_type);
643                 _bt_send_event(BT_OPP_SERVER_EVENT,
644                         BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_STARTED,
645                         param);
646         }
647         param = g_variant_new("(isssstii)", result,
648                                 transfer_info->filename,
649                                 transfer_info->type,
650                                 transfer_info->device_name,
651                                 transfer_info->file_path,
652                                 transfer_info->file_size,
653                                 transfer_info->transfer_id,
654                                 agent_info.server_type);
655         _bt_send_event(BT_OPP_SERVER_EVENT,
656                 BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_COMPLETED,
657                 param);
658         transfers = g_slist_remove(transfers, transfer_info);
659         __bt_free_transfer_info(transfer_info);
660 }
661
662 void _bt_obex_transfer_connected()
663 {
664         BT_DBG("+");
665
666         int result = BLUETOOTH_ERROR_NONE;
667         GVariant *param = NULL;
668
669         param = g_variant_new("(i)", result);
670
671         _bt_send_event(BT_OPP_SERVER_EVENT,
672                 BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_CONNECTED,
673                 param);
674         BT_DBG("-");
675 }
676
677 void _bt_obex_transfer_disconnected()
678 {
679         BT_DBG("+");
680
681         int result = BLUETOOTH_ERROR_NONE;
682         GVariant *param = NULL;
683
684         param = g_variant_new("(i)", result);
685         _bt_send_event(BT_OPP_SERVER_EVENT,
686                 BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_DISCONNECTED,
687                 param);
688         BT_DBG("-");
689 }
690
691 int _bt_register_obex_server(void)
692 {
693         GDBusConnection *g_conn;
694         GDBusProxy *manager_proxy;
695         GError *g_error = NULL;
696
697         /* Get the session bus. */
698         g_conn = _bt_get_session_gconn();
699         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
700
701         _bt_obex_agent_new(BT_OBEX_SERVER_AGENT_PATH);
702
703         _bt_obex_setup(BT_OBEX_SERVER_AGENT_PATH);
704
705         _bt_obex_set_authorize_cb(BT_OBEX_SERVER_AGENT_PATH,
706                                         __bt_authorize_cb, NULL);
707
708         manager_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
709                                                 NULL, BT_OBEX_SERVICE,
710                                                 BT_OBEX_PATH,
711                                                 BT_OBEX_MANAGER,
712                                                 NULL, &g_error);
713
714         if (manager_proxy == NULL) {
715                 return BLUETOOTH_ERROR_INTERNAL;
716         }
717
718         g_dbus_proxy_call_sync(manager_proxy, "RegisterAgent",
719                                 g_variant_new("(o)", BT_OBEX_SERVER_AGENT_PATH),
720                                 G_DBUS_CALL_FLAGS_NONE,
721                                 DBUS_TIMEOUT, NULL,
722                                 &g_error);
723
724         if (g_error != NULL) {
725                 BT_ERR("Agent registration failed: %s\n", g_error->message);
726                 g_object_unref(manager_proxy);
727                 g_error_free(g_error);
728                 return BLUETOOTH_ERROR_INTERNAL;
729         }
730
731         agent_info.proxy = manager_proxy;
732
733         return BLUETOOTH_ERROR_NONE;
734 }
735
736 int _bt_unregister_obex_server(void)
737 {
738         GError *g_error = NULL;
739
740         retv_if(agent_info.proxy == NULL,
741                                 BLUETOOTH_ERROR_INTERNAL);
742
743         g_dbus_proxy_call_sync(agent_info.proxy, "UnregisterAgent",
744                                 g_variant_new("(o)", BT_OBEX_SERVER_AGENT_PATH),
745                                 G_DBUS_CALL_FLAGS_NONE,
746                                 DBUS_TIMEOUT, NULL,
747                                 &g_error);
748         if (g_error != NULL) {
749                 BT_ERR("Agent unregistration failed: %s", g_error->message);
750                 g_error_free(g_error);
751         }
752         _bt_obex_agent_destroy(BT_OBEX_SERVER_AGENT_PATH);
753         g_object_unref(agent_info.proxy);
754         agent_info.proxy = NULL;
755
756         return BLUETOOTH_ERROR_NONE;
757 }
758
759 gboolean __bt_check_folder_path(const char *dest_path)
760 {
761         DIR *dp;
762
763         retv_if(dest_path == NULL, FALSE);
764
765         dp = opendir(dest_path);
766
767         if (dp == NULL) {
768                 BT_ERR("The directory does not exist");
769                 return FALSE;
770         }
771
772         closedir(dp);
773
774         return TRUE;
775 }
776
777 int _bt_obex_server_allocate(char *sender, const char *dest_path, int app_pid, gboolean is_native)
778 {
779         BT_DBG("+");
780         if (__bt_check_folder_path(dest_path) == FALSE)
781                 return BLUETOOTH_ERROR_INVALID_PARAM;
782
783         if (is_native == TRUE) {
784                 retv_if(agent_info.native_server,
785                                 BLUETOOTH_ERROR_DEVICE_BUSY);
786
787                 /* Force to change the control to native */
788                 agent_info.native_server = g_malloc0(sizeof(bt_server_info_t));
789                 agent_info.native_server->dest_path = g_strdup(dest_path);
790                 agent_info.native_server->sender = g_strdup(sender);
791                 agent_info.native_server->app_pid = app_pid;
792                 agent_info.server_type = BT_NATIVE_SERVER;
793                 _bt_unregister_osp_server_in_agent(BT_OBEX_SERVER, NULL);
794         } else {
795                 retv_if(agent_info.custom_server,
796                                 BLUETOOTH_ERROR_DEVICE_BUSY);
797
798                 /* Force to change the control to custom */
799                 agent_info.custom_server = g_malloc0(sizeof(bt_server_info_t));
800                 agent_info.custom_server->dest_path = g_strdup(dest_path);
801                 agent_info.custom_server->sender = g_strdup(sender);
802                 agent_info.custom_server->app_pid = app_pid;
803                 agent_info.server_type = BT_CUSTOM_SERVER;
804                 _bt_register_osp_server_in_agent(BT_OBEX_SERVER, NULL, NULL, -1);
805         }
806         BT_DBG("-");
807         return BLUETOOTH_ERROR_NONE;
808 }
809
810 int _bt_obex_server_deallocate(int app_pid, gboolean is_native)
811 {
812         if (is_native == TRUE) {
813                 retv_if(agent_info.native_server == NULL,
814                                 BLUETOOTH_ERROR_AGENT_DOES_NOT_EXIST);
815
816                 retv_if(agent_info.native_server->app_pid != app_pid,
817                                 BLUETOOTH_ERROR_ACCESS_DENIED);
818
819                 __bt_free_server_info(agent_info.native_server);
820                 agent_info.native_server = NULL;
821
822                 /* Change the control to custom */
823                 if (agent_info.custom_server) {
824                         agent_info.server_type = BT_CUSTOM_SERVER;
825                         _bt_register_osp_server_in_agent(BT_OBEX_SERVER,
826                                                         NULL, NULL, -1);
827                 }
828         } else {
829                 retv_if(agent_info.custom_server == NULL,
830                                 BLUETOOTH_ERROR_AGENT_DOES_NOT_EXIST);
831
832                 retv_if(agent_info.custom_server->app_pid != app_pid,
833                                 BLUETOOTH_ERROR_ACCESS_DENIED);
834
835                 __bt_free_server_info(agent_info.custom_server);
836                 agent_info.custom_server = NULL;
837
838                 _bt_unregister_osp_server_in_agent(BT_OBEX_SERVER, NULL);
839
840                 /* Change the control to native */
841                 if (agent_info.native_server)
842                         agent_info.server_type = BT_NATIVE_SERVER;
843         }
844
845         return BLUETOOTH_ERROR_NONE;
846 }
847
848 int _bt_obex_server_accept_authorize(const char *filename, gboolean is_native)
849 {
850         char file_path[BT_FILE_PATH_MAX] = { 0 };
851         bt_server_info_t *server_info;
852
853         BT_CHECK_PARAMETER(filename, return);
854
855         retv_if(agent_info.auth_info == NULL, BLUETOOTH_ERROR_INTERNAL);
856
857         retv_if(agent_info.auth_info->reply_context == NULL,
858                                 BLUETOOTH_ERROR_INTERNAL);
859
860         if (is_native == TRUE)
861                 server_info = agent_info.native_server;
862         else
863                 server_info = agent_info.custom_server;
864
865         retv_if(server_info == NULL, BLUETOOTH_ERROR_INTERNAL);
866
867         if (server_info->dest_path != NULL)
868                 snprintf(file_path, sizeof(file_path), "%s/%s",
869                         server_info->dest_path, filename);
870         else
871                 snprintf(file_path, sizeof(file_path), "%s", filename);
872
873         g_dbus_method_invocation_return_value(agent_info.auth_info->reply_context,
874                 g_variant_new("(s)",&file_path));
875         agent_info.auth_info->reply_context = NULL;
876         agent_info.auth_info->file_path = g_strdup(file_path);
877
878         return BLUETOOTH_ERROR_NONE;
879 }
880
881 int _bt_obex_server_reject_authorize(void)
882 {
883         GError *g_error;
884
885         retv_if(agent_info.auth_info->reply_context == NULL,
886                                 BLUETOOTH_ERROR_INTERNAL);
887
888         g_error = g_error_new(__bt_obex_error_quark(),
889                         BT_OBEX_AGENT_ERROR_CANCEL,
890                         "CancelledByUser");
891
892         g_dbus_method_invocation_return_gerror(agent_info.auth_info->reply_context,
893                         g_error);
894         g_error_free(g_error);
895
896         __bt_free_auth_info(agent_info.auth_info);
897         agent_info.auth_info = NULL;
898
899         return BLUETOOTH_ERROR_NONE;
900 }
901
902 int _bt_obex_server_set_destination_path(const char *dest_path,
903                                                 gboolean is_native)
904 {
905         bt_server_info_t *server_info;
906
907         BT_CHECK_PARAMETER(dest_path, return);
908
909         DIR *dp = NULL;
910
911         dp = opendir(dest_path);
912
913         if (dp == NULL) {
914                 BT_ERR("The directory does not exist");
915                 return BLUETOOTH_ERROR_INVALID_PARAM;
916         }
917
918         closedir(dp);
919
920         if (is_native == TRUE)
921                 server_info = agent_info.native_server;
922         else
923                 server_info = agent_info.custom_server;
924
925         retv_if(server_info == NULL,
926                         BLUETOOTH_ERROR_AGENT_DOES_NOT_EXIST);
927
928         g_free(server_info->dest_path);
929         server_info->dest_path = g_strdup(dest_path);
930
931         return BLUETOOTH_ERROR_NONE;
932 }
933
934 int _bt_obex_server_set_root(const char *root)
935 {
936         GError *g_error = NULL;
937         GVariant *folder = NULL;
938         char *string = "Root";
939         DIR *dp = NULL;
940
941         BT_CHECK_PARAMETER(root, return);
942
943         retv_if(agent_info.proxy == NULL,
944                                 BLUETOOTH_ERROR_INTERNAL);
945
946         dp = opendir(root);
947
948         if (dp == NULL) {
949                 BT_ERR("The directory does not exist");
950                 return BLUETOOTH_ERROR_INVALID_PARAM;
951         }
952
953         closedir(dp);
954
955         folder = g_variant_new_string(root);
956         g_dbus_proxy_call_sync(agent_info.proxy, "SetProperty",
957                         g_variant_new("(sv)", string, folder),
958                         G_DBUS_CALL_FLAGS_NONE,
959                         DBUS_TIMEOUT, NULL,
960                         &g_error);
961
962         if (g_error) {
963                 BT_ERR("SetProperty Fail: %s", g_error->message);
964                 g_error_free(g_error);
965                 return BLUETOOTH_ERROR_INTERNAL;
966         }
967
968         return BLUETOOTH_ERROR_NONE;
969 }
970
971 int _bt_obex_server_cancel_transfer(int transfer_id)
972 {
973         bt_transfer_info_t *transfer = NULL;
974         GDBusProxy *proxy;
975         GError *err = NULL;
976         BT_DBG("+");
977         transfer = __bt_find_transfer_by_id(transfer_id);
978
979         retv_if(transfer == NULL, BLUETOOTH_ERROR_NOT_FOUND);
980         proxy = __bt_get_transfer_proxy(transfer->path);
981
982         retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
983
984         g_dbus_proxy_call_sync(proxy, "Cancel", NULL,
985                 G_DBUS_CALL_FLAGS_NONE,
986                 DBUS_TIMEOUT, NULL, &err);
987         if (err) {
988                 BT_ERR("Dbus Err: %s", err->message);
989                 g_clear_error(&err);
990         }
991         g_object_unref(proxy);
992
993         return BLUETOOTH_ERROR_NONE;
994 }
995
996 int _bt_obex_server_cancel_all_transfers(void)
997 {
998         GSList *l;
999         bt_transfer_info_t *transfer;
1000
1001         for (l = transfers; l != NULL; l = l->next) {
1002                 transfer = l->data;
1003
1004                 if (transfer == NULL)
1005                         continue;
1006
1007                 _bt_obex_server_cancel_transfer(transfer->transfer_id);
1008         }
1009
1010         return BLUETOOTH_ERROR_NONE;
1011 }
1012
1013 int _bt_obex_server_is_activated(gboolean *activated)
1014 {
1015         BT_CHECK_PARAMETER(activated, return);
1016
1017         if (agent_info.custom_server) {
1018                 *activated = TRUE;
1019         } else {
1020                 *activated = FALSE;
1021         }
1022
1023         return BLUETOOTH_ERROR_NONE;
1024 }
1025
1026 int _bt_obex_server_check_allocation(gboolean *allocation)
1027 {
1028         BT_CHECK_PARAMETER(allocation, return);
1029
1030         if (agent_info.native_server || agent_info.custom_server) {
1031                 *allocation = TRUE;
1032         } else {
1033                 *allocation = FALSE;
1034         }
1035
1036         return BLUETOOTH_ERROR_NONE;
1037 }
1038
1039 int _bt_obex_server_check_termination(char *sender)
1040 {
1041         BT_CHECK_PARAMETER(sender, return);
1042
1043         if (agent_info.native_server) {
1044                 if (g_strcmp0(sender, agent_info.native_server->sender) == 0) {
1045                         _bt_obex_server_deallocate(agent_info.native_server->app_pid,
1046                                                 TRUE);
1047                 }
1048         }
1049
1050         if (agent_info.custom_server) {
1051                 if (g_strcmp0(sender, agent_info.custom_server->sender) == 0) {
1052                         _bt_obex_server_deallocate(agent_info.custom_server->app_pid,
1053                                                 FALSE);
1054                 }
1055         }
1056
1057         return BLUETOOTH_ERROR_NONE;
1058 }
1059
1060 int _bt_obex_server_is_receiving(gboolean *receiving)
1061 {
1062         BT_CHECK_PARAMETER(receiving, return);
1063
1064         if (transfers == NULL || g_slist_length(transfers) == 0) {
1065                 *receiving = FALSE;
1066         } else {
1067                 *receiving = TRUE;
1068         }
1069
1070         return BLUETOOTH_ERROR_NONE;
1071 }
1072
1073 gboolean __bt_obex_server_accept_timeout_cb(gpointer user_data)
1074 {
1075         request_info_t *req_info;
1076         GVariant *out_param1 = NULL;
1077         int result = BLUETOOTH_ERROR_TIMEOUT;
1078
1079         /* Already reply in _bt_obex_transfer_started */
1080         retv_if(agent_info.accept_id == 0, FALSE);
1081
1082         req_info = _bt_get_request_info(agent_info.accept_id);
1083         if (req_info == NULL || req_info->context == NULL) {
1084                 BT_ERR("info is NULL");
1085                 return FALSE;
1086         }
1087
1088         agent_info.accept_id = 0;
1089         GArray *g_out_param1 = NULL;
1090         g_out_param1 = g_array_new(FALSE, FALSE, sizeof(gchar));
1091         if (out_param1 == NULL) {
1092                 out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
1093                                 g_out_param1->data, g_out_param1->len,
1094                                 TRUE, NULL, NULL);
1095         }
1096
1097         g_dbus_method_invocation_return_value(req_info->context,
1098                         g_variant_new("(iv)", result, out_param1));
1099         g_array_free(g_out_param1, TRUE);
1100         _bt_delete_request_list(req_info->req_id);
1101
1102         return FALSE;
1103 }
1104
1105 /* To support the BOT  */
1106 int _bt_obex_server_accept_connection(int request_id)
1107 {
1108         if (!_bt_agent_reply_authorize(TRUE))
1109                 return BLUETOOTH_ERROR_INTERNAL;
1110
1111         agent_info.accept_id = request_id;
1112
1113         g_timeout_add(BT_SERVER_ACCEPT_TIMEOUT,
1114                         (GSourceFunc)__bt_obex_server_accept_timeout_cb,
1115                         NULL);
1116
1117         return BLUETOOTH_ERROR_NONE;
1118 }
1119
1120 /* To support the BOT  */
1121 int _bt_obex_server_reject_connection(void)
1122 {
1123         if (!_bt_agent_reply_authorize(FALSE))
1124                 return BLUETOOTH_ERROR_INTERNAL;
1125
1126         return BLUETOOTH_ERROR_NONE;
1127 }
1128