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