3 from __future__ import absolute_import, print_function, unicode_literals
5 from optparse import OptionParser
7 from pprint import pformat
10 import dbus.mainloop.glib
12 from gi.repository import GObject
14 import gobject as GObject
16 BUS_NAME='org.bluez.obex'
17 PATH = '/org/bluez/obex'
18 CLIENT_INTERFACE = 'org.bluez.obex.Client1'
19 SESSION_INTERFACE = 'org.bluez.obex.Session1'
20 MESSAGE_ACCESS_INTERFACE = 'org.bluez.obex.MessageAccess1'
21 MESSAGE_INTERFACE = 'org.bluez.obex.Message1'
22 TRANSFER_INTERFACE = 'org.bluez.obex.Transfer1'
25 """Hack to unwrap D-Bus values, so that they're easier to read when
26 printed. Taken from d-feet """
28 if isinstance(x, list):
31 if isinstance(x, tuple):
32 return tuple(map(unwrap, x))
34 if isinstance(x, dict):
35 return dict([(unwrap(k), unwrap(v)) for k, v in x.iteritems()])
37 for t in [unicode, str, long, int, float, bool]:
44 parser.add_option("-d", "--device", dest="device",
45 help="Device to connect", metavar="DEVICE")
46 parser.add_option("-c", "--chdir", dest="new_dir",
47 help="Change current directory to DIR", metavar="DIR")
48 parser.add_option("-l", "--lsdir", action="store_true", dest="ls_dir",
49 help="List folders in current directory")
50 parser.add_option("-v", "--verbose", action="store_true", dest="verbose")
51 parser.add_option("-L", "--lsmsg", action="store", dest="ls_msg",
52 help="List messages in supplied CWD subdir")
53 parser.add_option("-g", "--get", action="store", dest="get_msg",
54 help="Get message contents")
55 parser.add_option("-p", "--push", action="store", dest="push_msg",
57 parser.add_option("--get-properties", action="store", dest="get_msg_properties",
58 help="Get message properties")
59 parser.add_option("--mark-read", action="store", dest="mark_msg_read",
60 help="Marks the messages as read")
61 parser.add_option("--mark-unread", action="store", dest="mark_msg_unread",
62 help="Marks the messages as unread")
63 parser.add_option("--mark-deleted", action="store", dest="mark_msg_deleted",
64 help="Deletes the message from the folder")
65 parser.add_option("--mark-undeleted", action="store", dest="mark_msg_undeleted",
66 help="Undeletes the message")
67 parser.add_option("-u", "--update-inbox", action="store_true", dest="update_inbox",
68 help="Checks for new mails")
70 return parser.parse_args()
72 def set_folder(session, new_dir):
73 session.SetFolder(new_dir)
76 def __init__(self, session_path, verbose=False):
78 self.transfer_path = None
80 self.verbose = verbose
81 self.path = session_path
82 bus = dbus.SessionBus()
83 obj = bus.get_object(BUS_NAME, session_path)
84 self.session = dbus.Interface(obj, SESSION_INTERFACE)
85 self.map = dbus.Interface(obj, MESSAGE_ACCESS_INTERFACE)
86 bus.add_signal_receiver(self.properties_changed,
87 dbus_interface="org.freedesktop.DBus.Properties",
88 signal_name="PropertiesChanged",
91 def create_transfer_reply(self, path, properties):
92 self.transfer_path = path
93 self.props[path] = properties
95 print("Transfer created: %s (file %s)" % (path,
96 properties["Filename"]))
98 def generic_reply(self):
100 print("Operation succeeded")
102 def error(self, err):
106 def transfer_complete(self, path):
108 print("Transfer finished")
109 properties = self.props.get(path)
110 if properties == None:
112 f = open(properties["Filename"], "r")
113 os.remove(properties["Filename"])
116 def transfer_error(self, path):
117 print("Transfer %s error" % path)
120 def properties_changed(self, interface, properties, invalidated, path):
121 req = self.props.get(path)
125 if properties['Status'] == 'complete':
126 self.transfer_complete(path)
129 if properties['Status'] == 'error':
130 self.transfer_error(path)
133 def set_folder(self, new_dir):
134 self.map.SetFolder(new_dir)
136 def list_folders(self):
137 for i in self.map.ListFolders(dict()):
138 print("%s/" % (i["Name"]))
140 def list_messages(self, folder):
141 ret = self.map.ListMessages(folder, dict())
142 print(pformat(unwrap(ret)))
144 def get_message(self, handle):
145 self.map.ListMessages("", dict())
146 path = self.path + "/message" + handle
147 obj = bus.get_object(BUS_NAME, path)
148 msg = dbus.Interface(obj, MESSAGE_INTERFACE)
149 msg.Get("", True, reply_handler=self.create_transfer_reply,
150 error_handler=self.error)
152 def push_message(self, filename):
153 self.map.PushMessage(filename, "telecom/msg/outbox", dict(),
154 reply_handler=self.create_transfer_reply,
155 error_handler=self.error)
157 def get_message_properties(self, handle):
158 self.map.ListMessages("", dict())
159 path = self.path + "/message" + handle
160 obj = bus.get_object(BUS_NAME, path)
161 msg = dbus.Interface(obj, "org.freedesktop.DBus.Properties")
162 ret = msg.GetAll(MESSAGE_INTERFACE)
163 print(pformat(unwrap(ret)))
165 def set_message_property(self, handle, prop, flag):
166 self.map.ListMessages("", dict())
167 path = self.path + "/message" + handle
168 obj = bus.get_object(BUS_NAME, path)
169 msg = dbus.Interface(obj, MESSAGE_INTERFACE)
170 msg.SetProperty (prop, flag);
172 def update_inbox(self):
173 self.map.UpdateInbox()
176 if __name__ == '__main__':
178 dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
180 parser = OptionParser()
182 (options, args) = parse_options()
184 if not options.device:
188 bus = dbus.SessionBus()
189 mainloop = GObject.MainLoop()
191 client = dbus.Interface(bus.get_object(BUS_NAME, PATH),
194 print("Creating Session")
195 path = client.CreateSession(options.device, { "Target": "map" })
197 map_client = MapClient(path, options.verbose)
200 map_client.set_folder(options.new_dir)
203 map_client.list_folders()
205 if options.ls_msg is not None:
206 map_client.list_messages(options.ls_msg)
208 if options.get_msg is not None:
209 map_client.get_message(options.get_msg)
211 if options.push_msg is not None:
212 map_client.push_message(options.push_msg)
214 if options.get_msg_properties is not None:
215 map_client.get_message_properties(options.get_msg_properties)
217 if options.mark_msg_read is not None:
218 map_client.set_message_property(options.mark_msg_read, "Read", True)
220 if options.mark_msg_unread is not None:
221 map_client.set_message_property(options.mark_msg_unread, "Read", False)
223 if options.mark_msg_deleted is not None:
224 map_client.set_message_property(options.mark_msg_deleted, "Deleted", True)
226 if options.mark_msg_undeleted is not None:
227 map_client.set_message_property(options.mark_msg_undeleted, "Deleted", False)
229 if options.update_inbox:
230 map_client.update_inbox()