map.c 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. *
  4. * OBEX Client
  5. *
  6. * Copyright (C) 2011 Bartosz Szatkowski <bulislaw@linux.com> for Comarch
  7. *
  8. */
  9. #ifdef HAVE_CONFIG_H
  10. #include <config.h>
  11. #endif
  12. #define _GNU_SOURCE
  13. #include <errno.h>
  14. #include <string.h>
  15. #include <stdio.h>
  16. #include <stdbool.h>
  17. #include <inttypes.h>
  18. #include <stdlib.h>
  19. #include <glib.h>
  20. #include "lib/sdp.h"
  21. #include "gobex/gobex-apparam.h"
  22. #include "gdbus/gdbus.h"
  23. #include "obexd/src/log.h"
  24. #include "obexd/src/map_ap.h"
  25. #include "map-event.h"
  26. #include "map.h"
  27. #include "transfer.h"
  28. #include "session.h"
  29. #include "driver.h"
  30. #define OBEX_MAS_UUID \
  31. "\xBB\x58\x2B\x40\x42\x0C\x11\xDB\xB0\xDE\x08\x00\x20\x0C\x9A\x66"
  32. #define OBEX_MAS_UUID_LEN 16
  33. #define MAP_INTERFACE "org.bluez.obex.MessageAccess1"
  34. #define MAP_MSG_INTERFACE "org.bluez.obex.Message1"
  35. #define ERROR_INTERFACE "org.bluez.obex.Error"
  36. #define MAS_UUID "00001132-0000-1000-8000-00805f9b34fb"
  37. #define DEFAULT_COUNT 1024
  38. #define DEFAULT_OFFSET 0
  39. #define CHARSET_NATIVE 0
  40. #define CHARSET_UTF8 1
  41. static const char * const filter_list[] = {
  42. "subject",
  43. "timestamp",
  44. "sender",
  45. "sender-address",
  46. "recipient",
  47. "recipient-address",
  48. "type",
  49. "size",
  50. "status",
  51. "text",
  52. "attachment",
  53. "priority",
  54. "read",
  55. "sent",
  56. "protected",
  57. "replyto",
  58. NULL
  59. };
  60. #define FILTER_BIT_MAX 15
  61. #define FILTER_ALL 0x0000FFFF
  62. #define FILTER_READ_STATUS_NONE 0x00
  63. #define FILTER_READ_STATUS_ONLY_UNREAD 0x01
  64. #define FILTER_READ_STATUS_ONLY_READ 0x02
  65. #define FILTER_PRIORITY_NONE 0x00
  66. #define FILTER_PRIORITY_ONLY_HIGH 0x01
  67. #define FILTER_PRIORITY_ONLY_NONHIGH 0x02
  68. #define STATUS_READ 0
  69. #define STATUS_DELETE 1
  70. #define FILLER_BYTE 0x30
  71. struct map_data {
  72. struct obc_session *session;
  73. GHashTable *messages;
  74. int16_t mas_instance_id;
  75. uint8_t supported_message_types;
  76. uint32_t supported_features;
  77. };
  78. struct pending_request {
  79. struct map_data *map;
  80. DBusMessage *msg;
  81. char *folder;
  82. };
  83. #define MAP_MSG_FLAG_PRIORITY 0x01
  84. #define MAP_MSG_FLAG_READ 0x02
  85. #define MAP_MSG_FLAG_SENT 0x04
  86. #define MAP_MSG_FLAG_PROTECTED 0x08
  87. #define MAP_MSG_FLAG_TEXT 0x10
  88. struct map_msg {
  89. struct map_data *data;
  90. char *path;
  91. uint64_t handle;
  92. char *subject;
  93. char *timestamp;
  94. char *sender;
  95. char *sender_address;
  96. char *replyto;
  97. char *recipient;
  98. char *recipient_address;
  99. char *type;
  100. uint64_t size;
  101. char *status;
  102. uint64_t attachment_size;
  103. uint8_t flags;
  104. char *folder;
  105. GDBusPendingPropertySet pending;
  106. };
  107. struct map_parser {
  108. struct pending_request *request;
  109. DBusMessageIter *iter;
  110. };
  111. static DBusConnection *conn = NULL;
  112. static struct pending_request *pending_request_new(struct map_data *map,
  113. DBusMessage *message)
  114. {
  115. struct pending_request *p;
  116. p = g_new0(struct pending_request, 1);
  117. p->map = map;
  118. p->msg = dbus_message_ref(message);
  119. return p;
  120. }
  121. static void pending_request_free(struct pending_request *p)
  122. {
  123. dbus_message_unref(p->msg);
  124. g_free(p->folder);
  125. g_free(p);
  126. }
  127. static void simple_cb(struct obc_session *session,
  128. struct obc_transfer *transfer,
  129. GError *err, void *user_data)
  130. {
  131. struct pending_request *request = user_data;
  132. DBusMessage *reply;
  133. if (err != NULL)
  134. reply = g_dbus_create_error(request->msg,
  135. ERROR_INTERFACE ".Failed",
  136. "%s", err->message);
  137. else
  138. reply = dbus_message_new_method_return(request->msg);
  139. g_dbus_send_message(conn, reply);
  140. pending_request_free(request);
  141. }
  142. static DBusMessage *map_setpath(DBusConnection *connection,
  143. DBusMessage *message, void *user_data)
  144. {
  145. struct map_data *map = user_data;
  146. const char *folder;
  147. struct pending_request *request;
  148. GError *err = NULL;
  149. if (dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &folder,
  150. DBUS_TYPE_INVALID) == FALSE)
  151. return g_dbus_create_error(message,
  152. ERROR_INTERFACE ".InvalidArguments",
  153. NULL);
  154. request = pending_request_new(map, message);
  155. obc_session_setpath(map->session, folder, simple_cb, request, &err);
  156. if (err != NULL) {
  157. DBusMessage *reply;
  158. reply = g_dbus_create_error(message,
  159. ERROR_INTERFACE ".Failed",
  160. "%s", err->message);
  161. g_error_free(err);
  162. pending_request_free(request);
  163. return reply;
  164. }
  165. return NULL;
  166. }
  167. static void folder_element(GMarkupParseContext *ctxt, const char *element,
  168. const char **names, const char **values,
  169. gpointer user_data, GError **gerr)
  170. {
  171. DBusMessageIter dict, *iter = user_data;
  172. const char *key;
  173. int i;
  174. if (strcasecmp("folder", element) != 0)
  175. return;
  176. dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
  177. DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
  178. DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
  179. DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
  180. for (i = 0, key = names[i]; key; key = names[++i]) {
  181. if (strcasecmp("name", key) == 0)
  182. g_dbus_dict_append_entry(&dict, "Name",
  183. DBUS_TYPE_STRING,
  184. &values[i]);
  185. }
  186. dbus_message_iter_close_container(iter, &dict);
  187. }
  188. static const GMarkupParser folder_parser = {
  189. folder_element,
  190. NULL,
  191. NULL,
  192. NULL,
  193. NULL
  194. };
  195. static void folder_listing_cb(struct obc_session *session,
  196. struct obc_transfer *transfer,
  197. GError *err, void *user_data)
  198. {
  199. struct pending_request *request = user_data;
  200. GMarkupParseContext *ctxt;
  201. DBusMessage *reply;
  202. DBusMessageIter iter, array;
  203. char *contents;
  204. size_t size;
  205. int perr;
  206. if (err != NULL) {
  207. reply = g_dbus_create_error(request->msg,
  208. ERROR_INTERFACE ".Failed",
  209. "%s", err->message);
  210. goto done;
  211. }
  212. perr = obc_transfer_get_contents(transfer, &contents, &size);
  213. if (perr < 0) {
  214. reply = g_dbus_create_error(request->msg,
  215. ERROR_INTERFACE ".Failed",
  216. "Error reading contents: %s",
  217. strerror(-perr));
  218. goto done;
  219. }
  220. reply = dbus_message_new_method_return(request->msg);
  221. if (reply == NULL) {
  222. g_free(contents);
  223. goto clean;
  224. }
  225. dbus_message_iter_init_append(reply, &iter);
  226. dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
  227. DBUS_TYPE_ARRAY_AS_STRING
  228. DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
  229. DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
  230. DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &array);
  231. ctxt = g_markup_parse_context_new(&folder_parser, 0, &array, NULL);
  232. g_markup_parse_context_parse(ctxt, contents, size, NULL);
  233. g_markup_parse_context_free(ctxt);
  234. dbus_message_iter_close_container(&iter, &array);
  235. g_free(contents);
  236. done:
  237. g_dbus_send_message(conn, reply);
  238. clean:
  239. pending_request_free(request);
  240. }
  241. static DBusMessage *get_folder_listing(struct map_data *map,
  242. DBusMessage *message,
  243. GObexApparam *apparam)
  244. {
  245. struct pending_request *request;
  246. struct obc_transfer *transfer;
  247. GError *err = NULL;
  248. DBusMessage *reply;
  249. transfer = obc_transfer_get("x-obex/folder-listing", NULL, NULL, &err);
  250. if (transfer == NULL) {
  251. g_obex_apparam_free(apparam);
  252. goto fail;
  253. }
  254. obc_transfer_set_apparam(transfer, apparam);
  255. request = pending_request_new(map, message);
  256. if (!obc_session_queue(map->session, transfer, folder_listing_cb,
  257. request, &err)) {
  258. pending_request_free(request);
  259. goto fail;
  260. }
  261. return NULL;
  262. fail:
  263. reply = g_dbus_create_error(message, ERROR_INTERFACE ".Failed", "%s",
  264. err->message);
  265. g_error_free(err);
  266. return reply;
  267. }
  268. static GObexApparam *parse_offset(GObexApparam *apparam, DBusMessageIter *iter)
  269. {
  270. guint16 num;
  271. if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_UINT16)
  272. return NULL;
  273. dbus_message_iter_get_basic(iter, &num);
  274. return g_obex_apparam_set_uint16(apparam, MAP_AP_STARTOFFSET, num);
  275. }
  276. static GObexApparam *parse_max_count(GObexApparam *apparam,
  277. DBusMessageIter *iter)
  278. {
  279. guint16 num;
  280. if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_UINT16)
  281. return NULL;
  282. dbus_message_iter_get_basic(iter, &num);
  283. return g_obex_apparam_set_uint16(apparam, MAP_AP_MAXLISTCOUNT, num);
  284. }
  285. static GObexApparam *parse_folder_filters(GObexApparam *apparam,
  286. DBusMessageIter *iter)
  287. {
  288. DBusMessageIter array;
  289. if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
  290. return NULL;
  291. dbus_message_iter_recurse(iter, &array);
  292. while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) {
  293. const char *key;
  294. DBusMessageIter value, entry;
  295. dbus_message_iter_recurse(&array, &entry);
  296. dbus_message_iter_get_basic(&entry, &key);
  297. dbus_message_iter_next(&entry);
  298. dbus_message_iter_recurse(&entry, &value);
  299. if (strcasecmp(key, "Offset") == 0) {
  300. if (parse_offset(apparam, &value) == NULL)
  301. return NULL;
  302. } else if (strcasecmp(key, "MaxCount") == 0) {
  303. if (parse_max_count(apparam, &value) == NULL)
  304. return NULL;
  305. }
  306. dbus_message_iter_next(&array);
  307. }
  308. return apparam;
  309. }
  310. static DBusMessage *map_list_folders(DBusConnection *connection,
  311. DBusMessage *message, void *user_data)
  312. {
  313. struct map_data *map = user_data;
  314. GObexApparam *apparam;
  315. DBusMessageIter args;
  316. dbus_message_iter_init(message, &args);
  317. apparam = g_obex_apparam_set_uint16(NULL, MAP_AP_MAXLISTCOUNT,
  318. DEFAULT_COUNT);
  319. apparam = g_obex_apparam_set_uint16(apparam, MAP_AP_STARTOFFSET,
  320. DEFAULT_OFFSET);
  321. if (parse_folder_filters(apparam, &args) == NULL) {
  322. g_obex_apparam_free(apparam);
  323. return g_dbus_create_error(message,
  324. ERROR_INTERFACE ".InvalidArguments", NULL);
  325. }
  326. return get_folder_listing(map, message, apparam);
  327. }
  328. static void map_msg_free(void *data)
  329. {
  330. struct map_msg *msg = data;
  331. g_free(msg->path);
  332. g_free(msg->subject);
  333. g_free(msg->folder);
  334. g_free(msg->timestamp);
  335. g_free(msg->sender);
  336. g_free(msg->sender_address);
  337. g_free(msg->replyto);
  338. g_free(msg->recipient);
  339. g_free(msg->recipient_address);
  340. g_free(msg->type);
  341. g_free(msg->status);
  342. g_free(msg);
  343. }
  344. static DBusMessage *map_msg_get(DBusConnection *connection,
  345. DBusMessage *message, void *user_data)
  346. {
  347. struct map_msg *msg = user_data;
  348. struct obc_transfer *transfer;
  349. const char *target_file;
  350. gboolean attachment;
  351. GError *err = NULL;
  352. DBusMessage *reply;
  353. GObexApparam *apparam;
  354. char handle[17];
  355. if (dbus_message_get_args(message, NULL,
  356. DBUS_TYPE_STRING, &target_file,
  357. DBUS_TYPE_BOOLEAN, &attachment,
  358. DBUS_TYPE_INVALID) == FALSE)
  359. return g_dbus_create_error(message,
  360. ERROR_INTERFACE ".InvalidArguments", NULL);
  361. snprintf(handle, sizeof(handle), "%" PRIx64, msg->handle);
  362. transfer = obc_transfer_get("x-bt/message", handle, target_file, &err);
  363. if (transfer == NULL)
  364. goto fail;
  365. apparam = g_obex_apparam_set_uint8(NULL, MAP_AP_ATTACHMENT,
  366. attachment);
  367. apparam = g_obex_apparam_set_uint8(apparam, MAP_AP_CHARSET,
  368. CHARSET_UTF8);
  369. obc_transfer_set_apparam(transfer, apparam);
  370. if (!obc_session_queue(msg->data->session, transfer, NULL, NULL, &err))
  371. goto fail;
  372. return obc_transfer_create_dbus_reply(transfer, message);
  373. fail:
  374. reply = g_dbus_create_error(message, ERROR_INTERFACE ".Failed", "%s",
  375. err->message);
  376. g_error_free(err);
  377. return reply;
  378. }
  379. static void set_message_status_cb(struct obc_session *session,
  380. struct obc_transfer *transfer,
  381. GError *err, void *user_data)
  382. {
  383. struct map_msg *msg = user_data;
  384. if (err != NULL) {
  385. g_dbus_pending_property_error(msg->pending,
  386. ERROR_INTERFACE ".Failed",
  387. "%s", err->message);
  388. goto done;
  389. }
  390. g_dbus_pending_property_success(msg->pending);
  391. done:
  392. msg->pending = 0;
  393. }
  394. static gboolean get_folder(const GDBusPropertyTable *property,
  395. DBusMessageIter *iter, void *data)
  396. {
  397. struct map_msg *msg = data;
  398. dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &msg->folder);
  399. return TRUE;
  400. }
  401. static gboolean subject_exists(const GDBusPropertyTable *property, void *data)
  402. {
  403. struct map_msg *msg = data;
  404. return msg->subject != NULL;
  405. }
  406. static gboolean get_subject(const GDBusPropertyTable *property,
  407. DBusMessageIter *iter, void *data)
  408. {
  409. struct map_msg *msg = data;
  410. dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &msg->subject);
  411. return TRUE;
  412. }
  413. static gboolean timestamp_exists(const GDBusPropertyTable *property, void *data)
  414. {
  415. struct map_msg *msg = data;
  416. return msg->timestamp != NULL;
  417. }
  418. static gboolean get_timestamp(const GDBusPropertyTable *property,
  419. DBusMessageIter *iter, void *data)
  420. {
  421. struct map_msg *msg = data;
  422. dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &msg->timestamp);
  423. return TRUE;
  424. }
  425. static gboolean sender_exists(const GDBusPropertyTable *property, void *data)
  426. {
  427. struct map_msg *msg = data;
  428. return msg->sender != NULL;
  429. }
  430. static gboolean get_sender(const GDBusPropertyTable *property,
  431. DBusMessageIter *iter, void *data)
  432. {
  433. struct map_msg *msg = data;
  434. dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &msg->sender);
  435. return TRUE;
  436. }
  437. static gboolean sender_address_exists(const GDBusPropertyTable *property,
  438. void *data)
  439. {
  440. struct map_msg *msg = data;
  441. return msg->sender_address != NULL;
  442. }
  443. static gboolean get_sender_address(const GDBusPropertyTable *property,
  444. DBusMessageIter *iter, void *data)
  445. {
  446. struct map_msg *msg = data;
  447. dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
  448. &msg->sender_address);
  449. return TRUE;
  450. }
  451. static gboolean replyto_exists(const GDBusPropertyTable *property, void *data)
  452. {
  453. struct map_msg *msg = data;
  454. return msg->replyto != NULL;
  455. }
  456. static gboolean get_replyto(const GDBusPropertyTable *property,
  457. DBusMessageIter *iter, void *data)
  458. {
  459. struct map_msg *msg = data;
  460. dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &msg->replyto);
  461. return TRUE;
  462. }
  463. static gboolean recipient_exists(const GDBusPropertyTable *property, void *data)
  464. {
  465. struct map_msg *msg = data;
  466. return msg->recipient != NULL;
  467. }
  468. static gboolean get_recipient(const GDBusPropertyTable *property,
  469. DBusMessageIter *iter, void *data)
  470. {
  471. struct map_msg *msg = data;
  472. dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &msg->recipient);
  473. return TRUE;
  474. }
  475. static gboolean recipient_address_exists(const GDBusPropertyTable *property,
  476. void *data)
  477. {
  478. struct map_msg *msg = data;
  479. return msg->recipient_address != NULL;
  480. }
  481. static gboolean get_recipient_address(const GDBusPropertyTable *property,
  482. DBusMessageIter *iter, void *data)
  483. {
  484. struct map_msg *msg = data;
  485. dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
  486. &msg->recipient_address);
  487. return TRUE;
  488. }
  489. static gboolean type_exists(const GDBusPropertyTable *property, void *data)
  490. {
  491. struct map_msg *msg = data;
  492. return msg->type != NULL;
  493. }
  494. static gboolean get_type(const GDBusPropertyTable *property,
  495. DBusMessageIter *iter, void *data)
  496. {
  497. struct map_msg *msg = data;
  498. dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &msg->type);
  499. return TRUE;
  500. }
  501. static gboolean get_size(const GDBusPropertyTable *property,
  502. DBusMessageIter *iter, void *data)
  503. {
  504. struct map_msg *msg = data;
  505. dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT64, &msg->size);
  506. return TRUE;
  507. }
  508. static gboolean reception_status_exists(const GDBusPropertyTable *property,
  509. void *data)
  510. {
  511. struct map_msg *msg = data;
  512. return msg->status != NULL;
  513. }
  514. static gboolean get_reception_status(const GDBusPropertyTable *property,
  515. DBusMessageIter *iter, void *data)
  516. {
  517. struct map_msg *msg = data;
  518. dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &msg->status);
  519. return TRUE;
  520. }
  521. static gboolean get_attachment_size(const GDBusPropertyTable *property,
  522. DBusMessageIter *iter, void *data)
  523. {
  524. struct map_msg *msg = data;
  525. dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT64,
  526. &msg->attachment_size);
  527. return TRUE;
  528. }
  529. static gboolean get_flag(const GDBusPropertyTable *property,
  530. DBusMessageIter *iter, uint8_t flag,
  531. void *data)
  532. {
  533. struct map_msg *msg = data;
  534. dbus_bool_t value = (msg->flags & flag) != 0;
  535. dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &value);
  536. return TRUE;
  537. }
  538. static gboolean get_priority(const GDBusPropertyTable *property,
  539. DBusMessageIter *iter, void *data)
  540. {
  541. return get_flag(property, iter, MAP_MSG_FLAG_PRIORITY, data);
  542. }
  543. static gboolean get_read(const GDBusPropertyTable *property,
  544. DBusMessageIter *iter, void *data)
  545. {
  546. return get_flag(property, iter, MAP_MSG_FLAG_READ, data);
  547. }
  548. static gboolean get_sent(const GDBusPropertyTable *property,
  549. DBusMessageIter *iter, void *data)
  550. {
  551. return get_flag(property, iter, MAP_MSG_FLAG_SENT, data);
  552. }
  553. static gboolean get_protected(const GDBusPropertyTable *property,
  554. DBusMessageIter *iter, void *data)
  555. {
  556. return get_flag(property, iter, MAP_MSG_FLAG_PROTECTED, data);
  557. }
  558. static gboolean get_text(const GDBusPropertyTable *property,
  559. DBusMessageIter *iter, void *data)
  560. {
  561. return get_flag(property, iter, MAP_MSG_FLAG_TEXT, data);
  562. }
  563. static void set_status(const GDBusPropertyTable *property,
  564. DBusMessageIter *iter, GDBusPendingPropertySet id,
  565. uint8_t status, void *data)
  566. {
  567. struct map_msg *msg = data;
  568. struct obc_transfer *transfer;
  569. gboolean value;
  570. GError *err = NULL;
  571. GObexApparam *apparam;
  572. char contents[1];
  573. char handle[17];
  574. if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_BOOLEAN) {
  575. g_dbus_pending_property_error(id,
  576. ERROR_INTERFACE ".InvalidArguments",
  577. "Invalid arguments in method call");
  578. return;
  579. }
  580. dbus_message_iter_get_basic(iter, &value);
  581. contents[0] = FILLER_BYTE;
  582. snprintf(handle, sizeof(handle), "%" PRIx64, msg->handle);
  583. transfer = obc_transfer_put("x-bt/messageStatus", handle, NULL,
  584. contents, sizeof(contents), &err);
  585. if (transfer == NULL)
  586. goto fail;
  587. apparam = g_obex_apparam_set_uint8(NULL, MAP_AP_STATUSINDICATOR,
  588. status);
  589. apparam = g_obex_apparam_set_uint8(apparam, MAP_AP_STATUSVALUE,
  590. value);
  591. obc_transfer_set_apparam(transfer, apparam);
  592. if (!obc_session_queue(msg->data->session, transfer,
  593. set_message_status_cb, msg, &err))
  594. goto fail;
  595. msg->pending = id;
  596. return;
  597. fail:
  598. g_dbus_pending_property_error(id, ERROR_INTERFACE ".Failed", "%s",
  599. err->message);
  600. g_error_free(err);
  601. }
  602. static void set_read(const GDBusPropertyTable *property,
  603. DBusMessageIter *iter, GDBusPendingPropertySet id,
  604. void *data)
  605. {
  606. set_status(property, iter, id, STATUS_READ, data);
  607. }
  608. static void set_deleted(const GDBusPropertyTable *property,
  609. DBusMessageIter *iter, GDBusPendingPropertySet id,
  610. void *data)
  611. {
  612. set_status(property, iter, id, STATUS_DELETE, data);
  613. }
  614. static const GDBusMethodTable map_msg_methods[] = {
  615. { GDBUS_METHOD("Get",
  616. GDBUS_ARGS({ "targetfile", "s" },
  617. { "attachment", "b" }),
  618. GDBUS_ARGS({ "transfer", "o" },
  619. { "properties", "a{sv}" }),
  620. map_msg_get) },
  621. { }
  622. };
  623. static const GDBusPropertyTable map_msg_properties[] = {
  624. { "Folder", "s", get_folder },
  625. { "Subject", "s", get_subject, NULL, subject_exists },
  626. { "Timestamp", "s", get_timestamp, NULL, timestamp_exists },
  627. { "Sender", "s", get_sender, NULL, sender_exists },
  628. { "SenderAddress", "s", get_sender_address, NULL,
  629. sender_address_exists },
  630. { "ReplyTo", "s", get_replyto, NULL, replyto_exists },
  631. { "Recipient", "s", get_recipient, NULL, recipient_exists },
  632. { "RecipientAddress", "s", get_recipient_address, NULL,
  633. recipient_address_exists },
  634. { "Type", "s", get_type, NULL, type_exists },
  635. { "Size", "t", get_size },
  636. { "Text", "b", get_text },
  637. { "Status", "s", get_reception_status, NULL, reception_status_exists },
  638. { "AttachmentSize", "t", get_attachment_size },
  639. { "Priority", "b", get_priority },
  640. { "Read", "b", get_read, set_read },
  641. { "Sent", "b", get_sent },
  642. { "Protected", "b", get_protected },
  643. { "Deleted", "b", NULL, set_deleted },
  644. { }
  645. };
  646. static void parse_type(struct map_msg *msg, const char *value)
  647. {
  648. const char *type = NULL;
  649. if (strcasecmp(value, "SMS_GSM") == 0)
  650. type = "sms-gsm";
  651. else if (strcasecmp(value, "SMS_CDMA") == 0)
  652. type = "sms-cdma";
  653. else if (strcasecmp(value, "EMAIL") == 0)
  654. type = "email";
  655. else if (strcasecmp(value, "MMS") == 0)
  656. type = "mms";
  657. if (g_strcmp0(msg->type, type) == 0)
  658. return;
  659. g_free(msg->type);
  660. msg->type = g_strdup(type);
  661. g_dbus_emit_property_changed(conn, msg->path,
  662. MAP_MSG_INTERFACE, "Type");
  663. }
  664. static struct map_msg *map_msg_create(struct map_data *data, uint64_t handle,
  665. const char *folder, const char *type)
  666. {
  667. struct map_msg *msg;
  668. msg = g_new0(struct map_msg, 1);
  669. msg->data = data;
  670. msg->handle = handle;
  671. msg->path = g_strdup_printf("%s/message%" PRIu64,
  672. obc_session_get_path(data->session),
  673. msg->handle);
  674. msg->folder = g_strdup(folder);
  675. if (!g_dbus_register_interface(conn, msg->path, MAP_MSG_INTERFACE,
  676. map_msg_methods, NULL,
  677. map_msg_properties,
  678. msg, map_msg_free)) {
  679. map_msg_free(msg);
  680. return NULL;
  681. }
  682. g_hash_table_insert(data->messages, &msg->handle, msg);
  683. if (type)
  684. parse_type(msg, type);
  685. return msg;
  686. }
  687. static void parse_subject(struct map_msg *msg, const char *value)
  688. {
  689. if (g_strcmp0(msg->subject, value) == 0)
  690. return;
  691. g_free(msg->subject);
  692. msg->subject = g_strdup(value);
  693. g_dbus_emit_property_changed(conn, msg->path,
  694. MAP_MSG_INTERFACE, "Subject");
  695. }
  696. static void parse_datetime(struct map_msg *msg, const char *value)
  697. {
  698. if (g_strcmp0(msg->timestamp, value) == 0)
  699. return;
  700. g_free(msg->timestamp);
  701. msg->timestamp = g_strdup(value);
  702. g_dbus_emit_property_changed(conn, msg->path,
  703. MAP_MSG_INTERFACE, "Timestamp");
  704. }
  705. static void parse_sender(struct map_msg *msg, const char *value)
  706. {
  707. if (g_strcmp0(msg->sender, value) == 0)
  708. return;
  709. g_free(msg->sender);
  710. msg->sender = g_strdup(value);
  711. g_dbus_emit_property_changed(conn, msg->path,
  712. MAP_MSG_INTERFACE, "Sender");
  713. }
  714. static void parse_sender_address(struct map_msg *msg, const char *value)
  715. {
  716. if (g_strcmp0(msg->sender_address, value) == 0)
  717. return;
  718. g_free(msg->sender_address);
  719. msg->sender_address = g_strdup(value);
  720. g_dbus_emit_property_changed(conn, msg->path,
  721. MAP_MSG_INTERFACE, "SenderAddress");
  722. }
  723. static void parse_replyto(struct map_msg *msg, const char *value)
  724. {
  725. if (g_strcmp0(msg->replyto, value) == 0)
  726. return;
  727. g_free(msg->replyto);
  728. msg->replyto = g_strdup(value);
  729. g_dbus_emit_property_changed(conn, msg->path,
  730. MAP_MSG_INTERFACE, "ReplyTo");
  731. }
  732. static void parse_recipient(struct map_msg *msg, const char *value)
  733. {
  734. if (g_strcmp0(msg->recipient, value) == 0)
  735. return;
  736. g_free(msg->recipient);
  737. msg->recipient = g_strdup(value);
  738. g_dbus_emit_property_changed(conn, msg->path,
  739. MAP_MSG_INTERFACE, "Recipient");
  740. }
  741. static void parse_recipient_address(struct map_msg *msg, const char *value)
  742. {
  743. if (g_strcmp0(msg->recipient_address, value) == 0)
  744. return;
  745. g_free(msg->recipient_address);
  746. msg->recipient_address = g_strdup(value);
  747. g_dbus_emit_property_changed(conn, msg->path,
  748. MAP_MSG_INTERFACE, "RecipientAddress");
  749. }
  750. static void parse_size(struct map_msg *msg, const char *value)
  751. {
  752. uint64_t size = g_ascii_strtoll(value, NULL, 10);
  753. if (msg->size == size)
  754. return;
  755. msg->size = size;
  756. g_dbus_emit_property_changed(conn, msg->path,
  757. MAP_MSG_INTERFACE, "Size");
  758. }
  759. static void parse_text(struct map_msg *msg, const char *value)
  760. {
  761. gboolean flag = strcasecmp(value, "no") != 0;
  762. uint8_t oldflags = msg->flags;
  763. if (flag)
  764. msg->flags |= MAP_MSG_FLAG_TEXT;
  765. else
  766. msg->flags &= ~MAP_MSG_FLAG_TEXT;
  767. if (msg->flags != oldflags)
  768. g_dbus_emit_property_changed(conn, msg->path,
  769. MAP_MSG_INTERFACE, "Text");
  770. }
  771. static void parse_status(struct map_msg *msg, const char *value)
  772. {
  773. if (g_strcmp0(msg->status, value) == 0)
  774. return;
  775. g_free(msg->status);
  776. msg->status = g_strdup(value);
  777. g_dbus_emit_property_changed(conn, msg->path,
  778. MAP_MSG_INTERFACE, "Status");
  779. }
  780. static void parse_attachment_size(struct map_msg *msg, const char *value)
  781. {
  782. uint64_t attachment_size = g_ascii_strtoll(value, NULL, 10);
  783. if (msg->attachment_size == attachment_size)
  784. return;
  785. msg->attachment_size = attachment_size;
  786. g_dbus_emit_property_changed(conn, msg->path,
  787. MAP_MSG_INTERFACE, "AttachmentSize");
  788. }
  789. static void parse_priority(struct map_msg *msg, const char *value)
  790. {
  791. gboolean flag = strcasecmp(value, "no") != 0;
  792. uint8_t oldflags = msg->flags;
  793. if (flag)
  794. msg->flags |= MAP_MSG_FLAG_PRIORITY;
  795. else
  796. msg->flags &= ~MAP_MSG_FLAG_PRIORITY;
  797. if (msg->flags != oldflags)
  798. g_dbus_emit_property_changed(conn, msg->path,
  799. MAP_MSG_INTERFACE, "Priority");
  800. }
  801. static void parse_read(struct map_msg *msg, const char *value)
  802. {
  803. gboolean flag = strcasecmp(value, "no") != 0;
  804. uint8_t oldflags = msg->flags;
  805. if (flag)
  806. msg->flags |= MAP_MSG_FLAG_READ;
  807. else
  808. msg->flags &= ~MAP_MSG_FLAG_READ;
  809. if (msg->flags != oldflags)
  810. g_dbus_emit_property_changed(conn, msg->path,
  811. MAP_MSG_INTERFACE, "Read");
  812. }
  813. static void parse_sent(struct map_msg *msg, const char *value)
  814. {
  815. gboolean flag = strcasecmp(value, "no") != 0;
  816. uint8_t oldflags = msg->flags;
  817. if (flag)
  818. msg->flags |= MAP_MSG_FLAG_SENT;
  819. else
  820. msg->flags &= ~MAP_MSG_FLAG_SENT;
  821. if (msg->flags != oldflags)
  822. g_dbus_emit_property_changed(conn, msg->path,
  823. MAP_MSG_INTERFACE, "Sent");
  824. }
  825. static void parse_protected(struct map_msg *msg, const char *value)
  826. {
  827. gboolean flag = strcasecmp(value, "no") != 0;
  828. uint8_t oldflags = msg->flags;
  829. if (flag)
  830. msg->flags |= MAP_MSG_FLAG_PROTECTED;
  831. else
  832. msg->flags &= ~MAP_MSG_FLAG_PROTECTED;
  833. if (msg->flags != oldflags)
  834. g_dbus_emit_property_changed(conn, msg->path,
  835. MAP_MSG_INTERFACE, "Protected");
  836. }
  837. static struct map_msg_parser {
  838. const char *name;
  839. void (*func) (struct map_msg *msg, const char *value);
  840. } msg_parsers[] = {
  841. { "subject", parse_subject },
  842. { "datetime", parse_datetime },
  843. { "sender_name", parse_sender },
  844. { "sender_addressing", parse_sender_address },
  845. { "replyto_addressing", parse_replyto },
  846. { "recipient_name", parse_recipient },
  847. { "recipient_addressing", parse_recipient_address },
  848. { "type", parse_type },
  849. { "size", parse_size },
  850. { "text", parse_text },
  851. { "reception_status", parse_status },
  852. { "attachment_size", parse_attachment_size },
  853. { "priority", parse_priority },
  854. { "read", parse_read },
  855. { "sent", parse_sent },
  856. { "protected", parse_protected },
  857. { }
  858. };
  859. static void msg_element(GMarkupParseContext *ctxt, const char *element,
  860. const char **names, const char **values,
  861. gpointer user_data, GError **gerr)
  862. {
  863. struct map_parser *parser = user_data;
  864. struct map_data *data = parser->request->map;
  865. DBusMessageIter entry, *iter = parser->iter;
  866. struct map_msg *msg;
  867. const char *key;
  868. int i;
  869. uint64_t handle;
  870. if (strcasecmp("msg", element) != 0)
  871. return;
  872. for (i = 0, key = names[i]; key; key = names[++i]) {
  873. if (strcasecmp(key, "handle") == 0)
  874. break;
  875. }
  876. handle = strtoull(values[i], NULL, 16);
  877. msg = g_hash_table_lookup(data->messages, &handle);
  878. if (msg == NULL) {
  879. msg = map_msg_create(data, handle, parser->request->folder,
  880. NULL);
  881. if (msg == NULL)
  882. return;
  883. }
  884. dbus_message_iter_open_container(iter, DBUS_TYPE_DICT_ENTRY, NULL,
  885. &entry);
  886. dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
  887. &msg->path);
  888. for (i = 0, key = names[i]; key; key = names[++i]) {
  889. struct map_msg_parser *parser;
  890. for (parser = msg_parsers; parser && parser->name; parser++) {
  891. if (strcasecmp(key, parser->name) == 0) {
  892. if (values[i])
  893. parser->func(msg, values[i]);
  894. break;
  895. }
  896. }
  897. }
  898. g_dbus_get_properties(conn, msg->path, MAP_MSG_INTERFACE, &entry);
  899. dbus_message_iter_close_container(iter, &entry);
  900. }
  901. static const GMarkupParser msg_parser = {
  902. msg_element,
  903. NULL,
  904. NULL,
  905. NULL,
  906. NULL
  907. };
  908. static void message_listing_cb(struct obc_session *session,
  909. struct obc_transfer *transfer,
  910. GError *err, void *user_data)
  911. {
  912. struct pending_request *request = user_data;
  913. struct map_parser *parser;
  914. GMarkupParseContext *ctxt;
  915. DBusMessage *reply;
  916. DBusMessageIter iter, array;
  917. char *contents;
  918. size_t size;
  919. int perr;
  920. if (err != NULL) {
  921. reply = g_dbus_create_error(request->msg,
  922. ERROR_INTERFACE ".Failed",
  923. "%s", err->message);
  924. goto done;
  925. }
  926. perr = obc_transfer_get_contents(transfer, &contents, &size);
  927. if (perr < 0) {
  928. reply = g_dbus_create_error(request->msg,
  929. ERROR_INTERFACE ".Failed",
  930. "Error reading contents: %s",
  931. strerror(-perr));
  932. goto done;
  933. }
  934. reply = dbus_message_new_method_return(request->msg);
  935. if (reply == NULL) {
  936. g_free(contents);
  937. goto clean;
  938. }
  939. dbus_message_iter_init_append(reply, &iter);
  940. dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
  941. DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
  942. DBUS_TYPE_OBJECT_PATH_AS_STRING
  943. DBUS_TYPE_ARRAY_AS_STRING
  944. DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
  945. DBUS_TYPE_STRING_AS_STRING
  946. DBUS_TYPE_VARIANT_AS_STRING
  947. DBUS_DICT_ENTRY_END_CHAR_AS_STRING
  948. DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
  949. &array);
  950. parser = g_new(struct map_parser, 1);
  951. parser->request = request;
  952. parser->iter = &array;
  953. ctxt = g_markup_parse_context_new(&msg_parser, 0, parser, NULL);
  954. g_markup_parse_context_parse(ctxt, contents, size, NULL);
  955. g_markup_parse_context_free(ctxt);
  956. dbus_message_iter_close_container(&iter, &array);
  957. g_free(contents);
  958. g_free(parser);
  959. done:
  960. g_dbus_send_message(conn, reply);
  961. clean:
  962. pending_request_free(request);
  963. }
  964. static char *get_absolute_folder(struct map_data *map, const char *subfolder)
  965. {
  966. const char *root = obc_session_get_folder(map->session);
  967. if (!subfolder || strlen(subfolder) == 0)
  968. return g_strdup(root);
  969. else if (g_str_has_suffix(root, "/"))
  970. return g_strconcat(root, subfolder, NULL);
  971. else
  972. return g_strconcat(root, "/", subfolder, NULL);
  973. }
  974. static DBusMessage *get_message_listing(struct map_data *map,
  975. DBusMessage *message,
  976. const char *folder,
  977. GObexApparam *apparam)
  978. {
  979. struct pending_request *request;
  980. struct obc_transfer *transfer;
  981. GError *err = NULL;
  982. DBusMessage *reply;
  983. transfer = obc_transfer_get("x-bt/MAP-msg-listing", folder, NULL, &err);
  984. if (transfer == NULL) {
  985. g_obex_apparam_free(apparam);
  986. goto fail;
  987. }
  988. obc_transfer_set_apparam(transfer, apparam);
  989. request = pending_request_new(map, message);
  990. request->folder = get_absolute_folder(map, folder);
  991. if (!obc_session_queue(map->session, transfer, message_listing_cb,
  992. request, &err)) {
  993. pending_request_free(request);
  994. goto fail;
  995. }
  996. return NULL;
  997. fail:
  998. reply = g_dbus_create_error(message, ERROR_INTERFACE ".Failed", "%s",
  999. err->message);
  1000. g_error_free(err);
  1001. return reply;
  1002. }
  1003. static GObexApparam *parse_subject_length(GObexApparam *apparam,
  1004. DBusMessageIter *iter)
  1005. {
  1006. guint8 num;
  1007. if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_BYTE)
  1008. return NULL;
  1009. dbus_message_iter_get_basic(iter, &num);
  1010. return g_obex_apparam_set_uint8(apparam, MAP_AP_SUBJECTLENGTH, num);
  1011. }
  1012. static uint64_t get_filter_mask(const char *filterstr)
  1013. {
  1014. int i;
  1015. if (!filterstr)
  1016. return 0;
  1017. if (!g_ascii_strcasecmp(filterstr, "ALL"))
  1018. return FILTER_ALL;
  1019. for (i = 0; filter_list[i] != NULL; i++)
  1020. if (!g_ascii_strcasecmp(filterstr, filter_list[i]))
  1021. return 1ULL << i;
  1022. return 0;
  1023. }
  1024. static int set_field(guint32 *filter, const char *filterstr)
  1025. {
  1026. guint64 mask;
  1027. mask = get_filter_mask(filterstr);
  1028. if (mask == 0)
  1029. return -EINVAL;
  1030. *filter |= mask;
  1031. return 0;
  1032. }
  1033. static GObexApparam *parse_fields(GObexApparam *apparam, DBusMessageIter *iter)
  1034. {
  1035. DBusMessageIter array;
  1036. guint32 filter = 0;
  1037. if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
  1038. return NULL;
  1039. dbus_message_iter_recurse(iter, &array);
  1040. while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRING) {
  1041. const char *string;
  1042. dbus_message_iter_get_basic(&array, &string);
  1043. if (set_field(&filter, string) < 0)
  1044. return NULL;
  1045. dbus_message_iter_next(&array);
  1046. }
  1047. return g_obex_apparam_set_uint32(apparam, MAP_AP_PARAMETERMASK,
  1048. filter);
  1049. }
  1050. static GObexApparam *parse_filter_type(GObexApparam *apparam,
  1051. DBusMessageIter *iter)
  1052. {
  1053. DBusMessageIter array;
  1054. guint8 types = 0;
  1055. if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
  1056. return NULL;
  1057. dbus_message_iter_recurse(iter, &array);
  1058. while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRING) {
  1059. const char *string;
  1060. dbus_message_iter_get_basic(&array, &string);
  1061. if (!g_ascii_strcasecmp(string, "sms"))
  1062. types |= 0x03; /* sms-gsm and sms-cdma */
  1063. else if (!g_ascii_strcasecmp(string, "email"))
  1064. types |= 0x04; /* email */
  1065. else if (!g_ascii_strcasecmp(string, "mms"))
  1066. types |= 0x08; /* mms */
  1067. else
  1068. return NULL;
  1069. dbus_message_iter_next(&array);
  1070. }
  1071. return g_obex_apparam_set_uint8(apparam, MAP_AP_FILTERMESSAGETYPE,
  1072. types);
  1073. }
  1074. static GObexApparam *parse_period_begin(GObexApparam *apparam,
  1075. DBusMessageIter *iter)
  1076. {
  1077. const char *string;
  1078. if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING)
  1079. return NULL;
  1080. dbus_message_iter_get_basic(iter, &string);
  1081. return g_obex_apparam_set_string(apparam, MAP_AP_FILTERPERIODBEGIN,
  1082. string);
  1083. }
  1084. static GObexApparam *parse_period_end(GObexApparam *apparam,
  1085. DBusMessageIter *iter)
  1086. {
  1087. const char *string;
  1088. if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING)
  1089. return NULL;
  1090. dbus_message_iter_get_basic(iter, &string);
  1091. return g_obex_apparam_set_string(apparam, MAP_AP_FILTERPERIODEND,
  1092. string);
  1093. }
  1094. static GObexApparam *parse_filter_read(GObexApparam *apparam,
  1095. DBusMessageIter *iter)
  1096. {
  1097. guint8 status = FILTER_READ_STATUS_NONE;
  1098. dbus_bool_t dbus_status = FALSE;
  1099. if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_BOOLEAN)
  1100. return NULL;
  1101. dbus_message_iter_get_basic(iter, &dbus_status);
  1102. if (dbus_status)
  1103. status = FILTER_READ_STATUS_ONLY_READ;
  1104. else
  1105. status = FILTER_READ_STATUS_ONLY_UNREAD;
  1106. return g_obex_apparam_set_uint8(apparam, MAP_AP_FILTERREADSTATUS,
  1107. status);
  1108. }
  1109. static GObexApparam *parse_filter_recipient(GObexApparam *apparam,
  1110. DBusMessageIter *iter)
  1111. {
  1112. const char *string;
  1113. if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING)
  1114. return NULL;
  1115. dbus_message_iter_get_basic(iter, &string);
  1116. return g_obex_apparam_set_string(apparam, MAP_AP_FILTERRECIPIENT,
  1117. string);
  1118. }
  1119. static GObexApparam *parse_filter_sender(GObexApparam *apparam,
  1120. DBusMessageIter *iter)
  1121. {
  1122. const char *string;
  1123. if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING)
  1124. return NULL;
  1125. dbus_message_iter_get_basic(iter, &string);
  1126. return g_obex_apparam_set_string(apparam, MAP_AP_FILTERORIGINATOR,
  1127. string);
  1128. }
  1129. static GObexApparam *parse_filter_priority(GObexApparam *apparam,
  1130. DBusMessageIter *iter)
  1131. {
  1132. guint8 priority = FILTER_PRIORITY_NONE;
  1133. dbus_bool_t dbus_priority = FALSE;
  1134. if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_BOOLEAN)
  1135. return NULL;
  1136. dbus_message_iter_get_basic(iter, &dbus_priority);
  1137. if (dbus_priority)
  1138. priority = FILTER_PRIORITY_ONLY_HIGH;
  1139. else
  1140. priority = FILTER_PRIORITY_ONLY_NONHIGH;
  1141. return g_obex_apparam_set_uint8(apparam, MAP_AP_FILTERPRIORITY,
  1142. priority);
  1143. }
  1144. static GObexApparam *parse_message_filters(GObexApparam *apparam,
  1145. DBusMessageIter *iter)
  1146. {
  1147. DBusMessageIter array;
  1148. DBG("");
  1149. if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
  1150. return NULL;
  1151. dbus_message_iter_recurse(iter, &array);
  1152. while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) {
  1153. const char *key;
  1154. DBusMessageIter value, entry;
  1155. dbus_message_iter_recurse(&array, &entry);
  1156. dbus_message_iter_get_basic(&entry, &key);
  1157. dbus_message_iter_next(&entry);
  1158. dbus_message_iter_recurse(&entry, &value);
  1159. if (strcasecmp(key, "Offset") == 0) {
  1160. if (parse_offset(apparam, &value) == NULL)
  1161. return NULL;
  1162. } else if (strcasecmp(key, "MaxCount") == 0) {
  1163. if (parse_max_count(apparam, &value) == NULL)
  1164. return NULL;
  1165. } else if (strcasecmp(key, "SubjectLength") == 0) {
  1166. if (parse_subject_length(apparam, &value) == NULL)
  1167. return NULL;
  1168. } else if (strcasecmp(key, "Fields") == 0) {
  1169. if (parse_fields(apparam, &value) == NULL)
  1170. return NULL;
  1171. } else if (strcasecmp(key, "Types") == 0) {
  1172. if (parse_filter_type(apparam, &value) == NULL)
  1173. return NULL;
  1174. } else if (strcasecmp(key, "PeriodBegin") == 0) {
  1175. if (parse_period_begin(apparam, &value) == NULL)
  1176. return NULL;
  1177. } else if (strcasecmp(key, "PeriodEnd") == 0) {
  1178. if (parse_period_end(apparam, &value) == NULL)
  1179. return NULL;
  1180. } else if (strcasecmp(key, "Read") == 0) {
  1181. if (parse_filter_read(apparam, &value) == NULL)
  1182. return NULL;
  1183. } else if (strcasecmp(key, "Recipient") == 0) {
  1184. if (parse_filter_recipient(apparam, &value) == NULL)
  1185. return NULL;
  1186. } else if (strcasecmp(key, "Sender") == 0) {
  1187. if (parse_filter_sender(apparam, &value) == NULL)
  1188. return NULL;
  1189. } else if (strcasecmp(key, "Priority") == 0) {
  1190. if (parse_filter_priority(apparam, &value) == NULL)
  1191. return NULL;
  1192. }
  1193. dbus_message_iter_next(&array);
  1194. }
  1195. return apparam;
  1196. }
  1197. static DBusMessage *map_list_messages(DBusConnection *connection,
  1198. DBusMessage *message, void *user_data)
  1199. {
  1200. struct map_data *map = user_data;
  1201. const char *folder;
  1202. GObexApparam *apparam;
  1203. DBusMessageIter args;
  1204. dbus_message_iter_init(message, &args);
  1205. if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_STRING)
  1206. return g_dbus_create_error(message,
  1207. ERROR_INTERFACE ".InvalidArguments", NULL);
  1208. dbus_message_iter_get_basic(&args, &folder);
  1209. apparam = g_obex_apparam_set_uint16(NULL, MAP_AP_MAXLISTCOUNT,
  1210. DEFAULT_COUNT);
  1211. apparam = g_obex_apparam_set_uint16(apparam, MAP_AP_STARTOFFSET,
  1212. DEFAULT_OFFSET);
  1213. dbus_message_iter_next(&args);
  1214. if (parse_message_filters(apparam, &args) == NULL) {
  1215. g_obex_apparam_free(apparam);
  1216. return g_dbus_create_error(message,
  1217. ERROR_INTERFACE ".InvalidArguments", NULL);
  1218. }
  1219. return get_message_listing(map, message, folder, apparam);
  1220. }
  1221. static char **get_filter_strs(uint64_t filter, int *size)
  1222. {
  1223. char **list, **item;
  1224. int i;
  1225. list = g_malloc0(sizeof(char **) * (FILTER_BIT_MAX + 2));
  1226. item = list;
  1227. for (i = 0; filter_list[i] != NULL; i++)
  1228. if (filter & (1ULL << i))
  1229. *(item++) = g_strdup(filter_list[i]);
  1230. *item = NULL;
  1231. *size = item - list;
  1232. return list;
  1233. }
  1234. static DBusMessage *map_list_filter_fields(DBusConnection *connection,
  1235. DBusMessage *message, void *user_data)
  1236. {
  1237. char **filters = NULL;
  1238. int size;
  1239. DBusMessage *reply;
  1240. filters = get_filter_strs(FILTER_ALL, &size);
  1241. reply = dbus_message_new_method_return(message);
  1242. dbus_message_append_args(reply, DBUS_TYPE_ARRAY,
  1243. DBUS_TYPE_STRING, &filters, size,
  1244. DBUS_TYPE_INVALID);
  1245. g_strfreev(filters);
  1246. return reply;
  1247. }
  1248. static void update_inbox_cb(struct obc_session *session,
  1249. struct obc_transfer *transfer,
  1250. GError *err, void *user_data)
  1251. {
  1252. struct pending_request *request = user_data;
  1253. DBusMessage *reply;
  1254. if (err != NULL) {
  1255. reply = g_dbus_create_error(request->msg,
  1256. ERROR_INTERFACE ".Failed",
  1257. "%s", err->message);
  1258. goto done;
  1259. }
  1260. reply = dbus_message_new_method_return(request->msg);
  1261. done:
  1262. g_dbus_send_message(conn, reply);
  1263. pending_request_free(request);
  1264. }
  1265. static DBusMessage *map_update_inbox(DBusConnection *connection,
  1266. DBusMessage *message, void *user_data)
  1267. {
  1268. struct map_data *map = user_data;
  1269. DBusMessage *reply;
  1270. char contents[1];
  1271. struct obc_transfer *transfer;
  1272. GError *err = NULL;
  1273. struct pending_request *request;
  1274. contents[0] = FILLER_BYTE;
  1275. transfer = obc_transfer_put("x-bt/MAP-messageUpdate", NULL, NULL,
  1276. contents, sizeof(contents),
  1277. &err);
  1278. if (transfer == NULL)
  1279. goto fail;
  1280. request = pending_request_new(map, message);
  1281. if (!obc_session_queue(map->session, transfer, update_inbox_cb,
  1282. request, &err)) {
  1283. pending_request_free(request);
  1284. goto fail;
  1285. }
  1286. return NULL;
  1287. fail:
  1288. reply = g_dbus_create_error(message, ERROR_INTERFACE ".Failed", "%s",
  1289. err->message);
  1290. g_error_free(err);
  1291. return reply;
  1292. }
  1293. static DBusMessage *push_message(struct map_data *map,
  1294. DBusMessage *message,
  1295. const char *filename,
  1296. const char *folder,
  1297. GObexApparam *apparam)
  1298. {
  1299. struct obc_transfer *transfer;
  1300. GError *err = NULL;
  1301. DBusMessage *reply;
  1302. transfer = obc_transfer_put("x-bt/message", folder, filename,
  1303. NULL, 0, &err);
  1304. if (transfer == NULL) {
  1305. g_obex_apparam_free(apparam);
  1306. goto fail;
  1307. }
  1308. obc_transfer_set_apparam(transfer, apparam);
  1309. if (!obc_session_queue(map->session, transfer, NULL, NULL, &err))
  1310. goto fail;
  1311. return obc_transfer_create_dbus_reply(transfer, message);
  1312. fail:
  1313. reply = g_dbus_create_error(message, ERROR_INTERFACE ".Failed", "%s",
  1314. err->message);
  1315. g_error_free(err);
  1316. return reply;
  1317. }
  1318. static GObexApparam *parse_transparent(GObexApparam *apparam,
  1319. DBusMessageIter *iter)
  1320. {
  1321. dbus_bool_t transparent;
  1322. if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_BOOLEAN)
  1323. return NULL;
  1324. dbus_message_iter_get_basic(iter, &transparent);
  1325. return g_obex_apparam_set_uint8(apparam, MAP_AP_TRANSPARENT,
  1326. transparent ? TRUE : FALSE);
  1327. }
  1328. static GObexApparam *parse_retry(GObexApparam *apparam, DBusMessageIter *iter)
  1329. {
  1330. dbus_bool_t retry;
  1331. if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_BOOLEAN)
  1332. return NULL;
  1333. dbus_message_iter_get_basic(iter, &retry);
  1334. return g_obex_apparam_set_uint8(apparam, MAP_AP_RETRY,
  1335. retry ? TRUE : FALSE);
  1336. }
  1337. static GObexApparam *parse_charset(GObexApparam *apparam, DBusMessageIter *iter)
  1338. {
  1339. guint8 charset = 0;
  1340. const char *string;
  1341. if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING)
  1342. return NULL;
  1343. dbus_message_iter_get_basic(iter, &string);
  1344. if (strcasecmp(string, "native") == 0)
  1345. charset = CHARSET_NATIVE;
  1346. else if (strcasecmp(string, "utf8") == 0)
  1347. charset = CHARSET_UTF8;
  1348. else
  1349. return NULL;
  1350. return g_obex_apparam_set_uint8(apparam, MAP_AP_CHARSET, charset);
  1351. }
  1352. static GObexApparam *parse_push_options(GObexApparam *apparam,
  1353. DBusMessageIter *iter)
  1354. {
  1355. DBusMessageIter array;
  1356. if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
  1357. return NULL;
  1358. dbus_message_iter_recurse(iter, &array);
  1359. while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) {
  1360. const char *key;
  1361. DBusMessageIter value, entry;
  1362. dbus_message_iter_recurse(&array, &entry);
  1363. dbus_message_iter_get_basic(&entry, &key);
  1364. dbus_message_iter_next(&entry);
  1365. dbus_message_iter_recurse(&entry, &value);
  1366. if (strcasecmp(key, "Transparent") == 0) {
  1367. if (parse_transparent(apparam, &value) == NULL)
  1368. return NULL;
  1369. } else if (strcasecmp(key, "Retry") == 0) {
  1370. if (parse_retry(apparam, &value) == NULL)
  1371. return NULL;
  1372. } else if (strcasecmp(key, "Charset") == 0) {
  1373. if (parse_charset(apparam, &value) == NULL)
  1374. return NULL;
  1375. }
  1376. dbus_message_iter_next(&array);
  1377. }
  1378. return apparam;
  1379. }
  1380. static DBusMessage *map_push_message(DBusConnection *connection,
  1381. DBusMessage *message, void *user_data)
  1382. {
  1383. struct map_data *map = user_data;
  1384. char *filename;
  1385. char *folder;
  1386. GObexApparam *apparam;
  1387. DBusMessageIter args;
  1388. dbus_message_iter_init(message, &args);
  1389. if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_STRING)
  1390. return g_dbus_create_error(message,
  1391. ERROR_INTERFACE ".InvalidArguments", NULL);
  1392. dbus_message_iter_get_basic(&args, &filename);
  1393. dbus_message_iter_next(&args);
  1394. if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_STRING) {
  1395. return g_dbus_create_error(message,
  1396. ERROR_INTERFACE ".InvalidArguments", NULL);
  1397. }
  1398. dbus_message_iter_get_basic(&args, &folder);
  1399. dbus_message_iter_next(&args);
  1400. apparam = g_obex_apparam_set_uint8(NULL, MAP_AP_CHARSET, CHARSET_UTF8);
  1401. if (parse_push_options(apparam, &args) == NULL) {
  1402. g_obex_apparam_free(apparam);
  1403. return g_dbus_create_error(message,
  1404. ERROR_INTERFACE ".InvalidArguments", NULL);
  1405. }
  1406. return push_message(map, message, filename, folder, apparam);
  1407. }
  1408. static const GDBusMethodTable map_methods[] = {
  1409. { GDBUS_ASYNC_METHOD("SetFolder",
  1410. GDBUS_ARGS({ "name", "s" }), NULL,
  1411. map_setpath) },
  1412. { GDBUS_ASYNC_METHOD("ListFolders",
  1413. GDBUS_ARGS({ "filters", "a{sv}" }),
  1414. GDBUS_ARGS({ "content", "aa{sv}" }),
  1415. map_list_folders) },
  1416. { GDBUS_ASYNC_METHOD("ListMessages",
  1417. GDBUS_ARGS({ "folder", "s" }, { "filter", "a{sv}" }),
  1418. GDBUS_ARGS({ "messages", "a{oa{sv}}" }),
  1419. map_list_messages) },
  1420. { GDBUS_METHOD("ListFilterFields",
  1421. NULL,
  1422. GDBUS_ARGS({ "fields", "as" }),
  1423. map_list_filter_fields) },
  1424. { GDBUS_ASYNC_METHOD("UpdateInbox",
  1425. NULL,
  1426. NULL,
  1427. map_update_inbox) },
  1428. { GDBUS_ASYNC_METHOD("PushMessage",
  1429. GDBUS_ARGS({ "file", "s" }, { "folder", "s" },
  1430. { "args", "a{sv}" }),
  1431. GDBUS_ARGS({ "transfer", "o" },
  1432. { "properties", "a{sv}" }),
  1433. map_push_message) },
  1434. { }
  1435. };
  1436. static void map_msg_remove(void *data)
  1437. {
  1438. struct map_msg *msg = data;
  1439. char *path;
  1440. path = msg->path;
  1441. msg->path = NULL;
  1442. g_dbus_unregister_interface(conn, path, MAP_MSG_INTERFACE);
  1443. g_free(path);
  1444. }
  1445. static void map_handle_new_message(struct map_data *map,
  1446. struct map_event *event)
  1447. {
  1448. struct map_msg *msg;
  1449. msg = g_hash_table_lookup(map->messages, &event->handle);
  1450. /* New message event can be used if a new message replaces an old one */
  1451. if (msg)
  1452. g_hash_table_remove(map->messages, &event->handle);
  1453. map_msg_create(map, event->handle, event->folder, event->msg_type);
  1454. }
  1455. static void map_handle_status_changed(struct map_data *map,
  1456. struct map_event *event,
  1457. const char *status)
  1458. {
  1459. struct map_msg *msg;
  1460. msg = g_hash_table_lookup(map->messages, &event->handle);
  1461. if (msg == NULL)
  1462. return;
  1463. if (g_strcmp0(msg->status, status) == 0)
  1464. return;
  1465. g_free(msg->status);
  1466. msg->status = g_strdup(status);
  1467. g_dbus_emit_property_changed(conn, msg->path, MAP_MSG_INTERFACE,
  1468. "Status");
  1469. }
  1470. static void map_handle_folder_changed(struct map_data *map,
  1471. struct map_event *event,
  1472. const char *folder)
  1473. {
  1474. struct map_msg *msg;
  1475. if (!folder)
  1476. return;
  1477. msg = g_hash_table_lookup(map->messages, &event->handle);
  1478. if (!msg)
  1479. return;
  1480. if (g_strcmp0(msg->folder, folder) == 0)
  1481. return;
  1482. g_free(msg->folder);
  1483. msg->folder = g_strdup(folder);
  1484. g_dbus_emit_property_changed(conn, msg->path, MAP_MSG_INTERFACE,
  1485. "Folder");
  1486. }
  1487. static void map_handle_notification(struct map_event *event, void *user_data)
  1488. {
  1489. struct map_data *map = user_data;
  1490. DBG("Event report for %s:%d", obc_session_get_destination(map->session),
  1491. map->mas_instance_id);
  1492. DBG("type=%x handle=%" PRIx64 " folder=%s old_folder=%s msg_type=%s",
  1493. event->type, event->handle, event->folder, event->old_folder,
  1494. event->msg_type);
  1495. switch (event->type) {
  1496. case MAP_ET_NEW_MESSAGE:
  1497. map_handle_new_message(map, event);
  1498. map_handle_status_changed(map, event, "notification");
  1499. break;
  1500. case MAP_ET_DELIVERY_SUCCESS:
  1501. map_handle_status_changed(map, event, "delivery-success");
  1502. break;
  1503. case MAP_ET_SENDING_SUCCESS:
  1504. map_handle_status_changed(map, event, "sending-success");
  1505. break;
  1506. case MAP_ET_DELIVERY_FAILURE:
  1507. map_handle_status_changed(map, event, "delivery-failure");
  1508. break;
  1509. case MAP_ET_SENDING_FAILURE:
  1510. map_handle_status_changed(map, event, "sending-failure");
  1511. break;
  1512. case MAP_ET_MESSAGE_DELETED:
  1513. map_handle_folder_changed(map, event, "/telecom/msg/deleted");
  1514. break;
  1515. case MAP_ET_MESSAGE_SHIFT:
  1516. map_handle_folder_changed(map, event, event->folder);
  1517. break;
  1518. case MAP_ET_MEMORY_FULL:
  1519. case MAP_ET_MEMORY_AVAILABLE:
  1520. default:
  1521. break;
  1522. }
  1523. }
  1524. static bool set_notification_registration(struct map_data *map, bool status)
  1525. {
  1526. struct obc_transfer *transfer;
  1527. GError *err = NULL;
  1528. GObexApparam *apparam;
  1529. char contents[1];
  1530. const char *address;
  1531. address = obc_session_get_destination(map->session);
  1532. if (!address || map->mas_instance_id < 0)
  1533. return FALSE;
  1534. if (status) {
  1535. map_register_event_handler(map->session, map->mas_instance_id,
  1536. &map_handle_notification, map);
  1537. } else {
  1538. map_unregister_event_handler(map->session,
  1539. map->mas_instance_id);
  1540. }
  1541. contents[0] = FILLER_BYTE;
  1542. transfer = obc_transfer_put("x-bt/MAP-NotificationRegistration", NULL,
  1543. NULL, contents, sizeof(contents), &err);
  1544. if (transfer == NULL)
  1545. return false;
  1546. apparam = g_obex_apparam_set_uint8(NULL, MAP_AP_NOTIFICATIONSTATUS,
  1547. status);
  1548. obc_transfer_set_apparam(transfer, apparam);
  1549. if (obc_session_queue(map->session, transfer, NULL, map, &err))
  1550. return true;
  1551. return false;
  1552. }
  1553. static void map_free(void *data)
  1554. {
  1555. struct map_data *map = data;
  1556. set_notification_registration(map, false);
  1557. obc_session_unref(map->session);
  1558. g_hash_table_unref(map->messages);
  1559. g_free(map);
  1560. }
  1561. static void parse_service_record(struct map_data *map)
  1562. {
  1563. const void *data;
  1564. /* MAS instance id */
  1565. map->mas_instance_id = -1;
  1566. data = obc_session_get_attribute(map->session,
  1567. SDP_ATTR_MAS_INSTANCE_ID);
  1568. if (data != NULL)
  1569. map->mas_instance_id = *(uint8_t *)data;
  1570. else
  1571. DBG("Failed to read MAS instance id");
  1572. /* Supported Message Types */
  1573. data = obc_session_get_attribute(map->session,
  1574. SDP_ATTR_SUPPORTED_MESSAGE_TYPES);
  1575. if (data != NULL)
  1576. map->supported_message_types = *(uint8_t *)data;
  1577. else
  1578. DBG("Failed to read supported message types");
  1579. /* Supported Feature Bits */
  1580. data = obc_session_get_attribute(map->session,
  1581. SDP_ATTR_MAP_SUPPORTED_FEATURES);
  1582. if(data != NULL)
  1583. map->supported_features = *(uint32_t *) data;
  1584. else
  1585. map->supported_features = 0x0000001f;
  1586. }
  1587. static int map_probe(struct obc_session *session)
  1588. {
  1589. struct map_data *map;
  1590. const char *path;
  1591. path = obc_session_get_path(session);
  1592. map = g_try_new0(struct map_data, 1);
  1593. if (!map)
  1594. return -ENOMEM;
  1595. map->session = obc_session_ref(session);
  1596. map->messages = g_hash_table_new_full(g_int64_hash, g_int64_equal, NULL,
  1597. map_msg_remove);
  1598. parse_service_record(map);
  1599. DBG("%s, instance id %d", path, map->mas_instance_id);
  1600. set_notification_registration(map, true);
  1601. if (!g_dbus_register_interface(conn, path, MAP_INTERFACE, map_methods,
  1602. NULL, NULL, map, map_free)) {
  1603. map_free(map);
  1604. return -ENOMEM;
  1605. }
  1606. return 0;
  1607. }
  1608. static void map_remove(struct obc_session *session)
  1609. {
  1610. const char *path = obc_session_get_path(session);
  1611. DBG("%s", path);
  1612. g_dbus_unregister_interface(conn, path, MAP_INTERFACE);
  1613. }
  1614. static struct obc_driver map = {
  1615. .service = "MAP",
  1616. .uuid = MAS_UUID,
  1617. .target = OBEX_MAS_UUID,
  1618. .target_len = OBEX_MAS_UUID_LEN,
  1619. .probe = map_probe,
  1620. .remove = map_remove
  1621. };
  1622. int map_init(void)
  1623. {
  1624. int err;
  1625. DBG("");
  1626. conn = dbus_bus_get(DBUS_BUS_SESSION, NULL);
  1627. if (!conn)
  1628. return -EIO;
  1629. err = obc_driver_register(&map);
  1630. if (err < 0) {
  1631. dbus_connection_unref(conn);
  1632. conn = NULL;
  1633. return err;
  1634. }
  1635. return 0;
  1636. }
  1637. void map_exit(void)
  1638. {
  1639. DBG("");
  1640. dbus_connection_unref(conn);
  1641. conn = NULL;
  1642. obc_driver_unregister(&map);
  1643. }