code update
[apps/home/ug-nfc-efl.git] / ug-nfc-share-efl / src / ug-nfc-share-tag.c
1 /*
2   * Copyright 2012  Samsung Electronics Co., Ltd
3   *
4   * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
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 "ug-nfc-share-tag.h"
19 #include "ug-nfc-share-popup.h"
20
21 #include <stdio.h>
22 #include <Elementary.h>
23 #include <Ecore.h>
24 #include <bundle.h>
25 #include <Ecore_X.h>
26 #include <vconf.h>
27 #include <sys/types.h>
28 #include <sys/wait.h>
29
30 /* external library header */
31 #include <mime_type.h>
32 #include <notification.h>
33
34 #define NFC_POPUP_TIMEOUT               3.0
35
36 static ug_nfc_share_tag_type ug_nfc_share_tagType;
37
38
39 int _bt_ipc_send_obex_message(char *address, const uint8_t *files, uint32_t length);
40
41 /*-----------------------------------------------------------------------------------------------*/
42
43 static void _show_status_text(void *data, char *text)
44 {
45         ugdata_t *ug_data = (ugdata_t *)data;
46
47         LOGD("BEGIN>>>>");
48
49         ret_if(ug_data == NULL);
50         ret_if(text == NULL);
51
52         notification_status_message_post(text);
53
54         ug_destroy_me(ug_data->nfc_share_ug);
55
56         LOGD("END>>>>");
57 }
58
59 ug_nfc_share_tag_type ug_nfc_share_get_tag_type(void)
60 {
61         return ug_nfc_share_tagType;
62 }
63
64 void ug_nfc_share_set_tag_type(ug_nfc_share_tag_type tag_type)
65 {
66         if (tag_type < 0 || tag_type >= UG_NFC_SHARE_TAG_MAX)
67                 return;
68
69         ug_nfc_share_tagType = tag_type;
70 }
71
72 nfc_ndef_message_h ug_nfc_share_get_current_ndef(void *data)
73 {
74         ugdata_t *ug_data = (ugdata_t *)data;
75
76         LOGD("BEGIN >>>>");
77
78         retv_if(ug_data == NULL, NULL);
79
80         LOGD("END >>>>");
81
82         return ug_data->current_ndef;
83 }
84
85 ug_nfc_share_result_e ug_nfc_share_set_current_ndef(void *data, nfc_ndef_message_h ndef_msg)
86 {
87         LOGD("BEGIN >>>>");
88
89         ugdata_t *ug_data = (ugdata_t *)data;
90         if (ug_data == NULL)
91         {
92                 LOGD("ug_data is null");
93                 return UG_NFC_SHARE_ERROR;
94         }
95
96         if (ug_data->current_ndef != NULL)
97         {
98                 if (nfc_ndef_message_destroy(ug_data->current_ndef) != NFC_ERROR_NONE)
99                 {
100                         LOGD("nfc_ndef_message_destroy failed");
101                 }
102         }
103
104         ug_data->current_ndef = ndef_msg;
105         LOGD("END >>>>");
106
107         return UG_NFC_SHARE_OK;
108
109 }
110
111 static ug_nfc_share_result_e ug_nfc_share_make_mime_type_data_from_file_path(const char *path, uint8_t *type_data, uint32_t *type_size)
112 {
113         ug_nfc_share_result_e result = UG_NFC_SHARE_ERROR;
114         char *extension = NULL;
115
116         LOGD("BEGIN >>>>");
117
118         retv_if(path == NULL, result);
119         retv_if(type_data == NULL, result);
120         retv_if(type_size == NULL, result);
121
122         LOGD("typedata = %p, typesize = %d", type_data, *type_size);
123
124         memset(type_data, 0, *type_size);
125         *type_size = 0;
126
127         extension = strrchr(path, '.');
128         LOGD("extension = %s\n", GET_SAFE_STRING(extension));
129
130         if (extension != NULL)
131         {
132                 char *mime_str = NULL;
133
134                 if (mime_type_get_mime_type(extension+1, &mime_str) == MIME_TYPE_ERROR_NONE)
135                 {
136                         LOGD("mime_str[%s]", mime_str);
137
138                         *type_size = strlen(mime_str);
139                         memcpy(type_data, mime_str, *type_size);
140                         result = UG_NFC_SHARE_OK;
141                 }
142                 else
143                 {
144                         LOGD("ERROR :: mime_type_get_mime_type failed");
145                         result = UG_NFC_SHARE_ERROR;
146                 }
147         }
148
149         LOGD("mime type : %s", GET_SAFE_STRING((char *)type_data));
150
151         LOGD("END >>>>");
152
153         return result;
154 }
155
156 ug_nfc_share_result_e ug_nfc_share_make_ndef_message_from_file(nfc_ndef_message_h *msg, const char *path)
157 {
158         int result = UG_NFC_SHARE_ERROR;
159         struct stat st;
160         uint8_t type_buffer[50] = { 0, };
161         int type_size = sizeof(type_buffer);
162         nfc_ndef_record_h record = NULL;
163         FILE *file = NULL;
164         char *file_name = NULL;
165         uint8_t *file_data = NULL;
166         long int file_len = 0;
167
168
169         LOGD("BEGIN >>>>");
170
171         retv_if(msg == NULL, result);
172         retv_if(path == NULL, result);
173         /*Cause of Svace warning */
174         /*Name : TOCTTOU_SEQUENCE
175          Mitigation :
176          1.use fstat inplace of stat
177          2.or using check-Use-Check Pattern
178          */
179         retv_if((stat(path, &st) == -1 && errno == ENOENT), result);
180
181         /* read file and make payload*/
182         file = fopen(path, "r");
183         if (file != NULL)
184         {
185                 long int read_count = 0, read_total = 0;
186
187                 fseek(file, 0, SEEK_END);
188                 file_len = ftell(file);
189                 fseek(file, 0, SEEK_SET);
190
191                 UG_NFC_SHARE_MEM_MALLOC(file_data, file_len, uint8_t);
192                 if (file_data == NULL)
193                 {
194                         LOGD("ERROR :: UG_NFC_SHARE_MEM_MALLOC failed");
195
196                         fclose(file);
197
198                         return result;
199                 }
200
201                 do
202                 {
203                         read_count = fread(file_data + read_total, 1, file_len - read_total, file);
204                         read_total += read_count;
205                 }
206                 while (read_count != 0 && read_total < file_len);
207
208                 fclose(file);
209
210                 LOGD("fread(%s) success, size %ld\n", path, file_len);
211         }
212         else
213         {
214                 LOGD("fopen(%s) error\n");
215
216                 return result;
217         }
218
219         /* get type data */
220         result = ug_nfc_share_make_mime_type_data_from_file_path(path, type_buffer, (uint32_t *)&type_size);
221         if (result != UG_NFC_SHARE_OK)
222         {
223                 LOGD("ERROR :: _make_mime_type_data_from_file_path failed [%d]", result);
224
225                 return result;
226         }
227
228         /* get file name for id */
229         file_name = strrchr(path, '/');
230         if (file_name == NULL)
231         {
232                 file_name = (char *)path;
233         }
234         else
235         {
236                 file_name++;
237         }
238
239         LOGD("file name : %s", file_name);
240
241         /* create record */
242         result = nfc_ndef_record_create(&record, NFC_RECORD_TNF_MIME_MEDIA, type_buffer, type_size, (uint8_t *)file_name, strlen(file_name), file_data, file_len);
243         if (result != NFC_ERROR_NONE)
244         {
245                 LOGD("nfc_ndef_record_create failed (%d)", result);
246
247                 return result;
248         }
249
250         /* make file NDEF message */
251         result = nfc_ndef_message_create(msg);
252         if (result != NFC_ERROR_NONE)
253         {
254                 LOGD("nfc_ndef_message_create failed [%d]\n", result);
255
256                 nfc_ndef_record_destroy(record);
257
258                 return result;
259         }
260
261         /* append record to ndef message */
262         result = nfc_ndef_message_append_record(*msg, record);
263         if (result != NFC_ERROR_NONE)
264         {
265                 LOGD("nfc_ndef_message_append_record failed (%d)", result);
266
267                 return result;
268         }
269
270         LOGD("ug_nfc_share_make_ndef_message_from_file success");
271
272         LOGD("END>>>>");
273
274         return result;
275 }
276
277 /* nfc_handover */
278 ug_nfc_share_result_e ug_nfc_share_make_ndef_message_from_multi_file(nfc_ndef_message_h *msg, const char *path[], int record_count)
279 {
280         int result = UG_NFC_SHARE_ERROR;
281         struct stat st;
282         uint8_t type_buffer[50] = { 0, };
283         int type_size = sizeof(type_buffer);
284         nfc_ndef_record_h record = NULL;
285         FILE *file = NULL;
286         char *file_name = NULL;
287         uint8_t *file_data = NULL;
288         long int file_len = 0;
289         int index;
290
291
292         LOGD("BEGIN >>>>");
293
294         retv_if(msg == NULL, result);
295         retv_if(path == NULL, result);
296         /*Cause of Svace warning */
297         /*Name : TOCTTOU_SEQUENCE
298          Mitigation :
299          1.use fstat inplace of stat
300          2.or using check-Use-Check Pattern
301          */
302
303         for (index = 0; index < record_count; index++)
304         {
305                 retv_if((stat(path[index], &st) == -1 && errno == ENOENT), result);
306
307                 /* read file and make payload*/
308                 file = fopen(path[index], "r");
309
310                 if (file != NULL)
311                 {
312                         long int read_count = 0, read_total = 0;
313
314                         fseek(file, 0, SEEK_END);
315                         file_len = ftell(file);
316                         fseek(file, 0, SEEK_SET);
317
318                         UG_NFC_SHARE_MEM_MALLOC(file_data, file_len, uint8_t);
319                         if (file_data == NULL)
320                         {
321                                 LOGD("ERROR :: UG_NFC_SHARE_MEM_MALLOC failed");
322
323                                 fclose(file);
324
325                                 return result;
326                         }
327
328                         do
329                         {
330                                 read_count = fread(file_data + read_total, 1, file_len - read_total, file);
331                                 read_total += read_count;
332                         }
333                         while (read_count != 0 && read_total < file_len);
334
335                         fclose(file);
336
337                         LOGD("fread(%s) success, size %ld\n", path[index], file_len);
338                 }
339                 else
340                 {
341                         LOGD("fopen(%s) error\n");
342
343                         return result;
344                 }
345
346                 /* get type data */
347                 result = ug_nfc_share_make_mime_type_data_from_file_path(path[index], type_buffer, (uint32_t *)&type_size);
348                 if (result != UG_NFC_SHARE_OK)
349                 {
350                         LOGD("ERROR :: _make_mime_type_data_from_file_path failed [%d]", result);
351
352                         return result;
353                 }
354
355                 /* get file name for id */
356                 file_name = strrchr(path[index], '/');
357                 if (file_name == NULL)
358                 {
359                         file_name = (char *)path[index];
360                 }
361                 else
362                 {
363                         file_name++;
364                 }
365
366                 LOGD("file name : %s", file_name);
367
368                 /* create record */
369                 result = nfc_ndef_record_create(&record, NFC_RECORD_TNF_MIME_MEDIA, type_buffer, type_size, (uint8_t *)file_name, strlen(file_name), file_data, file_len);
370                 if (result != NFC_ERROR_NONE)
371                 {
372                         LOGD("nfc_ndef_record_create failed (%d)", result);
373
374                         return result;
375                 }
376
377                 /* make file NDEF message */
378                 result = nfc_ndef_message_create(msg);
379                 if (result != NFC_ERROR_NONE)
380                 {
381                         LOGD("nfc_ndef_message_create failed [%d]\n", result);
382
383                         nfc_ndef_record_destroy(record);
384
385                         return result;
386                 }
387
388                 /* append record to ndef message */
389                 result = nfc_ndef_message_append_record(*msg, record);
390                 if (result != NFC_ERROR_NONE)
391                 {
392                         LOGD("nfc_ndef_message_append_record failed (%d)", result);
393
394                         return result;
395                 }
396
397                 LOGD("ug_nfc_share_make_ndef_message_from_file success");
398
399                 LOGD("END>>>>");
400         }
401         return result;
402 }
403
404 void _ug_nfc_share_get_bt_addr_from_string(uint8_t *addr, char *addr_string)
405 {
406         char *temp = NULL;
407
408         if (addr == NULL || addr_string == NULL)
409         {
410                 return;
411         }
412
413         LOGD("string : %s", addr_string);
414
415         UG_NFC_SHARE_MEM_STRNDUP(temp, addr_string, strlen(addr_string));
416         if (temp != NULL)
417         {
418                 char *token = NULL;
419                 long value;
420                 int count = 0;
421
422                 token = strtok(temp, ":");
423
424                 do
425                 {
426                         value = strtol(token, NULL, 16);
427
428                         addr[count++] = (uint8_t)value;
429                 }
430                 while ((token = strtok(NULL, ":")) != NULL);
431         }
432         UG_NFC_SHARE_MEM_FREE(temp);
433 }
434
435 static void _p2p_connection_handover_completed_cb(nfc_error_e result, nfc_ac_type_e carrior, void *ac_data, int ac_data_size, void *user_data)
436 {
437         LOGD("BEGIN>>>>");
438
439         ugdata_t* ug_data = (ugdata_t*)user_data;
440
441         /* To prevent write event during showing popup, unset response callback */
442         ug_nfc_unset_nfc_callback();
443
444         /* nfc deactivate */
445         if(nfc_manager_deinitialize () != NFC_ERROR_NONE)
446         {
447                 LOGD("nfc_manager_deinitialize failed");
448         }
449
450         if(result == NFC_ERROR_NONE)
451         {
452                 char *data = NULL;
453
454                 LOGD("p2p_connection_handover is completed");
455
456                 data = (char *)bundle_get_val(ug_data->bd, "request_data");
457
458                 LOGD("uri[%d] = %s", strlen(data), data);
459
460                 if (_bt_ipc_send_obex_message((char *)ac_data, (uint8_t *)data, strlen(data) + 1) == 0)
461                 {
462                         _show_status_text(ug_data, IDS_SHARED);
463                 }
464                 else
465                 {
466                         LOGD("_bt_ipc_send_obex_message failed");
467
468                         _show_status_text(ug_data, IDS_UNABLE_TO_SHARE);
469                 }
470         }
471         else
472         {
473                 LOGD("p2p_connection_handover failed");
474
475                 _show_status_text(ug_data, IDS_UNABLE_TO_SHARE);
476         }
477
478         LOGD("END>>>>");
479 }
480
481 static void _p2p_send_completed_cb(nfc_error_e result, void *user_data)
482 {
483         LOGD("BEGIN>>>>");
484
485         ugdata_t* ug_data = (ugdata_t*)user_data;
486
487         /* To prevent write event during showing popup, unset response callback */
488         ug_nfc_unset_nfc_callback();
489
490         /* nfc deactivate */
491         if(nfc_manager_deinitialize () != NFC_ERROR_NONE)
492         {
493                 LOGD("nfc_manager_deinitialize failed");
494         }
495
496         if(result == NFC_ERROR_NONE)
497         {
498                 LOGD("_p2p_send_completed_cb is completed");
499
500                 _show_status_text(ug_data, IDS_SHARED);
501         }
502         else
503         {
504                 LOGD("_p2p_send_completed_cb failed");
505
506                 _show_status_text(ug_data, IDS_UNABLE_TO_SHARE);
507         }
508
509         LOGD("END>>>>");
510 }
511
512 static void _p2p_target_discovered_cb(nfc_discovered_type_e type, nfc_p2p_target_h target, void *user_data)
513 {
514         LOGD("BEGIN>>>>");
515
516         ugdata_t* ug_data = (ugdata_t*)user_data;
517
518         if(type == NFC_DISCOVERED_TYPE_ATTACHED)
519         {
520                 int result = NFC_ERROR_NONE;
521
522                 LOGD("NFC_DISCOVERED_TYPE_ATTACHED");
523
524                 if (ug_nfc_share_get_tag_type() == UG_NFC_SHARE_TAG_HANDOVER)
525                 {
526                         LOGD("UG_NFC_SHARE_TAG_HANDOVER\n");
527
528                         /* The code below will be changed after capi is completed */
529                         if ((result = nfc_p2p_connection_handover(target, NFC_AC_TYPE_UNKNOWN, _p2p_connection_handover_completed_cb, ug_data)) != NFC_ERROR_NONE)
530                         {
531                                 LOGD("nfc_p2p_connection_handover failed [%d]", result);
532                         }
533
534                         return;
535                 }
536                 else
537                 {
538                         nfc_ndef_message_h msg = NULL;
539
540                         msg = ug_nfc_share_get_current_ndef(ug_data);
541                         if(msg == NULL)
542                         {
543                                 LOGD("nfc_ndef_message_h is NULL!!\n");
544                                 return;
545                         }
546
547                         result = nfc_p2p_send(target, msg, _p2p_send_completed_cb, ug_data);
548                         if(result != NFC_ERROR_NONE)
549                         {
550                                 LOGD("nfc_p2p_send failed[%d]\n", result);
551                                 return;
552                         }
553                 }
554         }
555         else
556         {
557                 LOGD("NFC_DISCOVERED_TYPE_DETACHED");
558         }
559
560         LOGD("END>>>>");
561 }
562
563 void ug_nfc_set_nfc_callback(void *user_data)
564 {
565         LOGD("BEGIN>>>>");
566
567         nfc_manager_set_p2p_target_discovered_cb(_p2p_target_discovered_cb, user_data);
568
569         LOGD("END>>>>");
570 }
571
572 void ug_nfc_unset_nfc_callback(void)
573 {
574         LOGD("BEGIN>>>>");
575
576         nfc_manager_unset_p2p_target_discovered_cb();
577
578         LOGD("END>>>>");
579 }
580
581 int _bt_ipc_send_obex_message(char *address, const uint8_t *files, uint32_t length)
582 {
583         int result = 0;
584         uint32_t i, count = 1;
585         E_DBus_Connection *conn = NULL;
586
587         LOGD("BEGIN>>>>");
588
589         if (address == NULL || files == NULL)
590         {
591                 LOGD("invalid param [%p] [%p]", address, files);
592                 return 0;
593         }
594
595         /* count files */
596         for (i = 0; i < length; i++)
597         {
598                 if (files[i] == '?')
599                 {
600                         count++;
601                 }
602         }
603
604         if (e_dbus_init() > 0)
605         {
606                 if ((conn = e_dbus_bus_get(DBUS_BUS_SYSTEM)) != NULL)
607                 {
608                         DBusMessage *msg = NULL;
609
610                         if (e_dbus_request_name(conn, "User.Bluetooth.UG", 0, NULL, NULL) != NULL)
611                         {
612                                 if ((msg = dbus_message_new_signal("/org/projectx/connect_device", "User.Bluetooth.UG", "Send")) != NULL)
613                                 {
614                                         int reserved = 0;
615                                         char *type = "nfc";
616                                         char *name = address;
617                                         uint8_t temp[6] = { 0, };
618                                         uint8_t *addr = temp;
619
620                                         _ug_nfc_share_get_bt_addr_from_string(temp, address);
621
622                                         LOGD("msg [%p], reserved [%d], address [%02X:%02X:%02X:%02X:%02X:%02X], count [%d], files [%s]", msg, reserved, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], count, files);
623
624                                         if (dbus_message_append_args(msg,
625                                                                                                 DBUS_TYPE_INT32, &reserved,
626                                                                                                 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &addr, 6,
627                                                                                                 DBUS_TYPE_INT32, &count,
628                                                                                                 DBUS_TYPE_STRING, &files,
629                                                                                                 DBUS_TYPE_STRING, &type,
630                                                                                                 DBUS_TYPE_STRING, &name,
631                                                                                                 DBUS_TYPE_INVALID))
632                                         {
633                                                 e_dbus_message_send(conn, msg, NULL, -1, NULL);
634
635                                                 LOGD("Send success");
636                                         }
637                                         else
638                                         {
639                                                 LOGE("Connect sending failed");
640
641                                                 result = -1;
642                                         }
643
644                                         dbus_message_unref(msg);
645                                 }
646                                 else
647                                 {
648                                         LOGE("dbus_message_new_signal failed");
649
650                                         result = -1;
651                                 }
652                         }
653                         else
654                         {
655                                 LOGE("e_dbus_request_name failed");
656
657                                 result = -1;
658                         }
659                 }
660                 else
661                 {
662                         LOGE("e_dbus_bus_get failed");
663
664                         result = -1;
665                 }
666
667                 e_dbus_shutdown();
668         }
669         else
670         {
671                 LOGE("e_dbus_init failed");
672
673                 result = -1;
674         }
675
676         LOGD("END>>>>");
677
678         return result;
679 }