mas.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. *
  4. * OBEX Server
  5. *
  6. * Copyright (C) 2010-2011 Nokia Corporation
  7. *
  8. *
  9. */
  10. #ifdef HAVE_CONFIG_H
  11. #include <config.h>
  12. #endif
  13. #define _GNU_SOURCE
  14. #include <string.h>
  15. #include <errno.h>
  16. #include <glib.h>
  17. #include <fcntl.h>
  18. #include <inttypes.h>
  19. #include <sys/time.h>
  20. #include "gobex/gobex.h"
  21. #include "gobex/gobex-apparam.h"
  22. #include "obexd/src/obexd.h"
  23. #include "obexd/src/plugin.h"
  24. #include "obexd/src/log.h"
  25. #include "obexd/src/obex.h"
  26. #include "obexd/src/service.h"
  27. #include "obexd/src/mimetype.h"
  28. #include "obexd/src/manager.h"
  29. #include "obexd/src/map_ap.h"
  30. #include "filesystem.h"
  31. #include "messages.h"
  32. #define READ_STATUS_REQ 0
  33. #define DELETE_STATUS_REQ 1
  34. #define XML_DECL "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
  35. /* Building blocks for x-obex/folder-listing */
  36. #define FL_DTD "<!DOCTYPE folder-listing SYSTEM \"obex-folder-listing.dtd\">"
  37. #define FL_BODY_BEGIN "<folder-listing version=\"1.0\">"
  38. #define FL_BODY_EMPTY "<folder-listing version=\"1.0\"/>"
  39. #define FL_PARENT_FOLDER_ELEMENT "<parent-folder/>"
  40. #define FL_FOLDER_ELEMENT "<folder name=\"%s\"/>"
  41. #define FL_BODY_END "</folder-listing>"
  42. #define ML_BODY_BEGIN "<MAP-msg-listing version=\"1.0\">"
  43. #define ML_BODY_END "</MAP-msg-listing>"
  44. struct mas_session {
  45. struct mas_request *request;
  46. void *backend_data;
  47. gboolean finished;
  48. gboolean nth_call;
  49. GString *buffer;
  50. GObexApparam *inparams;
  51. GObexApparam *outparams;
  52. gboolean ap_sent;
  53. uint8_t notification_status;
  54. };
  55. static const uint8_t MAS_TARGET[TARGET_SIZE] = {
  56. 0xbb, 0x58, 0x2b, 0x40, 0x42, 0x0c, 0x11, 0xdb,
  57. 0xb0, 0xde, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66 };
  58. static int get_params(struct obex_session *os, struct mas_session *mas)
  59. {
  60. const uint8_t *buffer;
  61. ssize_t size;
  62. size = obex_get_apparam(os, &buffer);
  63. if (size <= 0)
  64. return 0;
  65. mas->inparams = g_obex_apparam_decode(buffer, size);
  66. if (mas->inparams == NULL) {
  67. DBG("Error when parsing parameters!");
  68. return -EBADR;
  69. }
  70. return 0;
  71. }
  72. static void reset_request(struct mas_session *mas)
  73. {
  74. if (mas->buffer) {
  75. g_string_free(mas->buffer, TRUE);
  76. mas->buffer = NULL;
  77. }
  78. if (mas->inparams) {
  79. g_obex_apparam_free(mas->inparams);
  80. mas->inparams = NULL;
  81. }
  82. if (mas->outparams) {
  83. g_obex_apparam_free(mas->outparams);
  84. mas->outparams = NULL;
  85. }
  86. mas->nth_call = FALSE;
  87. mas->finished = FALSE;
  88. mas->ap_sent = FALSE;
  89. }
  90. static void mas_clean(struct mas_session *mas)
  91. {
  92. reset_request(mas);
  93. g_free(mas);
  94. }
  95. static void *mas_connect(struct obex_session *os, int *err)
  96. {
  97. struct mas_session *mas;
  98. DBG("");
  99. mas = g_new0(struct mas_session, 1);
  100. *err = messages_connect(&mas->backend_data);
  101. if (*err < 0)
  102. goto failed;
  103. manager_register_session(os);
  104. return mas;
  105. failed:
  106. g_free(mas);
  107. return NULL;
  108. }
  109. static void mas_disconnect(struct obex_session *os, void *user_data)
  110. {
  111. struct mas_session *mas = user_data;
  112. DBG("");
  113. manager_unregister_session(os);
  114. messages_disconnect(mas->backend_data);
  115. mas_clean(mas);
  116. }
  117. static int mas_get(struct obex_session *os, void *user_data)
  118. {
  119. struct mas_session *mas = user_data;
  120. const char *type = obex_get_type(os);
  121. const char *name = obex_get_name(os);
  122. int ret;
  123. DBG("GET: name %s type %s mas %p",
  124. name, type, mas);
  125. if (type == NULL)
  126. return -EBADR;
  127. ret = get_params(os, mas);
  128. if (ret < 0)
  129. goto failed;
  130. ret = obex_get_stream_start(os, name);
  131. if (ret < 0)
  132. goto failed;
  133. return 0;
  134. failed:
  135. reset_request(mas);
  136. return ret;
  137. }
  138. static int mas_put(struct obex_session *os, void *user_data)
  139. {
  140. struct mas_session *mas = user_data;
  141. const char *type = obex_get_type(os);
  142. const char *name = obex_get_name(os);
  143. int ret;
  144. DBG("PUT: name %s type %s mas %p", name, type, mas);
  145. if (type == NULL)
  146. return -EBADR;
  147. ret = get_params(os, mas);
  148. if (ret < 0)
  149. goto failed;
  150. ret = obex_put_stream_start(os, name);
  151. if (ret < 0)
  152. goto failed;
  153. return 0;
  154. failed:
  155. reset_request(mas);
  156. return ret;
  157. }
  158. /* FIXME: Preserve whitespaces */
  159. static void g_string_append_escaped_printf(GString *string,
  160. const char *format, ...)
  161. {
  162. va_list ap;
  163. char *escaped;
  164. va_start(ap, format);
  165. escaped = g_markup_vprintf_escaped(format, ap);
  166. g_string_append(string, escaped);
  167. g_free(escaped);
  168. va_end(ap);
  169. }
  170. static gchar *get_mse_timestamp(void)
  171. {
  172. struct timeval time_val;
  173. struct tm ltime;
  174. gchar *local_ts;
  175. char sign;
  176. if (gettimeofday(&time_val, NULL) < 0)
  177. return NULL;
  178. if (!localtime_r(&time_val.tv_sec, &ltime))
  179. return NULL;
  180. if (difftime(mktime(localtime(&time_val.tv_sec)),
  181. mktime(gmtime(&time_val.tv_sec))) < 0)
  182. sign = '+';
  183. else
  184. sign = '-';
  185. local_ts = g_strdup_printf("%04d%02d%02dT%02d%02d%02d%c%2ld%2ld",
  186. ltime.tm_year + 1900, ltime.tm_mon + 1,
  187. ltime.tm_mday, ltime.tm_hour,
  188. ltime.tm_min, ltime.tm_sec, sign,
  189. ltime.tm_gmtoff/3600,
  190. (ltime.tm_gmtoff%3600)/60);
  191. return local_ts;
  192. }
  193. static const char *yesorno(gboolean a)
  194. {
  195. if (a)
  196. return "yes";
  197. return "no";
  198. }
  199. static void get_messages_listing_cb(void *session, int err, uint16_t size,
  200. gboolean newmsg,
  201. const struct messages_message *entry,
  202. void *user_data)
  203. {
  204. struct mas_session *mas = user_data;
  205. uint16_t max = 1024;
  206. gchar *mse_time;
  207. if (err < 0 && err != -EAGAIN) {
  208. obex_object_set_io_flags(mas, G_IO_ERR, err);
  209. return;
  210. }
  211. if (mas->inparams)
  212. g_obex_apparam_get_uint16(mas->inparams, MAP_AP_MAXLISTCOUNT,
  213. &max);
  214. if (max == 0) {
  215. if (!entry)
  216. mas->finished = TRUE;
  217. goto proceed;
  218. }
  219. if (!mas->nth_call) {
  220. g_string_append(mas->buffer, ML_BODY_BEGIN);
  221. mas->nth_call = TRUE;
  222. }
  223. if (!entry) {
  224. g_string_append(mas->buffer, ML_BODY_END);
  225. mas->finished = TRUE;
  226. goto proceed;
  227. }
  228. g_string_append(mas->buffer, "<msg");
  229. g_string_append_escaped_printf(mas->buffer, " handle=\"%s\"",
  230. entry->handle);
  231. if (entry->mask & PMASK_SUBJECT)
  232. g_string_append_escaped_printf(mas->buffer, " subject=\"%s\"",
  233. entry->subject);
  234. if (entry->mask & PMASK_DATETIME)
  235. g_string_append_escaped_printf(mas->buffer, " datetime=\"%s\"",
  236. entry->datetime);
  237. if (entry->mask & PMASK_SENDER_NAME)
  238. g_string_append_escaped_printf(mas->buffer,
  239. " sender_name=\"%s\"",
  240. entry->sender_name);
  241. if (entry->mask & PMASK_SENDER_ADDRESSING)
  242. g_string_append_escaped_printf(mas->buffer,
  243. " sender_addressing=\"%s\"",
  244. entry->sender_addressing);
  245. if (entry->mask & PMASK_REPLYTO_ADDRESSING)
  246. g_string_append_escaped_printf(mas->buffer,
  247. " replyto_addressing=\"%s\"",
  248. entry->replyto_addressing);
  249. if (entry->mask & PMASK_RECIPIENT_NAME)
  250. g_string_append_escaped_printf(mas->buffer,
  251. " recipient_name=\"%s\"",
  252. entry->recipient_name);
  253. if (entry->mask & PMASK_RECIPIENT_ADDRESSING)
  254. g_string_append_escaped_printf(mas->buffer,
  255. " recipient_addressing=\"%s\"",
  256. entry->recipient_addressing);
  257. if (entry->mask & PMASK_TYPE)
  258. g_string_append_escaped_printf(mas->buffer, " type=\"%s\"",
  259. entry->type);
  260. if (entry->mask & PMASK_RECEPTION_STATUS)
  261. g_string_append_escaped_printf(mas->buffer,
  262. " reception_status=\"%s\"",
  263. entry->reception_status);
  264. if (entry->mask & PMASK_SIZE)
  265. g_string_append_escaped_printf(mas->buffer, " size=\"%s\"",
  266. entry->size);
  267. if (entry->mask & PMASK_ATTACHMENT_SIZE)
  268. g_string_append_escaped_printf(mas->buffer,
  269. " attachment_size=\"%s\"",
  270. entry->attachment_size);
  271. if (entry->mask & PMASK_TEXT)
  272. g_string_append_escaped_printf(mas->buffer, " text=\"%s\"",
  273. yesorno(entry->text));
  274. if (entry->mask & PMASK_READ)
  275. g_string_append_escaped_printf(mas->buffer, " read=\"%s\"",
  276. yesorno(entry->read));
  277. if (entry->mask & PMASK_SENT)
  278. g_string_append_escaped_printf(mas->buffer, " sent=\"%s\"",
  279. yesorno(entry->sent));
  280. if (entry->mask & PMASK_PROTECTED)
  281. g_string_append_escaped_printf(mas->buffer, " protected=\"%s\"",
  282. yesorno(entry->protect));
  283. if (entry->mask & PMASK_PRIORITY)
  284. g_string_append_escaped_printf(mas->buffer, " priority=\"%s\"",
  285. yesorno(entry->priority));
  286. g_string_append(mas->buffer, "/>\n");
  287. proceed:
  288. if (!entry) {
  289. mas->outparams = g_obex_apparam_set_uint16(mas->outparams,
  290. MAP_AP_MESSAGESLISTINGSIZE,
  291. size);
  292. mas->outparams = g_obex_apparam_set_uint8(mas->outparams,
  293. MAP_AP_NEWMESSAGE,
  294. newmsg ? 1 : 0);
  295. /* Response to report the local time of MSE */
  296. mse_time = get_mse_timestamp();
  297. if (mse_time) {
  298. g_obex_apparam_set_string(mas->outparams,
  299. MAP_AP_MSETIME, mse_time);
  300. g_free(mse_time);
  301. }
  302. }
  303. if (err != -EAGAIN)
  304. obex_object_set_io_flags(mas, G_IO_IN, 0);
  305. }
  306. static void get_message_cb(void *session, int err, gboolean fmore,
  307. const char *chunk, void *user_data)
  308. {
  309. struct mas_session *mas = user_data;
  310. DBG("");
  311. if (err < 0 && err != -EAGAIN) {
  312. obex_object_set_io_flags(mas, G_IO_ERR, err);
  313. return;
  314. }
  315. if (!chunk) {
  316. mas->finished = TRUE;
  317. goto proceed;
  318. }
  319. g_string_append(mas->buffer, chunk);
  320. proceed:
  321. if (err != -EAGAIN)
  322. obex_object_set_io_flags(mas, G_IO_IN, 0);
  323. }
  324. static void get_folder_listing_cb(void *session, int err, uint16_t size,
  325. const char *name, void *user_data)
  326. {
  327. struct mas_session *mas = user_data;
  328. uint16_t max = 1024;
  329. if (err < 0 && err != -EAGAIN) {
  330. obex_object_set_io_flags(mas, G_IO_ERR, err);
  331. return;
  332. }
  333. if (mas->inparams)
  334. g_obex_apparam_get_uint16(mas->inparams, MAP_AP_MAXLISTCOUNT,
  335. &max);
  336. if (max == 0) {
  337. if (err != -EAGAIN)
  338. mas->outparams = g_obex_apparam_set_uint16(
  339. mas->outparams,
  340. MAP_AP_FOLDERLISTINGSIZE,
  341. size);
  342. if (!name)
  343. mas->finished = TRUE;
  344. goto proceed;
  345. }
  346. if (!mas->nth_call) {
  347. g_string_append(mas->buffer, XML_DECL);
  348. g_string_append(mas->buffer, FL_DTD);
  349. if (!name) {
  350. g_string_append(mas->buffer, FL_BODY_EMPTY);
  351. mas->finished = TRUE;
  352. goto proceed;
  353. }
  354. g_string_append(mas->buffer, FL_BODY_BEGIN);
  355. mas->nth_call = TRUE;
  356. }
  357. if (!name) {
  358. g_string_append(mas->buffer, FL_BODY_END);
  359. mas->finished = TRUE;
  360. goto proceed;
  361. }
  362. if (g_strcmp0(name, "..") == 0)
  363. g_string_append(mas->buffer, FL_PARENT_FOLDER_ELEMENT);
  364. else
  365. g_string_append_escaped_printf(mas->buffer, FL_FOLDER_ELEMENT,
  366. name);
  367. proceed:
  368. if (err != -EAGAIN)
  369. obex_object_set_io_flags(mas, G_IO_IN, err);
  370. }
  371. static void set_status_cb(void *session, int err, void *user_data)
  372. {
  373. struct mas_session *mas = user_data;
  374. DBG("");
  375. mas->finished = TRUE;
  376. if (err < 0)
  377. obex_object_set_io_flags(mas, G_IO_ERR, err);
  378. else
  379. obex_object_set_io_flags(mas, G_IO_OUT, 0);
  380. }
  381. static int mas_setpath(struct obex_session *os, void *user_data)
  382. {
  383. const char *name;
  384. const uint8_t *nonhdr;
  385. struct mas_session *mas = user_data;
  386. if (obex_get_non_header_data(os, &nonhdr) != 2) {
  387. error("Set path failed: flag and constants not found!");
  388. return -EBADR;
  389. }
  390. name = obex_get_name(os);
  391. DBG("SETPATH: name %s nonhdr 0x%x%x", name, nonhdr[0], nonhdr[1]);
  392. if ((nonhdr[0] & 0x02) != 0x02) {
  393. DBG("Error: requested directory creation");
  394. return -EBADR;
  395. }
  396. return messages_set_folder(mas->backend_data, name, nonhdr[0] & 0x01);
  397. }
  398. static void *folder_listing_open(const char *name, int oflag, mode_t mode,
  399. void *driver_data, size_t *size, int *err)
  400. {
  401. struct mas_session *mas = driver_data;
  402. /* 1024 is the default when there was no MaxListCount sent */
  403. uint16_t max = 1024;
  404. uint16_t offset = 0;
  405. if (oflag != O_RDONLY) {
  406. *err = -EBADR;
  407. return NULL;
  408. }
  409. DBG("name = %s", name);
  410. if (mas->inparams) {
  411. g_obex_apparam_get_uint16(mas->inparams, MAP_AP_MAXLISTCOUNT,
  412. &max);
  413. g_obex_apparam_get_uint16(mas->inparams, MAP_AP_STARTOFFSET,
  414. &offset);
  415. }
  416. *err = messages_get_folder_listing(mas->backend_data, name, max,
  417. offset, get_folder_listing_cb, mas);
  418. mas->buffer = g_string_new("");
  419. if (*err < 0)
  420. return NULL;
  421. else
  422. return mas;
  423. }
  424. static void *msg_listing_open(const char *name, int oflag, mode_t mode,
  425. void *driver_data, size_t *size, int *err)
  426. {
  427. struct mas_session *mas = driver_data;
  428. struct messages_filter filter = { 0, };
  429. /* 1024 is the default when there was no MaxListCount sent */
  430. uint16_t max = 1024;
  431. uint16_t offset = 0;
  432. /* If MAP client does not specify the subject length,
  433. then subject_len = 0 and subject should be sent unaltered. */
  434. uint8_t subject_len = 0;
  435. DBG("");
  436. if (oflag != O_RDONLY) {
  437. *err = -EBADR;
  438. return NULL;
  439. }
  440. if (!mas->inparams)
  441. goto done;
  442. g_obex_apparam_get_uint16(mas->inparams, MAP_AP_MAXLISTCOUNT, &max);
  443. g_obex_apparam_get_uint16(mas->inparams, MAP_AP_STARTOFFSET, &offset);
  444. g_obex_apparam_get_uint8(mas->inparams, MAP_AP_SUBJECTLENGTH,
  445. &subject_len);
  446. g_obex_apparam_get_uint32(mas->inparams, MAP_AP_PARAMETERMASK,
  447. &filter.parameter_mask);
  448. g_obex_apparam_get_uint8(mas->inparams, MAP_AP_FILTERMESSAGETYPE,
  449. &filter.type);
  450. filter.period_begin = g_obex_apparam_get_string(mas->inparams,
  451. MAP_AP_FILTERPERIODBEGIN);
  452. filter.period_end = g_obex_apparam_get_string(mas->inparams,
  453. MAP_AP_FILTERPERIODEND);
  454. g_obex_apparam_get_uint8(mas->inparams, MAP_AP_FILTERREADSTATUS,
  455. &filter.read_status);
  456. filter.recipient = g_obex_apparam_get_string(mas->inparams,
  457. MAP_AP_FILTERRECIPIENT);
  458. filter.originator = g_obex_apparam_get_string(mas->inparams,
  459. MAP_AP_FILTERORIGINATOR);
  460. g_obex_apparam_get_uint8(mas->inparams, MAP_AP_FILTERPRIORITY,
  461. &filter.priority);
  462. done:
  463. *err = messages_get_messages_listing(mas->backend_data, name, max,
  464. offset, subject_len, &filter,
  465. get_messages_listing_cb, mas);
  466. mas->buffer = g_string_new("");
  467. if (*err < 0)
  468. return NULL;
  469. else
  470. return mas;
  471. }
  472. static void *message_open(const char *name, int oflag, mode_t mode,
  473. void *driver_data, size_t *size, int *err)
  474. {
  475. struct mas_session *mas = driver_data;
  476. DBG("");
  477. if (oflag != O_RDONLY) {
  478. DBG("Message pushing unsupported");
  479. *err = -ENOSYS;
  480. return NULL;
  481. }
  482. *err = messages_get_message(mas->backend_data, name, 0,
  483. get_message_cb, mas);
  484. mas->buffer = g_string_new("");
  485. if (*err < 0)
  486. return NULL;
  487. else
  488. return mas;
  489. }
  490. static void *message_update_open(const char *name, int oflag, mode_t mode,
  491. void *driver_data, size_t *size,
  492. int *err)
  493. {
  494. struct mas_session *mas = driver_data;
  495. DBG("");
  496. if (oflag == O_RDONLY) {
  497. *err = -EBADR;
  498. return NULL;
  499. }
  500. *err = messages_update_inbox(mas->backend_data, set_status_cb, mas);
  501. if (*err < 0)
  502. return NULL;
  503. else
  504. return mas;
  505. }
  506. static void *message_set_status_open(const char *name, int oflag, mode_t mode,
  507. void *driver_data, size_t *size,
  508. int *err)
  509. {
  510. struct mas_session *mas = driver_data;
  511. uint8_t indicator;
  512. uint8_t value;
  513. DBG("");
  514. if (oflag == O_RDONLY) {
  515. *err = -EBADR;
  516. return NULL;
  517. }
  518. if (!g_obex_apparam_get_uint8(mas->inparams, MAP_AP_STATUSINDICATOR,
  519. &indicator)) {
  520. *err = -EBADR;
  521. return NULL;
  522. }
  523. if (!g_obex_apparam_get_uint8(mas->inparams, MAP_AP_STATUSVALUE,
  524. &value)) {
  525. *err = -EBADR;
  526. return NULL;
  527. }
  528. if (indicator == READ_STATUS_REQ)
  529. *err = messages_set_read(mas->backend_data, name, value,
  530. set_status_cb, mas);
  531. else if (indicator == DELETE_STATUS_REQ)
  532. *err = messages_set_delete(mas->backend_data, name, value,
  533. set_status_cb, mas);
  534. else
  535. *err = -EBADR;
  536. if (*err < 0)
  537. return NULL;
  538. return mas;
  539. }
  540. static ssize_t any_get_next_header(void *object, void *buf, size_t mtu,
  541. uint8_t *hi)
  542. {
  543. struct mas_session *mas = object;
  544. DBG("");
  545. if (mas->buffer->len == 0 && !mas->finished)
  546. return -EAGAIN;
  547. *hi = G_OBEX_HDR_APPARAM;
  548. if (mas->ap_sent)
  549. return 0;
  550. mas->ap_sent = TRUE;
  551. if (!mas->outparams)
  552. return 0;
  553. return g_obex_apparam_encode(mas->outparams, buf, mtu);
  554. }
  555. static void *any_open(const char *name, int oflag, mode_t mode,
  556. void *driver_data, size_t *size, int *err)
  557. {
  558. DBG("");
  559. *err = -ENOSYS;
  560. return NULL;
  561. }
  562. static ssize_t any_write(void *object, const void *buf, size_t count)
  563. {
  564. DBG("");
  565. return count;
  566. }
  567. static ssize_t any_read(void *obj, void *buf, size_t count)
  568. {
  569. struct mas_session *mas = obj;
  570. ssize_t len;
  571. DBG("");
  572. len = string_read(mas->buffer, buf, count);
  573. if (len == 0 && !mas->finished)
  574. return -EAGAIN;
  575. return len;
  576. }
  577. static int any_close(void *obj)
  578. {
  579. struct mas_session *mas = obj;
  580. DBG("");
  581. if (!mas->finished)
  582. messages_abort(mas->backend_data);
  583. reset_request(mas);
  584. return 0;
  585. }
  586. static void *notification_registration_open(const char *name, int oflag,
  587. mode_t mode, void *driver_data,
  588. size_t *size, int *err)
  589. {
  590. struct mas_session *mas = driver_data;
  591. uint8_t status;
  592. DBG("");
  593. if (O_RDONLY) {
  594. *err = -EBADR;
  595. return NULL;
  596. }
  597. if (!g_obex_apparam_get_uint8(mas->inparams, MAP_AP_NOTIFICATIONSTATUS,
  598. &status)) {
  599. *err = -EBADR;
  600. return NULL;
  601. }
  602. mas->notification_status = status;
  603. mas->finished = TRUE;
  604. *err = 0;
  605. return mas;
  606. }
  607. static struct obex_service_driver mas = {
  608. .name = "Message Access server",
  609. .service = OBEX_MAS,
  610. .target = MAS_TARGET,
  611. .target_size = TARGET_SIZE,
  612. .connect = mas_connect,
  613. .get = mas_get,
  614. .put = mas_put,
  615. .setpath = mas_setpath,
  616. .disconnect = mas_disconnect,
  617. };
  618. static struct obex_mime_type_driver mime_map = {
  619. .target = MAS_TARGET,
  620. .target_size = TARGET_SIZE,
  621. .mimetype = NULL,
  622. .open = any_open,
  623. .close = any_close,
  624. .read = any_read,
  625. .write = any_write,
  626. };
  627. static struct obex_mime_type_driver mime_message = {
  628. .target = MAS_TARGET,
  629. .target_size = TARGET_SIZE,
  630. .mimetype = "x-bt/message",
  631. .open = message_open,
  632. .close = any_close,
  633. .read = any_read,
  634. .write = any_write,
  635. };
  636. static struct obex_mime_type_driver mime_folder_listing = {
  637. .target = MAS_TARGET,
  638. .target_size = TARGET_SIZE,
  639. .mimetype = "x-obex/folder-listing",
  640. .get_next_header = any_get_next_header,
  641. .open = folder_listing_open,
  642. .close = any_close,
  643. .read = any_read,
  644. .write = any_write,
  645. };
  646. static struct obex_mime_type_driver mime_msg_listing = {
  647. .target = MAS_TARGET,
  648. .target_size = TARGET_SIZE,
  649. .mimetype = "x-bt/MAP-msg-listing",
  650. .get_next_header = any_get_next_header,
  651. .open = msg_listing_open,
  652. .close = any_close,
  653. .read = any_read,
  654. .write = any_write,
  655. };
  656. static struct obex_mime_type_driver mime_notification_registration = {
  657. .target = MAS_TARGET,
  658. .target_size = TARGET_SIZE,
  659. .mimetype = "x-bt/MAP-NotificationRegistration",
  660. .open = notification_registration_open,
  661. .close = any_close,
  662. .read = any_read,
  663. .write = any_write,
  664. };
  665. static struct obex_mime_type_driver mime_message_status = {
  666. .target = MAS_TARGET,
  667. .target_size = TARGET_SIZE,
  668. .mimetype = "x-bt/messageStatus",
  669. .open = message_set_status_open,
  670. .close = any_close,
  671. .read = any_read,
  672. .write = any_write,
  673. };
  674. static struct obex_mime_type_driver mime_message_update = {
  675. .target = MAS_TARGET,
  676. .target_size = TARGET_SIZE,
  677. .mimetype = "x-bt/MAP-messageUpdate",
  678. .open = message_update_open,
  679. .close = any_close,
  680. .read = any_read,
  681. .write = any_write,
  682. };
  683. static struct obex_mime_type_driver *map_drivers[] = {
  684. &mime_map,
  685. &mime_message,
  686. &mime_folder_listing,
  687. &mime_msg_listing,
  688. &mime_notification_registration,
  689. &mime_message_status,
  690. &mime_message_update,
  691. NULL
  692. };
  693. static int mas_init(void)
  694. {
  695. int err;
  696. int i;
  697. err = messages_init();
  698. if (err < 0)
  699. return err;
  700. for (i = 0; map_drivers[i] != NULL; ++i) {
  701. err = obex_mime_type_driver_register(map_drivers[i]);
  702. if (err < 0)
  703. goto failed;
  704. }
  705. err = obex_service_driver_register(&mas);
  706. if (err < 0)
  707. goto failed;
  708. return 0;
  709. failed:
  710. for (--i; i >= 0; --i)
  711. obex_mime_type_driver_unregister(map_drivers[i]);
  712. messages_exit();
  713. return err;
  714. }
  715. static void mas_exit(void)
  716. {
  717. int i;
  718. obex_service_driver_unregister(&mas);
  719. for (i = 0; map_drivers[i] != NULL; ++i)
  720. obex_mime_type_driver_unregister(map_drivers[i]);
  721. messages_exit();
  722. }
  723. OBEX_PLUGIN_DEFINE(mas, mas_init, mas_exit)