1 #! /usr/local/bin/python -O
4 ObexFTP VFS for Midnight Commander. Manipulate a cell phone's filesystem using obexftp.
6 Author: Oleg BroytMann <phd@phd.pp.ru>.
7 Copyright (C) 2004 PhiloSoft Design.
10 To use it install OpenOBEX (http://openobex.sourceforge.net/) and ObexFTP
11 (http://triq.net/obexftp) and edit the full path to the obexftp binary.
13 Put the file to the /usr/[local/]lib/mc/extfs, and add a line "obexftp" to the
14 /usr/[local/]lib/mc/extfs/extfs.ini. Then create somewhere a file called
15 "irda", "bluetooth" or "tty" to connect to the device using IrDA, Bluetooth or
18 For the "bluetooth" put there a line "CP:AD:RE:SS channel", where CP:AD:RE:SS
19 is the hardware address of the device you want to connect to, and channel is
20 the OBEX File Transfer channel; you can discover the address and the channel
21 for your device by using commands like "hcitool scan" and "sdptool browse".
22 Other lines in the file are ignored.
24 Put a device name like /dev/rfcomm0 into the "tty" file.
26 The content for the "irda" file is ignored.
28 Now run this "cd" command in the Midnight Commander (in the "bindings" files
29 the command is "%cd"): cd bluetooth#obexftp. The VFS script use obexftp to try
30 to connect to the device and list files and directories. It could be very slow...
35 __revision__ = "$Id: obexftp,v 1.1 2004/06/13 13:27:47 phd Exp $"
36 __date__ = "$Date: 2004/06/13 13:27:47 $"[7:-2]
37 __author__ = "Oleg Broytmann <phd@phd.pp.ru>"
38 __copyright__ = "Copyright (C) 2004 PhiloSoft Design"
41 obexftp_prog = "/usr/local/obex/bin/obexftp"
45 import xml.dom.minidom
48 sys.stderr.write(msg + '\n')
57 It is not a program - it is a VFS for Midnight Commander.
58 Put it in /usr/lib/mc/extfs.""")
61 def setup_transport():
62 """Setup transport parameters for the obexftp program"""
63 transport_filename = sys.argv[2]
64 base_filename = os.path.basename(transport_filename)
66 if base_filename == "bluetooth":
67 transport_file = open(transport_filename, 'r')
68 line = transport_file.readline().strip()
69 transport_file.close()
70 bdaddr, channel = line.split()
71 return ' '.join(["-b", bdaddr, "-B", channel])
72 elif base_filename == "tty":
73 transport_file = open(transport_filename, 'r')
74 device = transport_file.readline().strip()
75 transport_file.close()
76 return ' '.join(["-t", device])
77 elif base_filename == "irda":
78 return ' '.join(["-i"])
80 error("Unknown transport '%s'; expected 'bluetooth', 'tty' or 'irda'" % base_filename)
83 # Parse ObexFTP XML directory listings
85 class DirectoryEntry(object):
86 def __init__(self, type):
90 self.perm = "-rw-rw-rw-"
91 elif type == "folder":
92 self.perm = "drw-rw-rw-"
94 raise ValueError, "unknown type '%s'; expected 'file' or 'folder'" % self.type
97 if not hasattr(self, "modified"): # telecom
99 date, time = self.modified.split('T')
100 year, month, day = date[2:4], date[4:6], date[6:8]
101 hour, minute = time[:2], time[2:4]
102 return "%s-%s-%s %s:%s" % (month, day, year, hour, minute)
103 mtime = property(mtime)
106 if self.type == "file":
107 return """<%s: type=file, name=%s, size=%s, mtime=%s at 0x%x>""" % (
108 self.__class__.__name__, self.name, self.size, self.mtime, id(self)
110 if self.type == "folder":
111 if hasattr(self, "modified"):
112 return """<%s: type=directory, name=%s, mtime=%s at 0x%x>""" % (
113 self.__class__.__name__, self.name, self.mtime, id(self)
116 return """<%s: type=directory, name=%s at 0x%x>""" % (
117 self.__class__.__name__, self.name, id(self)
119 raise ValueError, "unknown type '%s'; expected 'file' or 'folder'" % self.type
121 def get_entries(dom, tag):
123 for subtag in dom.getElementsByTagName(tag):
124 entry = DirectoryEntry(tag)
125 attrs = subtag.attributes
126 for i in range(attrs.length):
128 setattr(entry, attr.name, attr.value)
129 entries.append(entry)
133 def _recursive_list(obexftp_args, directory):
134 """List the directory recursively"""
135 pipe = os.popen("%s %s -l '%s' 2>/dev/null" % (obexftp_prog, obexftp_args, directory), 'r')
136 listing = pipe.read()
143 dom = xml.dom.minidom.parseString(listing)
145 obex_xml = open("obex.xml", 'a')
146 obex_xml.write(listing)
150 directories = get_entries(dom, "folder")
151 files = get_entries(dom, "file")
153 prefix = directory[1:] # omit leading slash
154 debug = open("debug", 'a')
155 for entry in directories + files:
156 print >>debug, entry.perm, "1 user group", entry.size, entry.mtime, "%s/%s" % (prefix, entry.name)
157 print entry.perm, "1 user group", entry.size, entry.mtime, "%s/%s" % (prefix, entry.name)
160 for entry in directories:
161 _recursive_list(obexftp_args, "%s/%s" % (directory, entry.name))
164 """List the entire VFS"""
165 obexftp_args = setup_transport()
166 _recursive_list(obexftp_args, '/')
169 def mcobex_copyout():
170 """Get a file from the VFS"""
171 obexftp_args = setup_transport()
172 dummy_filename = sys.argv[3]
173 real_filename = sys.argv[4]
175 real_file = open(real_filename, 'w')
176 real_file.write("Copied from %s\n" % dummy_filename)
177 real_file.write("Copied to %s\n" % real_filename)
182 """Put a file to the VFS"""
183 obexftp_args = setup_transport()
184 dummy_filename = sys.argv[3]
185 real_filename = sys.argv[4]
187 real_file = open(real_filename + "-dummy.tmp", 'w')
188 real_file.write("Copied from %s\n" % real_filename)
189 real_file.write("Copied to %s\n" % dummy_filename)
194 """Remove a file from the VFS"""
195 obexftp_args = setup_transport()
196 dummy_filename = sys.argv[3]
198 real_file = open(".dummy.tmp", 'a')
199 real_file.write("Remove %s\n" % dummy_filename)
204 """Create a directory in the VFS"""
205 obexftp_args = setup_transport()
206 dummy_dirname = sys.argv[3]
208 real_file = open(".dummy.tmp", 'a')
209 real_file.write("Create %s\n" % dummy_dirname)
214 """Remove a directory from the VFS"""
215 obexftp_args = setup_transport()
216 dummy_dirname = sys.argv[3]
218 real_file = open(".dummy.tmp", 'a')
219 real_file.write("Remove %s\n" % dummy_dirname)
224 command = sys.argv[1]
225 procname = "mcobex_" + command
227 if not g.has_key(procname):
228 error("Unknown command %s" % command)
234 error = open("error", 'a')
235 traceback.print_exc(file=error)