Merge branch 'master' into tizen_2.1
[platform/core/connectivity/bluetooth-frwk.git] / bt-service / bt-service-obex-server.c
1 /*
2  * bluetooth-frwk
3  *
4  * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *              http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #include <dbus/dbus-glib.h>
21 #include <dbus/dbus.h>
22 #include <stdio.h>
23 #include <glib.h>
24 #include <dlog.h>
25 #include <string.h>
26 #include <dirent.h>
27 #include <vconf.h>
28
29 #include "bluetooth-api.h"
30 #include "bt-internal-types.h"
31
32 #include "bt-service-common.h"
33 #include "bt-service-event.h"
34 #include "bt-service-util.h"
35 #include "bt-service-obex-agent.h"
36 #include "bt-service-obex-server.h"
37 #include "bt-service-agent.h"
38
39 #define BT_OBEX_SERVER_AGENT_PATH "/org/obex/server_agent"
40 #define BT_OBEX_SERVICE "org.openobex"
41 #define BT_OBEX_MANAGER "org.openobex.Manager"
42
43 typedef struct {
44         char *filename;
45         char *path;
46         char *type;
47         char *device_name;
48         int transfer_id;
49         gint64 file_size;
50 } bt_transfer_info_t;
51
52 typedef struct {
53         DBusGMethodInvocation *reply_context;
54         gint64 file_size;
55         char *filename;
56         char *device_name;
57         char *transfer_path;
58 } bt_auth_info_t;
59
60 typedef struct {
61         char *dest_path;
62         char *sender;
63         int app_pid;
64 } bt_server_info_t;
65
66 typedef struct {
67         BtObexAgent *obex_agent;
68         DBusGProxy *proxy;
69         int server_type;
70         int accept_id;
71         bt_auth_info_t *auth_info;
72         bt_server_info_t *native_server;
73         bt_server_info_t *custom_server;
74 } bt_obex_agent_info_t;
75
76 static GSList *transfers;
77 static bt_obex_agent_info_t agent_info;
78
79 static GQuark __bt_obex_error_quark(void)
80 {
81         static GQuark quark = 0;
82         if (!quark)
83                 quark = g_quark_from_static_string("agent");
84
85         return quark;
86 }
87
88 static bt_transfer_info_t *__bt_find_transfer_by_id(int transfer_id)
89 {
90         GSList *l;
91         bt_transfer_info_t *transfer;
92
93         for (l = transfers; l != NULL; l = l->next) {
94                 transfer = l->data;
95
96                 if (transfer == NULL)
97                         continue;
98
99                 if (transfer->transfer_id == transfer_id)
100                         return transfer;
101         }
102
103         return NULL;
104 }
105
106 static bt_transfer_info_t *__bt_find_transfer_by_path(const char *transfer_path)
107 {
108         GSList *l;
109         bt_transfer_info_t *transfer;
110
111         retv_if(transfer_path == NULL, NULL);
112
113         for (l = transfers; l != NULL; l = l->next) {
114                 transfer = l->data;
115
116                 if (transfer == NULL)
117                         continue;
118
119                 if (g_strcmp0(transfer->path, transfer_path) == 0)
120                         return transfer;
121         }
122
123         return NULL;
124 }
125
126 static void __bt_free_server_info(bt_server_info_t *server_info)
127 {
128         ret_if(server_info == NULL);
129
130         g_free(server_info->sender);
131         g_free(server_info->dest_path);
132         g_free(server_info);
133 }
134
135 static void __bt_free_auth_info(bt_auth_info_t *auto_info)
136 {
137         ret_if(auto_info == NULL);
138
139         g_free(auto_info->filename);
140         g_free(auto_info->transfer_path);
141         g_free(auto_info->device_name);
142         g_free(auto_info);
143 }
144
145 static void __bt_free_transfer_info(bt_transfer_info_t *transfer_info)
146 {
147         ret_if(transfer_info == NULL);
148
149         g_free(transfer_info->path);
150         g_free(transfer_info->filename);
151         g_free(transfer_info->type);
152         g_free(transfer_info->device_name);
153         g_free(transfer_info);
154 }
155
156 static char *__bt_get_remote_device_name(const char *bdaddress)
157 {
158         GError *error = NULL;
159         char *device_path = NULL;
160         char *name = NULL;
161         GHashTable *hash = NULL;
162         GValue *value;
163         DBusGProxy *device_proxy;
164         DBusGProxy *adapter_proxy;
165         DBusGConnection *conn;
166
167         retv_if(bdaddress == NULL, NULL);
168
169         adapter_proxy = _bt_get_adapter_proxy();
170         retv_if(adapter_proxy == NULL, NULL);
171
172         conn = _bt_get_system_gconn();
173         retv_if(conn == NULL, NULL);
174
175         dbus_g_proxy_call(adapter_proxy, "FindDevice", NULL,
176                           G_TYPE_STRING, bdaddress, G_TYPE_INVALID,
177                           DBUS_TYPE_G_OBJECT_PATH, &device_path, G_TYPE_INVALID);
178
179         retv_if(device_path == NULL, NULL);
180
181         device_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME,
182                                       device_path, BT_DEVICE_INTERFACE);
183         g_free(device_path);
184         retv_if(device_proxy == NULL, NULL);
185         if (!dbus_g_proxy_call(device_proxy, "GetProperties", &error,
186                         G_TYPE_INVALID,
187                         dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
188                         &hash, G_TYPE_INVALID)) {
189                 if (error) {
190                         BT_ERR( "error in GetBasicProperties [%s]\n", error->message);
191                         g_error_free(error);
192                 }
193                 g_object_unref(device_proxy);
194                 return NULL;
195         }
196
197         if (hash != NULL) {
198                 value = g_hash_table_lookup(hash, "Alias");
199                 name = value ? g_value_dup_string(value) : NULL;
200                 g_hash_table_destroy(hash);
201         }
202
203         g_object_unref(device_proxy);
204
205         return name;
206 }
207
208 static int __bt_get_transfer_id(const char *path)
209 {
210         char *tmp = NULL;
211         if (path == NULL)
212                 return -1;
213
214         tmp = strrchr(path, 'r') + 1;
215         retv_if(tmp == NULL, -1);
216
217         return atoi(tmp);
218 }
219
220 static DBusGProxy *__bt_get_transfer_proxy(const char *transfer_path)
221 {
222         DBusGConnection *conn;
223         DBusGProxy *proxy;
224
225         conn = _bt_get_session_gconn();
226         retv_if(conn == NULL, NULL);
227
228         proxy = dbus_g_proxy_new_for_name(conn,
229                                         BT_OBEXD_INTERFACE,
230                                         transfer_path,
231                                         BT_OBEXD_TRANSFER_INTERFACE);
232
233         return proxy;
234 }
235
236 static int __bt_get_transfer_properties(bt_transfer_info_t *transfer_info,
237                                         const char *transfer_path)
238 {
239         GHashTable *hash = NULL;
240         GValue *value;
241         DBusGProxy *transfer_proxy;
242         char *bdaddress;
243
244         BT_CHECK_PARAMETER(transfer_info, return);
245         BT_CHECK_PARAMETER(transfer_path, return);
246
247         transfer_proxy = __bt_get_transfer_proxy(transfer_path);
248
249         retv_if(transfer_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
250
251         dbus_g_proxy_call(transfer_proxy, "GetProperties", NULL,
252                                 G_TYPE_INVALID,
253                                 dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
254                                 &hash, G_TYPE_INVALID);
255
256         if (hash == NULL) {
257                 g_object_unref(transfer_proxy);
258                 return BLUETOOTH_ERROR_INTERNAL;
259         }
260
261         value = g_hash_table_lookup(hash, "Operation");
262         transfer_info->type = value ? g_strdup(g_value_get_string(value)) : NULL;
263         if (!transfer_info->type)
264                 goto fail;
265
266         value = g_hash_table_lookup(hash, "Filename");
267         transfer_info->filename = value ? g_strdup(g_value_get_string(value)) : NULL;
268         if (!transfer_info->filename)
269                 goto fail;
270
271         value = g_hash_table_lookup(hash, "Size");
272         transfer_info->file_size  = value ? g_value_get_uint64(value) : 0;
273
274         transfer_info->path = g_strdup(transfer_path);
275         transfer_info->transfer_id = __bt_get_transfer_id(transfer_path);
276
277         value = g_hash_table_lookup(hash, "Address");
278         bdaddress = value ? (char *)g_value_get_string(value) : NULL;
279         if (!bdaddress)
280                 goto fail;
281
282         transfer_info->device_name = __bt_get_remote_device_name(bdaddress);
283         if (!transfer_info->device_name)
284                 transfer_info->device_name = g_strdup(bdaddress);
285
286         g_hash_table_destroy(hash);
287         g_object_unref(transfer_proxy);
288         return BLUETOOTH_ERROR_NONE;
289
290 fail:
291         g_hash_table_destroy(hash);
292         g_object_unref(transfer_proxy);
293         return BLUETOOTH_ERROR_INTERNAL;
294 }
295
296 static gboolean __bt_authorize_cb(DBusGMethodInvocation *context,
297                                         const char *path,
298                                         const char *bdaddress,
299                                         const char *name,
300                                         const char *type,
301                                         gint length,
302                                         gint time,
303                                         gpointer user_data)
304 {
305         char *device_name = NULL;
306         int result = BLUETOOTH_ERROR_NONE;
307
308         BT_DBG(" File name [%s] Address [%s] Type [%s] length [%d] path [%s] \n",
309             name, bdaddress, type, length, path);
310
311         __bt_free_auth_info(agent_info.auth_info);
312
313         agent_info.auth_info = g_malloc(sizeof(bt_auth_info_t));
314
315         agent_info.auth_info->reply_context = context;
316         agent_info.auth_info->filename = g_strdup(name);
317         agent_info.auth_info->file_size = length;
318         agent_info.auth_info->transfer_path = g_strdup(path);
319
320         device_name = __bt_get_remote_device_name(bdaddress);
321
322         if (!device_name)
323                 device_name = g_strdup(bdaddress);
324
325         agent_info.auth_info->device_name = device_name;
326
327         if (agent_info.server_type == BT_CUSTOM_SERVER) {
328                 /* No need to send the event */
329                 _bt_obex_server_accept_authorize(agent_info.auth_info->filename, FALSE);
330                 return TRUE;
331         }
332
333         _bt_send_event(BT_OPP_SERVER_EVENT,
334                 BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_AUTHORIZE,
335                 DBUS_TYPE_INT32, &result,
336                 DBUS_TYPE_STRING, &agent_info.auth_info->filename,
337                 DBUS_TYPE_UINT64, &agent_info.auth_info->file_size,
338                 DBUS_TYPE_INVALID);
339
340         return TRUE;
341 }
342
343 void _bt_obex_transfer_started(const char *transfer_path)
344 {
345         bt_transfer_info_t *transfer_info;
346         request_info_t *req_info;
347         GArray *out_param1 = NULL;
348         GArray *out_param2 = NULL;
349         int result = BLUETOOTH_ERROR_NONE;
350
351         BT_DBG("%s", transfer_path);
352
353         transfer_info = g_malloc0(sizeof(bt_transfer_info_t));
354
355         if (agent_info.auth_info != NULL
356              && g_strcmp0(transfer_path, agent_info.auth_info->transfer_path) == 0) {
357                 transfer_info->filename = g_strdup(agent_info.auth_info->filename);
358                 transfer_info->file_size = agent_info.auth_info->file_size;
359                 transfer_info->type = g_strdup(TRANSFER_PUT);
360                 transfer_info->path = g_strdup(agent_info.auth_info->transfer_path);
361                 transfer_info->device_name = g_strdup(agent_info.auth_info->device_name);
362                 transfer_info->transfer_id = __bt_get_transfer_id(transfer_path);
363         } else {
364                 if (__bt_get_transfer_properties(transfer_info, transfer_path) < 0) {
365                         BT_ERR("Get Properties failed");
366                         __bt_free_auth_info(agent_info.auth_info);
367                         __bt_free_transfer_info(transfer_info);
368                         agent_info.auth_info = NULL;
369                         return;
370                 }
371                 agent_info.server_type = BT_FTP_SERVER;
372         }
373
374         __bt_free_auth_info(agent_info.auth_info);
375         agent_info.auth_info = NULL;
376
377         if (agent_info.server_type == BT_CUSTOM_SERVER) {
378                 if (agent_info.custom_server == NULL) {
379                         __bt_free_transfer_info(transfer_info);
380                         return;
381                 }
382
383                 req_info = _bt_get_request_info(agent_info.accept_id);
384                 if (req_info == NULL || req_info->context == NULL) {
385                         BT_ERR("info is NULL");
386                         goto done;
387                 }
388
389                 agent_info.accept_id = 0;
390                 result = BLUETOOTH_ERROR_NONE;
391
392                 out_param1 = g_array_new(FALSE, FALSE, sizeof(gchar));
393                 out_param2 = g_array_new(FALSE, FALSE, sizeof(gchar));
394
395                 g_array_append_vals(out_param2, &result, sizeof(int));
396
397                 dbus_g_method_return(req_info->context, out_param1, out_param2);
398
399                 g_array_free(out_param1, TRUE);
400                 g_array_free(out_param2, TRUE);
401
402                 _bt_delete_request_list(req_info->req_id);
403         }
404 done:
405         transfers = g_slist_append(transfers, transfer_info);
406
407         BT_DBG("Transfer id %d\n", transfer_info->transfer_id);
408
409         _bt_send_event(BT_OPP_SERVER_EVENT,
410                 BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_STARTED,
411                 DBUS_TYPE_INT32, &result,
412                 DBUS_TYPE_STRING, &transfer_info->filename,
413                 DBUS_TYPE_STRING, &transfer_info->type,
414                 DBUS_TYPE_UINT64, &transfer_info->file_size,
415                 DBUS_TYPE_INT32, &transfer_info->transfer_id,
416                 DBUS_TYPE_INT32, &agent_info.server_type,
417                 DBUS_TYPE_INVALID);
418 }
419
420 void _bt_obex_transfer_progress(const char *transfer_path,
421                                         int total,
422                                         int transferred)
423 {
424         bt_transfer_info_t *transfer_info;
425         int progress = 0;
426         int result = BLUETOOTH_ERROR_NONE;
427
428         transfer_info = __bt_find_transfer_by_path(transfer_path);
429         ret_if(transfer_info == NULL);
430
431         progress = (int)(((gdouble)transferred /(gdouble)total) * 100);
432
433         _bt_send_event(BT_OPP_SERVER_EVENT,
434                 BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_PROGRESS,
435                 DBUS_TYPE_INT32, &result,
436                 DBUS_TYPE_STRING, &transfer_info->filename,
437                 DBUS_TYPE_STRING, &transfer_info->type,
438                 DBUS_TYPE_UINT64, &transfer_info->file_size,
439                 DBUS_TYPE_INT32, &transfer_info->transfer_id,
440                 DBUS_TYPE_INT32, &progress,
441                 DBUS_TYPE_INT32, &agent_info.server_type,
442                 DBUS_TYPE_INVALID);
443 }
444
445 void _bt_obex_transfer_completed(const char *transfer_path, gboolean success)
446 {
447         bt_transfer_info_t *transfer_info;
448         int result;
449         BT_DBG("Transfer [%s] Success [%d] \n", transfer_path, success);
450
451         result = (success == TRUE) ? BLUETOOTH_ERROR_NONE
452                                 : BLUETOOTH_ERROR_CANCEL;
453
454         transfer_info = __bt_find_transfer_by_path(transfer_path);
455         ret_if(transfer_info == NULL);
456
457         _bt_send_event(BT_OPP_SERVER_EVENT,
458                 BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_COMPLETED,
459                 DBUS_TYPE_INT32, &result,
460                 DBUS_TYPE_STRING, &transfer_info->filename,
461                 DBUS_TYPE_STRING, &transfer_info->type,
462                 DBUS_TYPE_STRING, &transfer_info->device_name,
463                 DBUS_TYPE_UINT64, &transfer_info->file_size,
464                 DBUS_TYPE_INT32, &transfer_info->transfer_id,
465                 DBUS_TYPE_INT32, &agent_info.server_type,
466                 DBUS_TYPE_INVALID);
467
468         transfers = g_slist_remove(transfers, transfer_info);
469         __bt_free_transfer_info(transfer_info);
470 }
471
472 int _bt_register_obex_server(void)
473 {
474         DBusGConnection *g_conn;
475         DBusGProxy *manager_proxy;
476         GError *g_error = NULL;
477
478         /* Get the session bus. */
479         g_conn = _bt_get_session_gconn();
480         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
481
482         if (!agent_info.obex_agent) {
483                 agent_info.obex_agent = _bt_obex_agent_new();
484
485                 retv_if(agent_info.obex_agent == NULL, BLUETOOTH_ERROR_INTERNAL);
486
487                 _bt_obex_setup(agent_info.obex_agent, BT_OBEX_SERVER_AGENT_PATH);
488
489                 _bt_obex_set_authorize_cb(agent_info.obex_agent,
490                                         __bt_authorize_cb, NULL);
491         }
492
493         manager_proxy = dbus_g_proxy_new_for_name(g_conn, BT_OBEX_SERVICE,
494                                                 "/", BT_OBEX_MANAGER);
495
496         if (manager_proxy == NULL) {
497                 g_object_unref(agent_info.obex_agent);
498                 agent_info.obex_agent = NULL;
499                 return BLUETOOTH_ERROR_INTERNAL;
500         }
501
502         dbus_g_proxy_call(manager_proxy, "RegisterAgent", &g_error,
503                           DBUS_TYPE_G_OBJECT_PATH, BT_OBEX_SERVER_AGENT_PATH,
504                           G_TYPE_INVALID, G_TYPE_INVALID);
505         if (g_error != NULL) {
506                 BT_ERR("Agent registration failed: %s\n", g_error->message);
507                 g_object_unref(agent_info.obex_agent);
508                 agent_info.obex_agent = NULL;
509                 g_object_unref(manager_proxy);
510                 g_error_free(g_error);
511                 return BLUETOOTH_ERROR_INTERNAL;
512         }
513
514         agent_info.proxy = manager_proxy;
515
516         return BLUETOOTH_ERROR_NONE;
517 }
518
519 int _bt_unregister_obex_server(void)
520 {
521         GError *g_error = NULL;
522
523         retv_if(agent_info.obex_agent == NULL,
524                                 BLUETOOTH_ERROR_AGENT_DOES_NOT_EXIST);
525
526         retv_if(agent_info.proxy == NULL,
527                                 BLUETOOTH_ERROR_INTERNAL);
528
529         dbus_g_proxy_call(agent_info.proxy, "UnregisterAgent", &g_error,
530                           DBUS_TYPE_G_OBJECT_PATH, BT_OBEX_SERVER_AGENT_PATH,
531                           G_TYPE_INVALID, G_TYPE_INVALID);
532         if (g_error != NULL) {
533                 BT_ERR("Agent unregistration failed: %s", g_error->message);
534                 g_error_free(g_error);
535         }
536
537         g_object_unref(agent_info.proxy);
538         agent_info.proxy = NULL;
539
540         g_object_unref(agent_info.obex_agent);
541         agent_info.obex_agent = NULL;
542
543         return BLUETOOTH_ERROR_NONE;
544 }
545
546 gboolean __bt_check_folder_path(const char *dest_path)
547 {
548         DIR *dp;
549
550         retv_if(dest_path == NULL, TRUE);
551
552         dp = opendir(dest_path);
553
554         if (dp == NULL) {
555                 BT_ERR("The directory does not exist");
556                 return FALSE;
557         }
558
559         closedir(dp);
560
561         return TRUE;
562 }
563
564 int _bt_obex_server_allocate(char *sender, const char *dest_path, int app_pid, gboolean is_native)
565 {
566         if (__bt_check_folder_path(dest_path) == FALSE)
567                 return BLUETOOTH_ERROR_INVALID_PARAM;
568
569         if (is_native == TRUE) {
570                 retv_if(agent_info.native_server,
571                                 BLUETOOTH_ERROR_DEVICE_BUSY);
572
573                 /* Force to change the control to native */
574                 agent_info.native_server = g_malloc0(sizeof(bt_server_info_t));
575                 agent_info.native_server->dest_path = g_strdup(dest_path);
576                 agent_info.native_server->sender = g_strdup(sender);
577                 agent_info.native_server->app_pid = app_pid;
578                 agent_info.server_type = BT_NATIVE_SERVER;
579                 _bt_unregister_osp_server_in_agent(BT_OBEX_SERVER, NULL);
580         } else {
581                 retv_if(agent_info.custom_server,
582                                 BLUETOOTH_ERROR_DEVICE_BUSY);
583
584                 /* Force to change the control to custom */
585                 agent_info.custom_server = g_malloc0(sizeof(bt_server_info_t));
586                 agent_info.custom_server->dest_path = g_strdup(dest_path);
587                 agent_info.custom_server->sender = g_strdup(sender);
588                 agent_info.custom_server->app_pid = app_pid;
589                 agent_info.server_type = BT_CUSTOM_SERVER;
590                 _bt_register_osp_server_in_agent(BT_OBEX_SERVER, NULL);
591         }
592
593         return BLUETOOTH_ERROR_NONE;
594 }
595
596 int _bt_obex_server_deallocate(int app_pid, gboolean is_native)
597 {
598         if (is_native == TRUE) {
599                 retv_if(agent_info.native_server == NULL,
600                                 BLUETOOTH_ERROR_AGENT_DOES_NOT_EXIST);
601
602                 retv_if(agent_info.native_server->app_pid != app_pid,
603                                 BLUETOOTH_ERROR_ACCESS_DENIED);
604
605                 __bt_free_server_info(agent_info.native_server);
606                 agent_info.native_server = NULL;
607
608                 /* Change the control to custom */
609                 if (agent_info.custom_server) {
610                         agent_info.server_type = BT_CUSTOM_SERVER;
611                         _bt_register_osp_server_in_agent(BT_OBEX_SERVER,
612                                                         NULL);
613                 }
614         } else {
615                 retv_if(agent_info.custom_server == NULL,
616                                 BLUETOOTH_ERROR_AGENT_DOES_NOT_EXIST);
617
618                 retv_if(agent_info.custom_server->app_pid != app_pid,
619                                 BLUETOOTH_ERROR_ACCESS_DENIED);
620
621                 __bt_free_server_info(agent_info.custom_server);
622                 agent_info.custom_server = NULL;
623
624                 _bt_unregister_osp_server_in_agent(BT_OBEX_SERVER, NULL);
625
626                 /* Change the control to native */
627                 if (agent_info.native_server)
628                         agent_info.server_type = BT_NATIVE_SERVER;
629         }
630
631         return BLUETOOTH_ERROR_NONE;
632 }
633
634 int _bt_obex_server_accept_authorize(const char *filename, gboolean is_native)
635 {
636         char file_path[BT_FILE_PATH_MAX] = { 0 };
637         bt_server_info_t *server_info;
638
639         BT_CHECK_PARAMETER(filename, return);
640
641         retv_if(agent_info.auth_info == NULL, BLUETOOTH_ERROR_INTERNAL);
642
643         retv_if(agent_info.auth_info->reply_context == NULL,
644                                 BLUETOOTH_ERROR_INTERNAL);
645
646         if (is_native == TRUE)
647                 server_info = agent_info.native_server;
648         else
649                 server_info = agent_info.custom_server;
650
651         retv_if(server_info == NULL, BLUETOOTH_ERROR_INTERNAL);
652
653         if (server_info->dest_path != NULL)
654                 snprintf(file_path, sizeof(file_path), "%s/%s",
655                         server_info->dest_path, filename);
656         else
657                 snprintf(file_path, sizeof(file_path), "%s", filename);
658
659         dbus_g_method_return(agent_info.auth_info->reply_context,
660                                 file_path);
661
662         agent_info.auth_info->reply_context = NULL;
663
664         return BLUETOOTH_ERROR_NONE;
665 }
666
667 int _bt_obex_server_reject_authorize(void)
668 {
669         GError *g_error;
670
671         retv_if(agent_info.auth_info->reply_context == NULL,
672                                 BLUETOOTH_ERROR_INTERNAL);
673
674         g_error = g_error_new(__bt_obex_error_quark(),
675                         BT_OBEX_AGENT_ERROR_CANCEL,
676                         "CancelledByUser");
677
678         dbus_g_method_return_error(agent_info.auth_info->reply_context,
679                                 g_error);
680         g_error_free(g_error);
681
682         __bt_free_auth_info(agent_info.auth_info);
683         agent_info.auth_info = NULL;
684
685         return BLUETOOTH_ERROR_NONE;
686 }
687
688 int _bt_obex_server_set_destination_path(const char *dest_path,
689                                                 gboolean is_native)
690 {
691         DIR *dp = NULL;
692         bt_server_info_t *server_info;
693
694         BT_CHECK_PARAMETER(dest_path, return);
695
696         dp = opendir(dest_path);
697
698         if (dp == NULL) {
699                 BT_ERR("The directory does not exist");
700                 return BLUETOOTH_ERROR_INVALID_PARAM;
701         }
702
703         closedir(dp);
704
705         if (is_native == TRUE)
706                 server_info = agent_info.native_server;
707         else
708                 server_info = agent_info.custom_server;
709
710         retv_if(server_info == NULL,
711                         BLUETOOTH_ERROR_AGENT_DOES_NOT_EXIST);
712
713         g_free(server_info->dest_path);
714         server_info->dest_path = g_strdup(dest_path);
715
716         return BLUETOOTH_ERROR_NONE;
717 }
718
719 int _bt_obex_server_set_root(const char *root)
720 {
721         GError *g_error = NULL;
722         GValue folder = { 0 };
723         DIR *dp = NULL;
724
725         BT_CHECK_PARAMETER(root, return);
726
727         retv_if(agent_info.proxy == NULL,
728                                 BLUETOOTH_ERROR_INTERNAL);
729
730         dp = opendir(root);
731
732         if (dp == NULL) {
733                 BT_ERR("The directory does not exist");
734                 return BLUETOOTH_ERROR_INVALID_PARAM;
735         }
736
737         closedir(dp);
738
739         g_value_init(&folder, G_TYPE_STRING);
740         g_value_set_string(&folder, root);
741
742         dbus_g_proxy_call(agent_info.proxy, "SetProperty",
743                         &g_error, G_TYPE_STRING, "Root",
744                         G_TYPE_VALUE, &folder, G_TYPE_INVALID, G_TYPE_INVALID);
745
746         g_value_unset(&folder);
747
748         if (g_error) {
749                 BT_ERR("SetProperty Fail: %s", g_error->message);
750                 g_error_free(g_error);
751                 return BLUETOOTH_ERROR_INTERNAL;
752         }
753
754         return BLUETOOTH_ERROR_NONE;
755 }
756
757 int _bt_obex_server_cancel_transfer(int transfer_id)
758 {
759         bt_transfer_info_t *transfer = NULL;
760         DBusGProxy *proxy;
761
762         transfer = __bt_find_transfer_by_id(transfer_id);
763         retv_if(transfer == NULL, BLUETOOTH_ERROR_NOT_FOUND);
764
765         proxy = __bt_get_transfer_proxy(transfer->path);
766
767         retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
768
769         dbus_g_proxy_call_no_reply(proxy, "Cancel",
770                                 G_TYPE_INVALID, G_TYPE_INVALID);
771
772         g_object_unref(proxy);
773
774         return BLUETOOTH_ERROR_NONE;
775 }
776
777 int _bt_obex_server_cancel_all_transfers(void)
778 {
779         GSList *l;
780         bt_transfer_info_t *transfer;
781
782         for (l = transfers; l != NULL; l = l->next) {
783                 transfer = l->data;
784
785                 if (transfer == NULL)
786                         continue;
787
788                 _bt_obex_server_cancel_transfer(transfer->transfer_id);
789         }
790
791         return BLUETOOTH_ERROR_NONE;
792 }
793
794 int _bt_obex_server_is_activated(gboolean *activated)
795 {
796         BT_CHECK_PARAMETER(activated, return);
797
798         if (agent_info.custom_server) {
799                 *activated = TRUE;
800         } else {
801                 *activated = FALSE;
802         }
803
804         return BLUETOOTH_ERROR_NONE;
805 }
806
807 int _bt_obex_server_check_allocation(gboolean *allocation)
808 {
809         BT_CHECK_PARAMETER(allocation, return);
810
811         if (agent_info.native_server || agent_info.custom_server) {
812                 *allocation = TRUE;
813         } else {
814                 *allocation = FALSE;
815         }
816
817         return BLUETOOTH_ERROR_NONE;
818 }
819
820 int _bt_obex_server_check_termination(char *sender)
821 {
822         BT_CHECK_PARAMETER(sender, return);
823
824         if (agent_info.native_server) {
825                 if (g_strcmp0(sender, agent_info.native_server->sender) == 0) {
826                         _bt_obex_server_deallocate(agent_info.native_server->app_pid,
827                                                 TRUE);
828                 }
829         }
830
831         if (agent_info.custom_server) {
832                 if (g_strcmp0(sender, agent_info.custom_server->sender) == 0) {
833                         _bt_obex_server_deallocate(agent_info.custom_server->app_pid,
834                                                 FALSE);
835                 }
836         }
837
838         return BLUETOOTH_ERROR_NONE;
839 }
840
841 int _bt_obex_server_is_receiving(gboolean *receiving)
842 {
843         BT_CHECK_PARAMETER(receiving, return);
844
845         if (transfers == NULL || g_slist_length(transfers) == 0) {
846                 *receiving = FALSE;
847         } else {
848                 *receiving = TRUE;
849         }
850
851         return BLUETOOTH_ERROR_NONE;
852 }
853
854 gboolean __bt_obex_server_accept_timeout_cb(gpointer user_data)
855 {
856         request_info_t *req_info;
857         GArray *out_param1;
858         GArray *out_param2;
859         int result = BLUETOOTH_ERROR_TIMEOUT;
860
861         /* Already reply in _bt_obex_transfer_started */
862         retv_if(agent_info.accept_id == 0, FALSE);
863
864         req_info = _bt_get_request_info(agent_info.accept_id);
865         if (req_info == NULL || req_info->context == NULL) {
866                 BT_ERR("info is NULL");
867                 return FALSE;
868         }
869
870         agent_info.accept_id = 0;
871
872         out_param1 = g_array_new(FALSE, FALSE, sizeof(gchar));
873         out_param2 = g_array_new(FALSE, FALSE, sizeof(gchar));
874
875         g_array_append_vals(out_param2, &result, sizeof(int));
876
877         dbus_g_method_return(req_info->context, out_param1, out_param2);
878
879         g_array_free(out_param1, TRUE);
880         g_array_free(out_param2, TRUE);
881
882         _bt_delete_request_list(req_info->req_id);
883
884         return FALSE;
885 }
886
887 /* To support the BOT  */
888 int _bt_obex_server_accept_connection(int request_id)
889 {
890         if (!_bt_agent_reply_authorize(TRUE))
891                 return BLUETOOTH_ERROR_INTERNAL;
892
893         agent_info.accept_id = request_id;
894
895         g_timeout_add(BT_SERVER_ACCEPT_TIMEOUT,
896                         (GSourceFunc)__bt_obex_server_accept_timeout_cb,
897                         NULL);
898
899         return BLUETOOTH_ERROR_NONE;
900 }
901
902 /* To support the BOT  */
903 int _bt_obex_server_reject_connection(void)
904 {
905         if (!_bt_agent_reply_authorize(FALSE))
906                 return BLUETOOTH_ERROR_INTERNAL;
907
908         return BLUETOOTH_ERROR_NONE;
909 }
910