upload tizen1.0 source
[profile/ivi/obexd.git] / 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 <errno.h>
29 #include <glib.h>
30 #include <fcntl.h>
31 #include <inttypes.h>
32
33 #include "obexd.h"
34 #include "plugin.h"
35 #include "log.h"
36 #include "obex.h"
37 #include "service.h"
38 #include "mimetype.h"
39 #include "filesystem.h"
40 #include "manager.h"
41
42 #include "messages.h"
43 #ifdef TIZEN_PATCH
44 #include "map_ap.h"
45 #include "bmessage-parser.h"
46 #endif
47
48 /* Channel number according to bluez doc/assigned-numbers.txt */
49 #define MAS_CHANNEL     16
50
51 #define MAS_RECORD "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>         \
52 <record>                                                                \
53   <attribute id=\"0x0001\">                                             \
54     <sequence>                                                          \
55       <uuid value=\"0x1132\"/>                                          \
56     </sequence>                                                         \
57   </attribute>                                                          \
58                                                                         \
59   <attribute id=\"0x0004\">                                             \
60     <sequence>                                                          \
61       <sequence>                                                        \
62         <uuid value=\"0x0100\"/>                                        \
63       </sequence>                                                       \
64       <sequence>                                                        \
65         <uuid value=\"0x0003\"/>                                        \
66         <uint8 value=\"%u\" name=\"channel\"/>                          \
67       </sequence>                                                       \
68       <sequence>                                                        \
69         <uuid value=\"0x0008\"/>                                        \
70       </sequence>                                                       \
71     </sequence>                                                         \
72   </attribute>                                                          \
73                                                                         \
74   <attribute id=\"0x0009\">                                             \
75     <sequence>                                                          \
76       <sequence>                                                        \
77         <uuid value=\"0x1134\"/>                                        \
78         <uint16 value=\"0x0100\" name=\"version\"/>                     \
79       </sequence>                                                       \
80     </sequence>                                                         \
81   </attribute>                                                          \
82                                                                         \
83   <attribute id=\"0x0100\">                                             \
84     <text value=\"%s\" name=\"name\"/>                                  \
85   </attribute>                                                          \
86                                                                         \
87   <attribute id=\"0x0315\">                                             \
88     <uint8 value=\"0x00\"/>                                             \
89   </attribute>                                                          \
90                                                                         \
91   <attribute id=\"0x0316\">                                             \
92     <uint8 value=\"0x0F\"/>                                             \
93   </attribute>                                                          \
94 </record>"
95
96 #define XML_DECL "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
97
98 /* Building blocks for x-obex/folder-listing */
99 #define FL_DTD "<!DOCTYPE folder-listing SYSTEM \"obex-folder-listing.dtd\">"
100 #define FL_BODY_BEGIN "<folder-listing version=\"1.0\">"
101 #define FL_BODY_EMPTY "<folder-listing version=\"1.0\"/>"
102 #define FL_PARENT_FOLDER_ELEMENT "<parent-folder/>"
103 #define FL_FOLDER_ELEMENT "<folder name=\"%s\"/>"
104 #define FL_BODY_END "</folder-listing>"
105
106 #define ML_BODY_BEGIN "<MAP-msg-listing version=\"1.0\">"
107 #define ML_BODY_END "</MAP-msg-listing>"
108
109 struct mas_session {
110         struct mas_request *request;
111         void *backend_data;
112         gboolean finished;
113         gboolean nth_call;
114         GString *buffer;
115 #ifdef TIZEN_PATCH
116         map_ap_t *ap;
117 #endif
118 };
119
120 static const uint8_t MAS_TARGET[TARGET_SIZE] = {
121                         0xbb, 0x58, 0x2b, 0x40, 0x42, 0x0c, 0x11, 0xdb,
122                         0xb0, 0xde, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66  };
123
124 #ifdef TIZEN_PATCH
125 static void bmessage_parser(struct mas_session *mas,
126                            struct bmessage_property *bmessage)
127 {
128         /* STRING PARSER : Under implementation */
129         DBG("%s", mas->buffer->str);
130 }
131 #endif
132
133 static void reset_request(struct mas_session *mas)
134 {
135         if (mas->buffer) {
136                 g_string_free(mas->buffer, TRUE);
137                 mas->buffer = NULL;
138         }
139 #ifdef TIZEN_PATCH
140         map_ap_free(mas->ap);
141         mas->ap = NULL;
142 #endif
143         mas->nth_call = FALSE;
144         mas->finished = FALSE;
145 }
146
147 static void mas_clean(struct mas_session *mas)
148 {
149         reset_request(mas);
150         g_free(mas);
151 }
152
153 static void *mas_connect(struct obex_session *os, int *err)
154 {
155         struct mas_session *mas;
156
157         DBG("");
158
159         mas = g_new0(struct mas_session, 1);
160
161         *err = messages_connect(&mas->backend_data);
162         if (*err < 0)
163                 goto failed;
164
165         manager_register_session(os);
166
167         return mas;
168
169 failed:
170         g_free(mas);
171
172         return NULL;
173 }
174
175 static void mas_disconnect(struct obex_session *os, void *user_data)
176 {
177         struct mas_session *mas = user_data;
178
179         DBG("");
180
181         manager_unregister_session(os);
182         messages_disconnect(mas->backend_data);
183
184         mas_clean(mas);
185 }
186
187 static int mas_get(struct obex_session *os, void *user_data)
188 {
189         struct mas_session *mas = user_data;
190         const char *type = obex_get_type(os);
191         const char *name = obex_get_name(os);
192         int ret;
193 #ifdef TIZEN_PATCH
194         const uint8_t *buffer = NULL;
195         ssize_t rsize = 0;
196 #endif
197
198         DBG("GET: name %s type %s mas %p",
199                         name, type, mas);
200
201         if (type == NULL)
202                 return -EBADR;
203
204 #ifdef TIZEN_PATCH
205         rsize = obex_get_apparam(os, &buffer);
206
207         if (rsize < 0) {
208                 if (g_ascii_strcasecmp(type, "x-bt/message") == 0) {
209                         ret = -EBADR;
210                         goto failed;
211                 }
212         } else {
213                 mas->ap = map_ap_decode(buffer, rsize);
214                 if (mas->ap == NULL) {
215                         ret = -EBADR;
216                         goto failed;
217                 }
218         }
219 #endif
220         ret = obex_get_stream_start(os, name);
221         if (ret < 0)
222                 goto failed;
223
224         return 0;
225
226 failed:
227         reset_request(mas);
228
229         return ret;
230 }
231
232 static int mas_put(struct obex_session *os, void *user_data)
233 {
234         struct mas_session *mas = user_data;
235         const char *type = obex_get_type(os);
236         const char *name = obex_get_name(os);
237         int ret;
238 #ifdef TIZEN_PATCH
239         const uint8_t *buffer = NULL;
240         ssize_t rsize = 0;
241 #endif
242
243         DBG("PUT: name %s type %s mas %p", name, type, mas);
244
245         if (type == NULL)
246                 return -EBADR;
247
248 #ifdef TIZEN_PATCH
249         rsize = obex_get_apparam(os, &buffer);
250         if (rsize < 0) {
251                 if (g_ascii_strcasecmp(type, "x-bt/messageStatus") == 0 ||
252                         g_ascii_strcasecmp(type, "x-bt/message") == 0) {
253                         ret = -EBADR;
254                         goto failed;
255                 }
256         } else {
257                 mas->ap = map_ap_decode(buffer, rsize);
258                 if (mas->ap == NULL) {
259                         ret = -EBADR;
260                         goto failed;
261                 }
262         }
263 #endif
264         ret = obex_put_stream_start(os, name);
265         if (ret < 0)
266                 goto failed;
267
268         return 0;
269
270 failed:
271         reset_request(mas);
272
273         return ret;
274 }
275
276 /* FIXME: Preserve whitespaces */
277 static void g_string_append_escaped_printf(GString *string,
278                                                 const gchar *format, ...)
279 {
280         va_list ap;
281         char *escaped;
282
283         va_start(ap, format);
284         escaped = g_markup_vprintf_escaped(format, ap);
285         g_string_append(string, escaped);
286         g_free(escaped);
287         va_end(ap);
288 }
289
290 static const char *yesorno(gboolean a)
291 {
292         if (a)
293                 return "yes";
294
295         return "no";
296 }
297
298 static void get_messages_listing_cb(void *session, int err, uint16_t size,
299                                         gboolean newmsg,
300                                         const struct messages_message *entry,
301                                         void *user_data)
302 {
303         struct mas_session *mas = user_data;
304
305         if (err < 0 && err != -EAGAIN) {
306                 obex_object_set_io_flags(mas, G_IO_ERR, err);
307                 return;
308         }
309
310         if (!mas->nth_call) {
311                 g_string_append(mas->buffer, ML_BODY_BEGIN);
312                 mas->nth_call = TRUE;
313         }
314
315         if (!entry) {
316                 g_string_append(mas->buffer, ML_BODY_END);
317                 mas->finished = TRUE;
318
319                 goto proceed;
320         }
321
322         g_string_append(mas->buffer, "<msg");
323
324         g_string_append_escaped_printf(mas->buffer, " handle=\"%s\"",
325                                                                 entry->handle);
326
327         if (entry->mask & PMASK_SUBJECT)
328                 g_string_append_escaped_printf(mas->buffer, " subject=\"%s\"",
329                                 entry->subject);
330
331         if (entry->mask & PMASK_DATETIME)
332                 g_string_append_escaped_printf(mas->buffer, " datetime=\"%s\"",
333                                 entry->datetime);
334
335         if (entry->mask & PMASK_SENDER_NAME)
336                 g_string_append_escaped_printf(mas->buffer,
337                                                 " sender_name=\"%s\"",
338                                                 entry->sender_name);
339
340         if (entry->mask & PMASK_SENDER_ADDRESSING)
341                 g_string_append_escaped_printf(mas->buffer,
342                                                 " sender_addressing=\"%s\"",
343                                                 entry->sender_addressing);
344
345         if (entry->mask & PMASK_REPLYTO_ADDRESSING)
346                 g_string_append_escaped_printf(mas->buffer,
347                                                 " replyto_addressing=\"%s\"",
348                                                 entry->replyto_addressing);
349
350         if (entry->mask & PMASK_RECIPIENT_NAME)
351                 g_string_append_escaped_printf(mas->buffer,
352                                                 " recipient_name=\"%s\"",
353                                                 entry->recipient_name);
354
355         if (entry->mask & PMASK_RECIPIENT_ADDRESSING)
356                 g_string_append_escaped_printf(mas->buffer,
357                                                 " recipient_addressing=\"%s\"",
358                                                 entry->recipient_addressing);
359
360         if (entry->mask & PMASK_TYPE)
361                 g_string_append_escaped_printf(mas->buffer, " type=\"%s\"",
362                                 entry->type);
363
364         if (entry->mask & PMASK_RECEPTION_STATUS)
365                 g_string_append_escaped_printf(mas->buffer,
366                                                 " reception_status=\"%s\"",
367                                                 entry->reception_status);
368
369         if (entry->mask & PMASK_SIZE)
370                 g_string_append_escaped_printf(mas->buffer, " size=\"%s\"",
371                                 entry->size);
372
373         if (entry->mask & PMASK_ATTACHMENT_SIZE)
374                 g_string_append_escaped_printf(mas->buffer,
375                                                 " attachment_size=\"%s\"",
376                                                 entry->attachment_size);
377
378         if (entry->mask & PMASK_TEXT)
379                 g_string_append_escaped_printf(mas->buffer, " text=\"%s\"",
380                                 yesorno(entry->text));
381
382         if (entry->mask & PMASK_READ)
383                 g_string_append_escaped_printf(mas->buffer, " read=\"%s\"",
384                                 yesorno(entry->read));
385
386         if (entry->mask & PMASK_SENT)
387                 g_string_append_escaped_printf(mas->buffer, " sent=\"%s\"",
388                                 yesorno(entry->sent));
389
390         if (entry->mask & PMASK_PROTECTED)
391                 g_string_append_escaped_printf(mas->buffer, " protected=\"%s\"",
392                                 yesorno(entry->protect));
393
394         if (entry->mask & PMASK_PRIORITY)
395                 g_string_append_escaped_printf(mas->buffer, " priority=\"%s\"",
396                                 yesorno(entry->priority));
397
398         g_string_append(mas->buffer, "/>\n");
399
400 proceed:
401         if (err != -EAGAIN)
402                 obex_object_set_io_flags(mas, G_IO_IN, 0);
403 }
404
405 static void get_message_cb(void *session, int err, gboolean fmore,
406                                         const char *chunk, void *user_data)
407 {
408         struct mas_session *mas = user_data;
409
410         DBG("");
411
412         if (err < 0 && err != -EAGAIN) {
413                 obex_object_set_io_flags(mas, G_IO_ERR, err);
414                 return;
415         }
416
417         if (!chunk) {
418                 mas->finished = TRUE;
419                 goto proceed;
420         }
421
422         g_string_append(mas->buffer, chunk);
423
424 proceed:
425         if (err != -EAGAIN)
426                 obex_object_set_io_flags(mas, G_IO_IN, 0);
427 }
428
429 static void get_folder_listing_cb(void *session, int err, uint16_t size,
430                                         const char *name, void *user_data)
431 {
432         struct mas_session *mas = user_data;
433
434         if (err < 0 && err != -EAGAIN) {
435                 obex_object_set_io_flags(mas, G_IO_ERR, err);
436                 return;
437         }
438
439         if (!mas->nth_call) {
440                 g_string_append(mas->buffer, XML_DECL);
441                 g_string_append(mas->buffer, FL_DTD);
442                 if (!name) {
443                         g_string_append(mas->buffer, FL_BODY_EMPTY);
444                         mas->finished = TRUE;
445                         goto proceed;
446                 }
447                 g_string_append(mas->buffer, FL_BODY_BEGIN);
448                 mas->nth_call = TRUE;
449         }
450
451         if (!name) {
452                 g_string_append(mas->buffer, FL_BODY_END);
453                 mas->finished = TRUE;
454                 goto proceed;
455         }
456
457         if (g_strcmp0(name, "..") == 0)
458                 g_string_append(mas->buffer, FL_PARENT_FOLDER_ELEMENT);
459         else
460                 g_string_append_escaped_printf(mas->buffer, FL_FOLDER_ELEMENT,
461                                                                         name);
462
463 proceed:
464         if (err != -EAGAIN)
465                 obex_object_set_io_flags(mas, G_IO_IN, err);
466 }
467
468 static void update_inbox_cb(void *session, int err, void *user_data)
469 {
470         struct mas_session *mas = user_data;
471
472         DBG("");
473
474         mas->finished = TRUE;
475
476         if (err < 0)
477                 obex_object_set_io_flags(mas, G_IO_ERR, err);
478         else
479                 obex_object_set_io_flags(mas, G_IO_OUT, 0);
480 }
481
482 #ifdef TIZEN_PATCH
483 static void message_status_cb(void *session, int err, void *user_data)
484 {
485         struct mas_session *mas = user_data;
486
487         DBG("");
488
489         mas->finished = TRUE;
490
491         if (err < 0)
492                 obex_object_set_io_flags(mas, G_IO_ERR, err);
493         else
494                 obex_object_set_io_flags(mas, G_IO_OUT, 0);
495 }
496
497 static void folder_size_result_cb(void *session, int err, uint16_t size,
498                                         const char *name, void *user_data)
499 {
500         struct mas_session *mas = user_data;
501
502         map_ap_set_u16(mas->ap, MAP_AP_FOLDERLISTINGSIZE,
503                                         GUINT16_FROM_BE(size));
504
505         if (err < 0)
506                 obex_object_set_io_flags(mas, G_IO_ERR, err);
507         else
508                 obex_object_set_io_flags(mas, G_IO_OUT, 0);
509 }
510 #endif
511
512 static int mas_setpath(struct obex_session *os, void *user_data)
513 {
514         const char *name;
515         const uint8_t *nonhdr;
516         struct mas_session *mas = user_data;
517
518         if (obex_get_non_header_data(os, &nonhdr) != 2) {
519                 error("Set path failed: flag and constants not found!");
520                 return -EBADR;
521         }
522
523         name = obex_get_name(os);
524
525         DBG("SETPATH: name %s nonhdr 0x%x%x", name, nonhdr[0], nonhdr[1]);
526
527         if ((nonhdr[0] & 0x02) != 0x02) {
528                 DBG("Error: requested directory creation");
529                 return -EBADR;
530         }
531
532         return messages_set_folder(mas->backend_data, name, nonhdr[0] & 0x01);
533 }
534
535 static void *folder_listing_open(const char *name, int oflag, mode_t mode,
536                                 void *driver_data, size_t *size, int *err)
537 {
538         struct mas_session *mas = driver_data;
539 #ifdef TIZEN_PATCH
540         messages_folder_listing_cb cb;
541         uint16_t maxlistcount = 1024;
542         uint16_t offset = 0;
543 #endif
544
545         if (oflag != O_RDONLY) {
546                 *err = -EBADR;
547                 return NULL;
548         }
549
550         DBG("name = %s", name);
551
552 #ifdef TIZEN_PATCH
553         if (mas->ap != NULL) {
554                 map_ap_get_u16(mas->ap, MAP_AP_MAXLISTCOUNT, &maxlistcount);
555                 map_ap_get_u16(mas->ap, MAP_AP_STARTOFFSET, &offset);
556         }
557
558         DBG("Maxlistcount = %d \n offset = %d\n", maxlistcount, offset);
559
560         if (maxlistcount == 0)
561                 cb = folder_size_result_cb;
562         else
563                 cb = get_folder_listing_cb;
564
565         *err = messages_get_folder_listing(mas->backend_data, name,
566                                                 maxlistcount, offset, cb, mas);
567 #else
568         /* 1024 is the default when there was no MaxListCount sent */
569         *err = messages_get_folder_listing(mas->backend_data, name, 1024, 0,
570                         get_folder_listing_cb, mas);
571 #endif
572
573         mas->buffer = g_string_new("");
574
575         if (*err < 0)
576                 return NULL;
577         else
578                 return mas;
579 }
580
581 static void *msg_listing_open(const char *name, int oflag, mode_t mode,
582                                 void *driver_data, size_t *size, int *err)
583 {
584         struct mas_session *mas = driver_data;
585         struct messages_filter filter = { 0, };
586
587         DBG("");
588
589         if (oflag != O_RDONLY) {
590                 *err = -EBADR;
591                 return NULL;
592         }
593
594         *err = messages_get_messages_listing(mas->backend_data, name, 0xffff, 0,
595                         &filter,
596                         get_messages_listing_cb, mas);
597
598         mas->buffer = g_string_new("");
599
600         if (*err < 0)
601                 return NULL;
602         else
603                 return mas;
604 }
605
606 #ifdef TIZEN_PATCH
607 static void message_get(struct mas_session *mas, const char *name, int *err)
608 {
609         DBG("");
610
611         /* TODO: check for Mandatory application parameter
612         * Attachment and Charset and optional parameter fraction request */
613         *err = messages_get_message(mas->backend_data, name, 0,
614                         get_message_cb, mas);
615         mas->buffer = g_string_new("");
616 }
617
618 static void message_put(struct mas_session *mas, const char *name, int *err)
619 {
620         DBG("");
621
622         /* TODO: check for Mandatory application parameter
623         * Charset and optional parameter transparent and retry */
624         mas->buffer = g_string_new("");
625 }
626 #endif
627
628 static void *message_open(const char *name, int oflag, mode_t mode,
629                                 void *driver_data, size_t *size, int *err)
630 {
631         struct mas_session *mas = driver_data;
632
633         DBG("");
634
635 #ifdef TIZEN_PATCH
636         if (oflag == O_RDONLY)
637                 message_get(mas, name, err);
638         else
639                 message_put(mas, name, err);
640 #else
641         if (oflag != O_RDONLY) {
642                 DBG("Message pushing unsupported");
643                 *err = -EINVAL;
644
645                 return NULL;
646         }
647
648         *err = messages_get_message(mas->backend_data, name, 0,
649                         get_message_cb, mas);
650
651         mas->buffer = g_string_new("");
652 #endif
653         if (*err < 0)
654                 return NULL;
655         else
656                 return mas;
657 }
658
659 static void *message_update_open(const char *name, int oflag, mode_t mode,
660                                         void *driver_data, size_t *size,
661                                         int *err)
662 {
663         struct mas_session *mas = driver_data;
664
665         DBG("");
666
667         if (!(oflag & O_WRONLY)) {
668                 *err = -EBADR;
669                 return NULL;
670         }
671
672         *err = messages_update_inbox(mas->backend_data, update_inbox_cb, mas);
673         if (*err < 0)
674                 return NULL;
675         else
676                 return mas;
677 }
678
679 #ifdef TIZEN_PATCH
680 static void *message_status_open(const char *name, int oflag, mode_t mode,
681                                         void *driver_data, size_t *size,
682                                         int *err)
683
684 {
685         struct mas_session *mas = driver_data;
686         uint8_t indicator;
687         uint8_t value;
688
689          if (!(oflag & O_WRONLY)) {
690                 *err = -EBADR;
691                 return NULL;
692          }
693
694         map_ap_get_u8(mas->ap, MAP_AP_STATUSINDICATOR, &indicator);
695         map_ap_get_u8(mas->ap, MAP_AP_STATUSVALUE, &value);
696
697         DBG("Indicator = %d \n value = %d\n", indicator, value);
698
699         *err = messages_set_message_status(mas->backend_data, name, indicator,
700                                                 value, message_status_cb, mas);
701
702         if (*err < 0)
703                 return NULL;
704         else
705                 return mas;
706 }
707
708 static ssize_t message_write(void *object, const void *buf, size_t count)
709 {
710         struct mas_session *mas = object;
711         GString *string;
712
713         DBG("");
714
715         string = g_string_append_len(mas->buffer, buf, count);
716
717         return string->len;
718 }
719
720 static int message_close(void *obj)
721 {
722         struct mas_session *mas = obj;
723         struct bmessage_property bmessage = { 0, };
724
725         DBG("");
726
727         /* Bmessage body parsing */
728         bmessage_parser(mas, &bmessage);
729
730         if (!mas->finished)
731                 messages_abort(mas->backend_data);
732
733         reset_request(mas);
734
735         return 0;
736 }
737 #endif
738
739 static void *any_open(const char *name, int oflag, mode_t mode,
740                                 void *driver_data, size_t *size, int *err)
741 {
742         DBG("");
743
744         *err = -EINVAL;
745
746         return NULL;
747 }
748
749 static ssize_t any_write(void *object, const void *buf, size_t count)
750 {
751         DBG("");
752
753         return count;
754 }
755
756 static ssize_t any_read(void *obj, void *buf, size_t count)
757 {
758         struct mas_session *mas = obj;
759         ssize_t len;
760
761         DBG("");
762
763         len = string_read(mas->buffer, buf, count);
764
765         if (len == 0 && !mas->finished)
766                 return -EAGAIN;
767
768         return len;
769 }
770
771 static int any_close(void *obj)
772 {
773         struct mas_session *mas = obj;
774
775         DBG("");
776
777         if (!mas->finished)
778                 messages_abort(mas->backend_data);
779
780         reset_request(mas);
781
782         return 0;
783 }
784
785 static struct obex_service_driver mas = {
786         .name = "Message Access server",
787         .service = OBEX_MAS,
788         .channel = MAS_CHANNEL,
789         .secure = TRUE,
790         .record = MAS_RECORD,
791         .target = MAS_TARGET,
792         .target_size = TARGET_SIZE,
793         .connect = mas_connect,
794         .get = mas_get,
795         .put = mas_put,
796         .setpath = mas_setpath,
797         .disconnect = mas_disconnect,
798 };
799
800 static struct obex_mime_type_driver mime_map = {
801         .target = MAS_TARGET,
802         .target_size = TARGET_SIZE,
803         .mimetype = NULL,
804         .open = any_open,
805         .close = any_close,
806         .read = any_read,
807         .write = any_write,
808 };
809
810 static struct obex_mime_type_driver mime_message = {
811         .target = MAS_TARGET,
812         .target_size = TARGET_SIZE,
813         .mimetype = "x-bt/message",
814         .open = message_open,
815 #ifdef TIZEN_PATCH
816         .close = message_close,
817 #else
818         .close = any_close,
819 #endif
820         .read = any_read,
821 #ifdef TIZEN_PATCH
822         .write = message_write,
823 #else
824         .write = any_write,
825 #endif
826 };
827
828 static struct obex_mime_type_driver mime_folder_listing = {
829         .target = MAS_TARGET,
830         .target_size = TARGET_SIZE,
831         .mimetype = "x-obex/folder-listing",
832         .open = folder_listing_open,
833         .close = any_close,
834         .read = any_read,
835         .write = any_write,
836 };
837
838 static struct obex_mime_type_driver mime_msg_listing = {
839         .target = MAS_TARGET,
840         .target_size = TARGET_SIZE,
841         .mimetype = "x-bt/MAP-msg-listing",
842         .open = msg_listing_open,
843         .close = any_close,
844         .read = any_read,
845         .write = any_write,
846 };
847
848 static struct obex_mime_type_driver mime_notification_registration = {
849         .target = MAS_TARGET,
850         .target_size = TARGET_SIZE,
851         .mimetype = "x-bt/MAP-NotificationRegistration",
852         .open = any_open,
853         .close = any_close,
854         .read = any_read,
855         .write = any_write,
856 };
857
858 static struct obex_mime_type_driver mime_message_status = {
859         .target = MAS_TARGET,
860         .target_size = TARGET_SIZE,
861         .mimetype = "x-bt/messageStatus",
862 #ifdef TIZEN_PATCH
863         .open = message_status_open,
864 #else
865         .open = any_open,
866 #endif
867         .close = any_close,
868         .read = any_read,
869         .write = any_write,
870 };
871
872 static struct obex_mime_type_driver mime_message_update = {
873         .target = MAS_TARGET,
874         .target_size = TARGET_SIZE,
875         .mimetype = "x-bt/MAP-messageUpdate",
876         .open = message_update_open,
877         .close = any_close,
878         .read = any_read,
879         .write = any_write,
880 };
881
882 static struct obex_mime_type_driver *map_drivers[] = {
883         &mime_map,
884         &mime_message,
885         &mime_folder_listing,
886         &mime_msg_listing,
887         &mime_notification_registration,
888         &mime_message_status,
889         &mime_message_update,
890         NULL
891 };
892
893 static int mas_init(void)
894 {
895         int err;
896         int i;
897
898         err = messages_init();
899         if (err < 0)
900                 return err;
901
902         for (i = 0; map_drivers[i] != NULL; ++i) {
903                 err = obex_mime_type_driver_register(map_drivers[i]);
904                 if (err < 0)
905                         goto failed;
906         }
907
908         err = obex_service_driver_register(&mas);
909         if (err < 0)
910                 goto failed;
911
912         return 0;
913
914 failed:
915         for (--i; i >= 0; --i)
916                 obex_mime_type_driver_unregister(map_drivers[i]);
917
918         messages_exit();
919
920         return err;
921 }
922
923 static void mas_exit(void)
924 {
925         int i;
926
927         obex_service_driver_unregister(&mas);
928
929         for (i = 0; map_drivers[i] != NULL; ++i)
930                 obex_mime_type_driver_unregister(map_drivers[i]);
931
932         messages_exit();
933 }
934
935 OBEX_PLUGIN_DEFINE(mas, mas_init, mas_exit)