tizen 2.3 release
[framework/connectivity/bluez.git] / obexd / plugins / mas.c
1 /*
2  *
3  *  OBEX Server
4  *
5  *  Copyright (C) 2010-2011  Nokia Corporation
6  *
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <string.h>
29 #include <errno.h>
30 #include <glib.h>
31 #include <fcntl.h>
32 #include <inttypes.h>
33 #ifdef __TIZEN_PATCH__
34 #include <sys/time.h>
35 #endif
36 #include <gobex/gobex.h>
37 #include <gobex/gobex-apparam.h>
38
39 #include "obexd.h"
40 #include "plugin.h"
41 #include "log.h"
42 #include "obex.h"
43 #include "service.h"
44 #include "mimetype.h"
45 #include "filesystem.h"
46 #include "manager.h"
47 #include "map_ap.h"
48
49 #include "messages.h"
50
51 #define READ_STATUS_REQ 0
52 #define DELETE_STATUS_REQ 1
53
54 #define XML_DECL "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
55
56 /* Building blocks for x-obex/folder-listing */
57 #define FL_DTD "<!DOCTYPE folder-listing SYSTEM \"obex-folder-listing.dtd\">"
58 #define FL_BODY_BEGIN "<folder-listing version=\"1.0\">"
59 #define FL_BODY_EMPTY "<folder-listing version=\"1.0\"/>"
60 #define FL_PARENT_FOLDER_ELEMENT "<parent-folder/>"
61 #define FL_FOLDER_ELEMENT "<folder name=\"%s\"/>"
62 #define FL_BODY_END "</folder-listing>"
63
64 #define ML_BODY_BEGIN "<MAP-msg-listing version=\"1.0\">"
65 #define ML_BODY_END "</MAP-msg-listing>"
66
67 struct mas_session {
68         struct mas_request *request;
69         void *backend_data;
70         gboolean finished;
71         gboolean nth_call;
72         GString *buffer;
73         GObexApparam *inparams;
74         GObexApparam *outparams;
75         gboolean ap_sent;
76 #ifdef __TIZEN_PATCH__
77         gboolean headers_sent;
78         int notification_status;
79         char *remote_addr;
80         char *response_handle;
81 #endif
82 };
83
84 static const uint8_t MAS_TARGET[TARGET_SIZE] = {
85                         0xbb, 0x58, 0x2b, 0x40, 0x42, 0x0c, 0x11, 0xdb,
86                         0xb0, 0xde, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66  };
87
88 static int get_params(struct obex_session *os, struct mas_session *mas)
89 {
90         const uint8_t *buffer;
91         ssize_t size;
92
93         size = obex_get_apparam(os, &buffer);
94         if (size < 0)
95                 size = 0;
96
97         mas->inparams = g_obex_apparam_decode(buffer, size);
98         if (mas->inparams == NULL) {
99                 DBG("Error when parsing parameters!");
100                 return -EBADR;
101         }
102
103         return 0;
104 }
105
106 static void reset_request(struct mas_session *mas)
107 {
108         if (mas->buffer) {
109                 g_string_free(mas->buffer, TRUE);
110                 mas->buffer = NULL;
111         }
112
113         if (mas->inparams) {
114                 g_obex_apparam_free(mas->inparams);
115                 mas->inparams = NULL;
116         }
117
118         if (mas->outparams) {
119                 g_obex_apparam_free(mas->outparams);
120                 mas->outparams = NULL;
121         }
122
123         mas->nth_call = FALSE;
124         mas->finished = FALSE;
125         mas->ap_sent = FALSE;
126 #ifdef __TIZEN_PATCH__
127         mas->headers_sent = FALSE;
128         g_free(mas->response_handle);
129         mas->response_handle = NULL;
130 #endif
131 }
132
133 static void mas_clean(struct mas_session *mas)
134 {
135         reset_request(mas);
136 #ifdef __TIZEN_PATCH__
137         g_free(mas->remote_addr);
138 #endif
139         g_free(mas);
140 }
141
142 static void *mas_connect(struct obex_session *os, int *err)
143 {
144         struct mas_session *mas;
145 #ifdef __TIZEN_PATCH__
146         char *address;
147 #endif
148
149         DBG("");
150
151         mas = g_new0(struct mas_session, 1);
152
153         *err = messages_connect(&mas->backend_data);
154         if (*err < 0)
155                 goto failed;
156
157         manager_register_session(os);
158
159 #ifdef __TIZEN_PATCH__
160         if (obex_getpeername(os, &address) == 0) {
161                 mas->remote_addr = address;
162                 DBG("mas->remote_addr = %s\n", mas->remote_addr);
163         }
164 #endif
165
166         return mas;
167
168 failed:
169         g_free(mas);
170
171         return NULL;
172 }
173
174 static void mas_disconnect(struct obex_session *os, void *user_data)
175 {
176         struct mas_session *mas = user_data;
177
178         DBG("");
179
180         manager_unregister_session(os);
181         messages_disconnect(mas->backend_data);
182
183         mas_clean(mas);
184 }
185
186 static int mas_get(struct obex_session *os, void *user_data)
187 {
188         struct mas_session *mas = user_data;
189         const char *type = obex_get_type(os);
190         const char *name = obex_get_name(os);
191         int ret;
192
193         DBG("GET: name %s type %s mas %p",
194                         name, type, mas);
195
196         if (type == NULL)
197                 return -EBADR;
198
199         ret = get_params(os, mas);
200         if (ret < 0)
201                 goto failed;
202
203         ret = obex_get_stream_start(os, name);
204         if (ret < 0)
205                 goto failed;
206
207         return 0;
208
209 failed:
210         reset_request(mas);
211
212         return ret;
213 }
214
215 static int mas_put(struct obex_session *os, void *user_data)
216 {
217         struct mas_session *mas = user_data;
218         const char *type = obex_get_type(os);
219         const char *name = obex_get_name(os);
220         int ret;
221
222         DBG("PUT: name %s type %s mas %p", name, type, mas);
223
224         if (type == NULL)
225                 return -EBADR;
226
227         ret = get_params(os, mas);
228         if (ret < 0)
229                 goto failed;
230
231         ret = obex_put_stream_start(os, name);
232         if (ret < 0)
233                 goto failed;
234
235         return 0;
236
237 failed:
238         reset_request(mas);
239
240         return ret;
241 }
242
243 /* FIXME: Preserve whitespaces */
244 static void g_string_append_escaped_printf(GString *string,
245                                                 const char *format, ...)
246 {
247         va_list ap;
248         char *escaped;
249
250         va_start(ap, format);
251         escaped = g_markup_vprintf_escaped(format, ap);
252         g_string_append(string, escaped);
253         g_free(escaped);
254         va_end(ap);
255 }
256
257 static const char *yesorno(gboolean a)
258 {
259         if (a)
260                 return "yes";
261
262         return "no";
263 }
264
265 #ifdef __TIZEN_PATCH__
266 static gchar *get_local_timestamp(void)
267 {
268         struct timeval tv;
269         struct tm ltime;
270
271         gettimeofday(&tv, NULL);
272
273         if (!localtime_r(&tv.tv_sec, &ltime))
274                 return NULL;
275
276         return g_strdup_printf("%04d%02d%02dT%02d%02d%02d",
277                                         ltime.tm_year + 1900, ltime.tm_mon + 1,
278                                         ltime.tm_mday, ltime.tm_hour,
279                                         ltime.tm_min, ltime.tm_sec);
280 }
281 #endif
282
283 static void get_messages_listing_cb(void *session, int err, uint16_t size,
284                                         gboolean newmsg,
285                                         const struct messages_message *entry,
286                                         void *user_data)
287 {
288         struct mas_session *mas = user_data;
289         uint16_t max = 1024;
290 #ifdef __TIZEN_PATCH__
291         gchar *msetime;
292 #endif
293
294         if (err < 0 && err != -EAGAIN) {
295                 obex_object_set_io_flags(mas, G_IO_ERR, err);
296                 return;
297         }
298
299         g_obex_apparam_get_uint16(mas->inparams, MAP_AP_MAXLISTCOUNT, &max);
300
301         if (max == 0) {
302                 if (!entry)
303                         mas->finished = TRUE;
304
305                 goto proceed;
306         }
307
308         if (!mas->nth_call) {
309                 g_string_append(mas->buffer, ML_BODY_BEGIN);
310                 mas->nth_call = TRUE;
311         }
312
313         if (!entry) {
314                 g_string_append(mas->buffer, ML_BODY_END);
315                 mas->finished = TRUE;
316
317                 goto proceed;
318         }
319
320         g_string_append(mas->buffer, "<msg");
321
322         g_string_append_escaped_printf(mas->buffer, " handle=\"%s\"",
323                                                                 entry->handle);
324
325         if (entry->mask & PMASK_SUBJECT)
326                 g_string_append_escaped_printf(mas->buffer, " subject=\"%s\"",
327                                 entry->subject);
328
329         if (entry->mask & PMASK_DATETIME)
330                 g_string_append_escaped_printf(mas->buffer, " datetime=\"%s\"",
331                                 entry->datetime);
332
333         if (entry->mask & PMASK_SENDER_NAME)
334                 g_string_append_escaped_printf(mas->buffer,
335                                                 " sender_name=\"%s\"",
336                                                 entry->sender_name);
337
338         if (entry->mask & PMASK_SENDER_ADDRESSING)
339                 g_string_append_escaped_printf(mas->buffer,
340                                                 " sender_addressing=\"%s\"",
341                                                 entry->sender_addressing);
342
343         if (entry->mask & PMASK_REPLYTO_ADDRESSING)
344                 g_string_append_escaped_printf(mas->buffer,
345                                                 " replyto_addressing=\"%s\"",
346                                                 entry->replyto_addressing);
347
348         if (entry->mask & PMASK_RECIPIENT_NAME)
349                 g_string_append_escaped_printf(mas->buffer,
350                                                 " recipient_name=\"%s\"",
351                                                 entry->recipient_name);
352
353         if (entry->mask & PMASK_RECIPIENT_ADDRESSING)
354                 g_string_append_escaped_printf(mas->buffer,
355                                                 " recipient_addressing=\"%s\"",
356                                                 entry->recipient_addressing);
357
358         if (entry->mask & PMASK_TYPE)
359                 g_string_append_escaped_printf(mas->buffer, " type=\"%s\"",
360                                 entry->type);
361
362         if (entry->mask & PMASK_RECEPTION_STATUS)
363                 g_string_append_escaped_printf(mas->buffer,
364                                                 " reception_status=\"%s\"",
365                                                 entry->reception_status);
366
367         if (entry->mask & PMASK_SIZE)
368                 g_string_append_escaped_printf(mas->buffer, " size=\"%s\"",
369                                 entry->size);
370
371         if (entry->mask & PMASK_ATTACHMENT_SIZE)
372                 g_string_append_escaped_printf(mas->buffer,
373                                                 " attachment_size=\"%s\"",
374                                                 entry->attachment_size);
375
376         if (entry->mask & PMASK_TEXT)
377                 g_string_append_escaped_printf(mas->buffer, " text=\"%s\"",
378                                 yesorno(entry->text));
379
380         if (entry->mask & PMASK_READ)
381                 g_string_append_escaped_printf(mas->buffer, " read=\"%s\"",
382                                 yesorno(entry->read));
383
384         if (entry->mask & PMASK_SENT)
385                 g_string_append_escaped_printf(mas->buffer, " sent=\"%s\"",
386                                 yesorno(entry->sent));
387
388         if (entry->mask & PMASK_PROTECTED)
389                 g_string_append_escaped_printf(mas->buffer, " protected=\"%s\"",
390                                 yesorno(entry->protect));
391
392         if (entry->mask & PMASK_PRIORITY)
393                 g_string_append_escaped_printf(mas->buffer, " priority=\"%s\"",
394                                 yesorno(entry->priority));
395
396         g_string_append(mas->buffer, "/>\n");
397
398 proceed:
399         if (!entry) {
400                 mas->outparams = g_obex_apparam_set_uint16(mas->outparams,
401                                                 MAP_AP_MESSAGESLISTINGSIZE,
402                                                 size);
403                 mas->outparams = g_obex_apparam_set_uint8(mas->outparams,
404                                                 MAP_AP_NEWMESSAGE,
405                                                 newmsg ? 1 : 0);
406 #ifdef __TIZEN_PATCH__
407                 msetime = get_local_timestamp();
408                 if (msetime) {
409                         g_obex_apparam_set_string(mas->outparams,
410                                                 MAP_AP_MSETIME, msetime);
411                         g_free(msetime);
412                 }
413 #endif
414         }
415
416         if (err != -EAGAIN)
417                 obex_object_set_io_flags(mas, G_IO_IN, 0);
418 }
419
420 #ifdef __TIZEN_PATCH__
421 static void put_message_cb(void *session, int err, guint64 handle,
422                                                         void *user_data)
423 {
424         struct mas_session *mas = user_data;
425
426         DBG("");
427
428         if (err < 0) {
429                 obex_object_set_io_flags(mas, G_IO_ERR, err);
430                 return;
431         }
432         mas->finished = FALSE;
433         mas->response_handle = g_strdup_printf("%llx", handle);
434
435         obex_object_set_io_flags(mas, G_IO_OUT, 0);
436 }
437 #endif
438
439 static void get_message_cb(void *session, int err, gboolean fmore,
440                                         const char *chunk, void *user_data)
441 {
442         struct mas_session *mas = user_data;
443
444         DBG("");
445
446         if (err < 0 && err != -EAGAIN) {
447                 obex_object_set_io_flags(mas, G_IO_ERR, err);
448                 return;
449         }
450
451         if (!chunk) {
452                 mas->finished = TRUE;
453                 goto proceed;
454         }
455
456         g_string_append(mas->buffer, chunk);
457
458 proceed:
459         if (err != -EAGAIN)
460                 obex_object_set_io_flags(mas, G_IO_IN, 0);
461 }
462
463 static void get_folder_listing_cb(void *session, int err, uint16_t size,
464                                         const char *name, void *user_data)
465 {
466         struct mas_session *mas = user_data;
467         uint16_t max = 1024;
468
469         if (err < 0 && err != -EAGAIN) {
470                 obex_object_set_io_flags(mas, G_IO_ERR, err);
471                 return;
472         }
473
474         g_obex_apparam_get_uint16(mas->inparams, MAP_AP_MAXLISTCOUNT, &max);
475
476         if (max == 0) {
477                 if (err != -EAGAIN)
478                         mas->outparams = g_obex_apparam_set_uint16(
479                                                 mas->outparams,
480                                                 MAP_AP_FOLDERLISTINGSIZE,
481                                                 size);
482
483                 if (!name)
484                         mas->finished = TRUE;
485
486                 goto proceed;
487 #ifndef __TIZEN_PATCH__
488         }
489 #else
490         } else {
491                 mas->ap_sent = TRUE;
492         }
493 #endif
494         if (!mas->nth_call) {
495                 g_string_append(mas->buffer, XML_DECL);
496                 g_string_append(mas->buffer, FL_DTD);
497                 if (!name) {
498                         g_string_append(mas->buffer, FL_BODY_EMPTY);
499                         mas->finished = TRUE;
500                         goto proceed;
501                 }
502                 g_string_append(mas->buffer, FL_BODY_BEGIN);
503                 mas->nth_call = TRUE;
504         }
505
506         if (!name) {
507                 g_string_append(mas->buffer, FL_BODY_END);
508                 mas->finished = TRUE;
509                 goto proceed;
510         }
511
512         if (g_strcmp0(name, "..") == 0)
513                 g_string_append(mas->buffer, FL_PARENT_FOLDER_ELEMENT);
514         else
515                 g_string_append_escaped_printf(mas->buffer, FL_FOLDER_ELEMENT,
516                                                                         name);
517
518 proceed:
519         if (err != -EAGAIN)
520                 obex_object_set_io_flags(mas, G_IO_IN, err);
521 }
522
523 static void set_status_cb(void *session, int err, void *user_data)
524 {
525         struct mas_session *mas = user_data;
526
527         DBG("");
528
529         mas->finished = TRUE;
530
531         if (err < 0)
532                 obex_object_set_io_flags(mas, G_IO_ERR, err);
533         else
534                 obex_object_set_io_flags(mas, G_IO_OUT, 0);
535 }
536
537 static int mas_setpath(struct obex_session *os, void *user_data)
538 {
539         const char *name;
540         const uint8_t *nonhdr;
541         struct mas_session *mas = user_data;
542
543         if (obex_get_non_header_data(os, &nonhdr) != 2) {
544                 error("Set path failed: flag and constants not found!");
545                 return -EBADR;
546         }
547
548         name = obex_get_name(os);
549
550         DBG("SETPATH: name %s nonhdr 0x%x%x", name, nonhdr[0], nonhdr[1]);
551
552         if ((nonhdr[0] & 0x02) != 0x02) {
553                 DBG("Error: requested directory creation");
554                 return -EBADR;
555         }
556
557         return messages_set_folder(mas->backend_data, name, nonhdr[0] & 0x01);
558 }
559
560 static void *folder_listing_open(const char *name, int oflag, mode_t mode,
561                                 void *driver_data, size_t *size, int *err)
562 {
563         struct mas_session *mas = driver_data;
564         /* 1024 is the default when there was no MaxListCount sent */
565         uint16_t max = 1024;
566         uint16_t offset = 0;
567
568         if (oflag != O_RDONLY) {
569                 *err = -EBADR;
570                 return NULL;
571         }
572
573         DBG("name = %s", name);
574
575         g_obex_apparam_get_uint16(mas->inparams, MAP_AP_MAXLISTCOUNT, &max);
576         g_obex_apparam_get_uint16(mas->inparams, MAP_AP_STARTOFFSET, &offset);
577
578         *err = messages_get_folder_listing(mas->backend_data, name, max,
579                                         offset, get_folder_listing_cb, mas);
580
581         mas->buffer = g_string_new("");
582
583         if (*err < 0)
584                 return NULL;
585         else
586                 return mas;
587 }
588
589 static void *msg_listing_open(const char *name, int oflag, mode_t mode,
590                                 void *driver_data, size_t *size, int *err)
591 {
592         struct mas_session *mas = driver_data;
593         struct messages_filter filter = { 0, };
594         /* 1024 is the default when there was no MaxListCount sent */
595         uint16_t max = 1024;
596         uint16_t offset = 0;
597         /* If MAP client does not specify the subject length,
598            then subject_len = 0 and subject should be sent unaltered. */
599         uint8_t subject_len = 0;
600
601         DBG("");
602
603         if (oflag != O_RDONLY) {
604                 *err = -EBADR;
605                 return NULL;
606         }
607
608         g_obex_apparam_get_uint16(mas->inparams, MAP_AP_MAXLISTCOUNT, &max);
609         g_obex_apparam_get_uint16(mas->inparams, MAP_AP_STARTOFFSET, &offset);
610         g_obex_apparam_get_uint8(mas->inparams, MAP_AP_SUBJECTLENGTH,
611                                                 &subject_len);
612
613         g_obex_apparam_get_uint32(mas->inparams, MAP_AP_PARAMETERMASK,
614                                                 &filter.parameter_mask);
615         g_obex_apparam_get_uint8(mas->inparams, MAP_AP_FILTERMESSAGETYPE,
616                                                 &filter.type);
617         filter.period_begin = g_obex_apparam_get_string(mas->inparams,
618                                                 MAP_AP_FILTERPERIODBEGIN);
619         filter.period_end = g_obex_apparam_get_string(mas->inparams,
620                                                 MAP_AP_FILTERPERIODEND);
621         g_obex_apparam_get_uint8(mas->inparams, MAP_AP_FILTERREADSTATUS,
622                                                 &filter.read_status);
623         filter.recipient = g_obex_apparam_get_string(mas->inparams,
624                                                 MAP_AP_FILTERRECIPIENT);
625         filter.originator = g_obex_apparam_get_string(mas->inparams,
626                                                 MAP_AP_FILTERORIGINATOR);
627         g_obex_apparam_get_uint8(mas->inparams, MAP_AP_FILTERPRIORITY,
628                                                 &filter.priority);
629
630         *err = messages_get_messages_listing(mas->backend_data, name, max,
631                         offset, subject_len, &filter,
632                         get_messages_listing_cb, mas);
633
634         mas->buffer = g_string_new("");
635
636         if (*err < 0)
637                 return NULL;
638         else
639                 return mas;
640 }
641
642 static void *message_open(const char *name, int oflag, mode_t mode,
643                                 void *driver_data, size_t *size, int *err)
644 {
645         struct mas_session *mas = driver_data;
646
647         DBG("");
648
649 #ifdef __TIZEN_PATCH__
650         if (oflag != O_RDONLY) {
651                 DBG("Message pushing invoked \n");
652
653                 DBG("name = %s", name);
654                 uint8_t transparent = 0;
655                 uint8_t retry = 1;
656                 uint8_t charset;
657
658                 g_obex_apparam_get_uint8(mas->inparams, MAP_AP_TRANSPARENT,
659                                                                 &transparent);
660                 DBG("transparent = %d \n", transparent);
661                 g_obex_apparam_get_uint8(mas->inparams, MAP_AP_RETRY, &retry);
662                 DBG("retry = %d \n", retry);
663
664                 if (!g_obex_apparam_get_uint8(mas->inparams, MAP_AP_CHARSET,
665                                                                 &charset)) {
666                         *err = -EBADR;
667                         return NULL;
668                 }
669                 mas->headers_sent = FALSE;
670
671                 *err = messages_push_message(mas->backend_data, name,
672                                                 transparent, retry, charset,
673                                                 put_message_cb, mas);
674         } else {
675                 uint8_t fraction_request = 0;
676                 uint8_t attachment;
677                 uint8_t charset;
678
679                 if (!g_obex_apparam_get_uint8(mas->inparams, MAP_AP_ATTACHMENT,
680                                                                 &attachment)) {
681                         *err = -EBADR;
682                         return NULL;
683                 }
684
685                 if (!g_obex_apparam_get_uint8(mas->inparams, MAP_AP_CHARSET,
686                                                                 &charset)) {
687                         *err = -EBADR;
688                         return NULL;
689                 }
690
691                 if (!g_obex_apparam_get_uint8(mas->inparams, MAP_AP_FRACTIONREQUEST,
692                                                                 &fraction_request))
693                         mas->ap_sent = TRUE;
694
695                 *err = messages_get_message(mas->backend_data, name, attachment,
696                                                 charset, fraction_request,
697                                                 get_message_cb, mas);
698         }
699 #else
700         if (oflag != O_RDONLY) {
701                 DBG("Message pushing unsupported");
702                 *err = -ENOSYS;
703
704                 return NULL;
705         }
706
707         *err = messages_get_message(mas->backend_data, name, 0,
708                         get_message_cb, mas);
709 #endif
710
711         mas->buffer = g_string_new("");
712
713         if (*err < 0)
714                 return NULL;
715         else
716                 return mas;
717 }
718
719 #ifdef __TIZEN_PATCH__
720 static ssize_t message_write(void *object, const void *buf, size_t count)
721 {
722         DBG("");
723         struct mas_session *mas = object;
724
725         if (mas->finished)
726                 return 0;
727
728         g_string_append_len(mas->buffer, buf, count);
729
730         DBG("count = %d \n", count);
731
732         if (g_strrstr(mas->buffer->str, "END:BMSG\r\n")) {
733                 DBG("BMsg received. \n");
734
735         messages_push_message_data(mas->backend_data,
736                                         mas->buffer->str, NULL);
737         }
738
739         return count;
740 }
741 #endif
742
743 static void *message_update_open(const char *name, int oflag, mode_t mode,
744                                         void *driver_data, size_t *size,
745                                         int *err)
746 {
747         struct mas_session *mas = driver_data;
748
749         DBG("");
750
751         if (oflag == O_RDONLY) {
752                 *err = -EBADR;
753                 return NULL;
754         }
755
756         *err = messages_update_inbox(mas->backend_data, set_status_cb, mas);
757         if (*err < 0)
758                 return NULL;
759         else
760                 return mas;
761 }
762
763 static void *message_set_status_open(const char *name, int oflag, mode_t mode,
764                                         void *driver_data, size_t *size,
765                                         int *err)
766
767 {
768         struct mas_session *mas = driver_data;
769         uint8_t indicator;
770         uint8_t value;
771
772         DBG("");
773
774         if (oflag == O_RDONLY) {
775                 *err = -EBADR;
776                 return NULL;
777         }
778
779         if (!g_obex_apparam_get_uint8(mas->inparams, MAP_AP_STATUSINDICATOR,
780                                                                 &indicator)) {
781                 *err = -EBADR;
782                 return NULL;
783         }
784
785         if (!g_obex_apparam_get_uint8(mas->inparams, MAP_AP_STATUSVALUE,
786                                                                 &value)) {
787                 *err = -EBADR;
788                 return NULL;
789         }
790
791         if (indicator == READ_STATUS_REQ)
792                 *err = messages_set_read(mas->backend_data, name, value,
793                                                         set_status_cb, mas);
794         else if (indicator == DELETE_STATUS_REQ)
795                 *err = messages_set_delete(mas->backend_data, name, value,
796                                                         set_status_cb, mas);
797         else
798                 *err = -EBADR;
799
800         if (*err < 0)
801                 return NULL;
802
803         return mas;
804 }
805
806 #ifdef __TIZEN_PATCH__
807 static void *notification_registration_open(const char *name, int oflag,
808                 mode_t mode, void *driver_data, size_t *size, int *err)
809 {
810         struct mas_session *mas = driver_data;
811         uint8_t status;
812
813         if (oflag == O_RDONLY) {
814                 *err = -EBADR;
815                 return NULL;
816         }
817
818         if (!g_obex_apparam_get_uint8(mas->inparams,
819                         MAP_AP_NOTIFICATIONSTATUS, &status)) {
820                 *err = -EBADR;
821                 return NULL;
822         }
823
824         DBG("status: %d", status);
825
826         mas->notification_status = status;
827         *err = 0;
828         mas->finished = TRUE;
829         return mas;
830 }
831
832 static int notification_registration_close(void *obj)
833 {
834         struct mas_session *mas = obj;
835
836         DBG("");
837
838         messages_set_notification_registration(mas->backend_data,
839                         mas->remote_addr, mas->notification_status,
840                         NULL);
841
842         reset_request(mas);
843
844         return 0;
845 }
846
847 static ssize_t put_next_header(void *object, void *buf, size_t mtu,
848                                                         uint8_t *hi)
849 {
850         struct mas_session *mas = object;
851         size_t len;
852
853         DBG("");
854         if (mas->headers_sent)
855                 return 0;
856
857         if (mas->response_handle)
858                 DBG("mas->response_handle %s\n", mas->response_handle);
859         else
860                 return 0;
861
862         *hi = G_OBEX_HDR_NAME;
863
864         len = strlen(mas->response_handle);
865
866         DBG("len %d\n", len);
867         DBG("mas->response_handle %s\n", mas->response_handle);
868
869         memcpy(buf, mas->response_handle, len);
870
871         mas->headers_sent = TRUE;
872
873         return len;
874 }
875 #endif
876
877
878 static ssize_t any_get_next_header(void *object, void *buf, size_t mtu,
879                                                                 uint8_t *hi)
880 {
881         struct mas_session *mas = object;
882
883         DBG("");
884
885         if (mas->buffer->len == 0 && !mas->finished)
886                 return -EAGAIN;
887
888         *hi = G_OBEX_HDR_APPARAM;
889
890         if (mas->ap_sent)
891                 return 0;
892
893         mas->ap_sent = TRUE;
894         return g_obex_apparam_encode(mas->outparams, buf, mtu);
895 }
896
897 static void *any_open(const char *name, int oflag, mode_t mode,
898                                 void *driver_data, size_t *size, int *err)
899 {
900         DBG("");
901
902         *err = -ENOSYS;
903
904         return NULL;
905 }
906
907 static ssize_t any_write(void *object, const void *buf, size_t count)
908 {
909         DBG("");
910
911         return count;
912 }
913
914 static ssize_t any_read(void *obj, void *buf, size_t count)
915 {
916         struct mas_session *mas = obj;
917         ssize_t len;
918
919         DBG("");
920
921         len = string_read(mas->buffer, buf, count);
922
923         if (len == 0 && !mas->finished)
924                 return -EAGAIN;
925
926         return len;
927 }
928
929 static int any_close(void *obj)
930 {
931         struct mas_session *mas = obj;
932
933         DBG("");
934
935         if (!mas->finished)
936                 messages_abort(mas->backend_data);
937
938         reset_request(mas);
939
940         return 0;
941 }
942
943 static struct obex_service_driver mas = {
944         .name = "Message Access server",
945         .service = OBEX_MAS,
946         .target = MAS_TARGET,
947         .target_size = TARGET_SIZE,
948         .connect = mas_connect,
949         .get = mas_get,
950         .put = mas_put,
951         .setpath = mas_setpath,
952         .disconnect = mas_disconnect,
953 };
954
955 static struct obex_mime_type_driver mime_map = {
956         .target = MAS_TARGET,
957         .target_size = TARGET_SIZE,
958         .mimetype = NULL,
959         .open = any_open,
960         .close = any_close,
961         .read = any_read,
962         .write = any_write,
963 };
964
965 static struct obex_mime_type_driver mime_message = {
966         .target = MAS_TARGET,
967         .target_size = TARGET_SIZE,
968         .mimetype = "x-bt/message",
969         .open = message_open,
970         .close = any_close,
971         .read = any_read,
972 #ifdef __TIZEN_PATCH__
973         .write = message_write,
974         .get_next_header = put_next_header
975 #else
976         .write = any_write,
977 #endif
978 };
979
980 static struct obex_mime_type_driver mime_folder_listing = {
981         .target = MAS_TARGET,
982         .target_size = TARGET_SIZE,
983         .mimetype = "x-obex/folder-listing",
984         .get_next_header = any_get_next_header,
985         .open = folder_listing_open,
986         .close = any_close,
987         .read = any_read,
988         .write = any_write,
989 };
990
991 static struct obex_mime_type_driver mime_msg_listing = {
992         .target = MAS_TARGET,
993         .target_size = TARGET_SIZE,
994         .mimetype = "x-bt/MAP-msg-listing",
995         .get_next_header = any_get_next_header,
996         .open = msg_listing_open,
997         .close = any_close,
998         .read = any_read,
999         .write = any_write,
1000 };
1001
1002 static struct obex_mime_type_driver mime_notification_registration = {
1003         .target = MAS_TARGET,
1004         .target_size = TARGET_SIZE,
1005         .mimetype = "x-bt/MAP-NotificationRegistration",
1006 #ifdef __TIZEN_PATCH__
1007         .open = notification_registration_open,
1008         .close = notification_registration_close,
1009 #else
1010         .open = any_open,
1011         .close = any_close,
1012 #endif
1013         .read = any_read,
1014         .write = any_write,
1015 };
1016
1017 static struct obex_mime_type_driver mime_message_status = {
1018         .target = MAS_TARGET,
1019         .target_size = TARGET_SIZE,
1020         .mimetype = "x-bt/messageStatus",
1021         .open = message_set_status_open,
1022         .close = any_close,
1023         .read = any_read,
1024         .write = any_write,
1025 };
1026
1027 static struct obex_mime_type_driver mime_message_update = {
1028         .target = MAS_TARGET,
1029         .target_size = TARGET_SIZE,
1030         .mimetype = "x-bt/MAP-messageUpdate",
1031         .open = message_update_open,
1032         .close = any_close,
1033         .read = any_read,
1034         .write = any_write,
1035 };
1036
1037 static struct obex_mime_type_driver *map_drivers[] = {
1038         &mime_map,
1039         &mime_message,
1040         &mime_folder_listing,
1041         &mime_msg_listing,
1042         &mime_notification_registration,
1043         &mime_message_status,
1044         &mime_message_update,
1045         NULL
1046 };
1047
1048 static int mas_init(void)
1049 {
1050         int err;
1051         int i;
1052
1053         err = messages_init();
1054         if (err < 0)
1055                 return err;
1056
1057         for (i = 0; map_drivers[i] != NULL; ++i) {
1058                 err = obex_mime_type_driver_register(map_drivers[i]);
1059                 if (err < 0)
1060                         goto failed;
1061         }
1062
1063         err = obex_service_driver_register(&mas);
1064         if (err < 0)
1065                 goto failed;
1066
1067         return 0;
1068
1069 failed:
1070         for (--i; i >= 0; --i)
1071                 obex_mime_type_driver_unregister(map_drivers[i]);
1072
1073         messages_exit();
1074
1075         return err;
1076 }
1077
1078 static void mas_exit(void)
1079 {
1080         int i;
1081
1082         obex_service_driver_unregister(&mas);
1083
1084         for (i = 0; map_drivers[i] != NULL; ++i)
1085                 obex_mime_type_driver_unregister(map_drivers[i]);
1086
1087         messages_exit();
1088 }
1089
1090 OBEX_PLUGIN_DEFINE(mas, mas_init, mas_exit)