map-client 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. #!/usr/bin/python
  2. # SPDX-License-Identifier: LGPL-2.1-or-later
  3. from __future__ import absolute_import, print_function, unicode_literals
  4. from optparse import OptionParser
  5. import os
  6. from pprint import pformat
  7. import sys
  8. import dbus
  9. import dbus.mainloop.glib
  10. try:
  11. from gi.repository import GObject
  12. except ImportError:
  13. import gobject as GObject
  14. BUS_NAME='org.bluez.obex'
  15. PATH = '/org/bluez/obex'
  16. CLIENT_INTERFACE = 'org.bluez.obex.Client1'
  17. SESSION_INTERFACE = 'org.bluez.obex.Session1'
  18. MESSAGE_ACCESS_INTERFACE = 'org.bluez.obex.MessageAccess1'
  19. MESSAGE_INTERFACE = 'org.bluez.obex.Message1'
  20. TRANSFER_INTERFACE = 'org.bluez.obex.Transfer1'
  21. def unwrap(x):
  22. """Hack to unwrap D-Bus values, so that they're easier to read when
  23. printed. Taken from d-feet """
  24. if isinstance(x, list):
  25. return map(unwrap, x)
  26. if isinstance(x, tuple):
  27. return tuple(map(unwrap, x))
  28. if isinstance(x, dict):
  29. return dict([(unwrap(k), unwrap(v)) for k, v in x.iteritems()])
  30. for t in [unicode, str, long, int, float, bool]:
  31. if isinstance(x, t):
  32. return t(x)
  33. return x
  34. def parse_options():
  35. parser.add_option("-d", "--device", dest="device",
  36. help="Device to connect", metavar="DEVICE")
  37. parser.add_option("-c", "--chdir", dest="new_dir",
  38. help="Change current directory to DIR", metavar="DIR")
  39. parser.add_option("-l", "--lsdir", action="store_true", dest="ls_dir",
  40. help="List folders in current directory")
  41. parser.add_option("-v", "--verbose", action="store_true", dest="verbose")
  42. parser.add_option("-L", "--lsmsg", action="store", dest="ls_msg",
  43. help="List messages in supplied CWD subdir")
  44. parser.add_option("-g", "--get", action="store", dest="get_msg",
  45. help="Get message contents")
  46. parser.add_option("-p", "--push", action="store", dest="push_msg",
  47. help="Push message")
  48. parser.add_option("--get-properties", action="store", dest="get_msg_properties",
  49. help="Get message properties")
  50. parser.add_option("--mark-read", action="store", dest="mark_msg_read",
  51. help="Marks the messages as read")
  52. parser.add_option("--mark-unread", action="store", dest="mark_msg_unread",
  53. help="Marks the messages as unread")
  54. parser.add_option("--mark-deleted", action="store", dest="mark_msg_deleted",
  55. help="Deletes the message from the folder")
  56. parser.add_option("--mark-undeleted", action="store", dest="mark_msg_undeleted",
  57. help="Undeletes the message")
  58. parser.add_option("-u", "--update-inbox", action="store_true", dest="update_inbox",
  59. help="Checks for new mails")
  60. return parser.parse_args()
  61. def set_folder(session, new_dir):
  62. session.SetFolder(new_dir)
  63. class MapClient:
  64. def __init__(self, session_path, verbose=False):
  65. self.progress = 0
  66. self.transfer_path = None
  67. self.props = dict()
  68. self.verbose = verbose
  69. self.path = session_path
  70. bus = dbus.SessionBus()
  71. obj = bus.get_object(BUS_NAME, session_path)
  72. self.session = dbus.Interface(obj, SESSION_INTERFACE)
  73. self.map = dbus.Interface(obj, MESSAGE_ACCESS_INTERFACE)
  74. bus.add_signal_receiver(self.properties_changed,
  75. dbus_interface="org.freedesktop.DBus.Properties",
  76. signal_name="PropertiesChanged",
  77. path_keyword="path")
  78. def create_transfer_reply(self, path, properties):
  79. self.transfer_path = path
  80. self.props[path] = properties
  81. if self.verbose:
  82. print("Transfer created: %s (file %s)" % (path,
  83. properties["Filename"]))
  84. def generic_reply(self):
  85. if self.verbose:
  86. print("Operation succeeded")
  87. def error(self, err):
  88. print(err)
  89. mainloop.quit()
  90. def transfer_complete(self, path):
  91. if self.verbose:
  92. print("Transfer finished")
  93. properties = self.props.get(path)
  94. if properties == None:
  95. return
  96. f = open(properties["Filename"], "r")
  97. os.remove(properties["Filename"])
  98. print(f.readlines())
  99. def transfer_error(self, path):
  100. print("Transfer %s error" % path)
  101. mainloop.quit()
  102. def properties_changed(self, interface, properties, invalidated, path):
  103. req = self.props.get(path)
  104. if req == None:
  105. return
  106. if properties['Status'] == 'complete':
  107. self.transfer_complete(path)
  108. return
  109. if properties['Status'] == 'error':
  110. self.transfer_error(path)
  111. return
  112. def set_folder(self, new_dir):
  113. self.map.SetFolder(new_dir)
  114. def list_folders(self):
  115. for i in self.map.ListFolders(dict()):
  116. print("%s/" % (i["Name"]))
  117. def list_messages(self, folder):
  118. ret = self.map.ListMessages(folder, dict())
  119. print(pformat(unwrap(ret)))
  120. def get_message(self, handle):
  121. self.map.ListMessages("", dict())
  122. path = self.path + "/message" + handle
  123. obj = bus.get_object(BUS_NAME, path)
  124. msg = dbus.Interface(obj, MESSAGE_INTERFACE)
  125. msg.Get("", True, reply_handler=self.create_transfer_reply,
  126. error_handler=self.error)
  127. def push_message(self, filename):
  128. self.map.PushMessage(filename, "telecom/msg/outbox", dict(),
  129. reply_handler=self.create_transfer_reply,
  130. error_handler=self.error)
  131. def get_message_properties(self, handle):
  132. self.map.ListMessages("", dict())
  133. path = self.path + "/message" + handle
  134. obj = bus.get_object(BUS_NAME, path)
  135. msg = dbus.Interface(obj, "org.freedesktop.DBus.Properties")
  136. ret = msg.GetAll(MESSAGE_INTERFACE)
  137. print(pformat(unwrap(ret)))
  138. def set_message_property(self, handle, prop, flag):
  139. self.map.ListMessages("", dict())
  140. path = self.path + "/message" + handle
  141. obj = bus.get_object(BUS_NAME, path)
  142. msg = dbus.Interface(obj, MESSAGE_INTERFACE)
  143. msg.SetProperty (prop, flag);
  144. def update_inbox(self):
  145. self.map.UpdateInbox()
  146. if __name__ == '__main__':
  147. dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
  148. parser = OptionParser()
  149. (options, args) = parse_options()
  150. if not options.device:
  151. parser.print_help()
  152. exit(0)
  153. bus = dbus.SessionBus()
  154. mainloop = GObject.MainLoop()
  155. client = dbus.Interface(bus.get_object(BUS_NAME, PATH),
  156. CLIENT_INTERFACE)
  157. print("Creating Session")
  158. path = client.CreateSession(options.device, { "Target": "map" })
  159. map_client = MapClient(path, options.verbose)
  160. if options.new_dir:
  161. map_client.set_folder(options.new_dir)
  162. if options.ls_dir:
  163. map_client.list_folders()
  164. if options.ls_msg is not None:
  165. map_client.list_messages(options.ls_msg)
  166. if options.get_msg is not None:
  167. map_client.get_message(options.get_msg)
  168. if options.push_msg is not None:
  169. map_client.push_message(options.push_msg)
  170. if options.get_msg_properties is not None:
  171. map_client.get_message_properties(options.get_msg_properties)
  172. if options.mark_msg_read is not None:
  173. map_client.set_message_property(options.mark_msg_read, "Read", True)
  174. if options.mark_msg_unread is not None:
  175. map_client.set_message_property(options.mark_msg_unread, "Read", False)
  176. if options.mark_msg_deleted is not None:
  177. map_client.set_message_property(options.mark_msg_deleted, "Deleted", True)
  178. if options.mark_msg_undeleted is not None:
  179. map_client.set_message_property(options.mark_msg_undeleted, "Deleted", False)
  180. if options.update_inbox:
  181. map_client.update_inbox()
  182. mainloop.run()