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 The script requires Midnight Commander 3.1+ (http://www.ibiblio.org/mc/),
11 Python 2.2+ (http://www.python.org/), OpenOBEX 1.0.1+ (http://openobex.sourceforge.net/)
12 and ObexFTP 0.10.4+ (http://triq.net/obexftp).
14 Edit the full path to the obexftp binary (see below). Put the file to the
15 /usr/[local/]lib/mc/extfs, and add a line "obexftp" to the
16 /usr/[local/]lib/mc/extfs/extfs.ini. Then create somewhere a transport file.
18 The transport file can have any name, and is expected to be a text file with at
19 least one line defining the transport to your device. Other lines in the file
22 First word in the line is a transport name - Bluetooth, IrDA or TTY. The name
25 For the Bluetooth transport put there a line "Bluetooth CP:AD:RE:SS channel",
26 where CP:AD:RE:SS is the hardware address of the device you want to connect to,
27 and channel is the OBEX File Transfer channel; you can discover the address and
28 the channel for your device by using commands like "hcitool scan" and "sdptool
31 For the TTY put a device name: "tty /dev/rfcomm0".
33 The content with the IrDA just put "IrDA" in the file.
35 Now run this "cd" command in the Midnight Commander (in the "bindings" files
36 the command is "%cd"): cd description#obexftp. The VFS script uses obexftp to
37 connect to the device and list files and directories. Plese be warned that
38 opening the VFS for the first time is VERY slow, because the script needs to
39 scan the entire cell phone's filesystem. And there must be a timeout between
40 connections, which doesn't make the scanning process faster. Midnight Commander
41 caches the result, so you can browse directories quickly.
46 __revision__ = "$Id: obexftp,v 1.6 2004/06/13 21:48:59 phd Exp $"
47 __date__ = "$Date: 2004/06/13 21:48:59 $"[7:-2]
48 __author__ = "Oleg Broytmann <phd@phd.pp.ru>"
49 __copyright__ = "Copyright (C) 2004 PhiloSoft Design"
52 # Change this to suite your needs
53 obexftp_prog = "/usr/local/obex/bin/obexftp"
58 import xml.dom.minidom
59 from tempfile import mkdtemp
63 sys.stderr.write(msg + '\n')
72 It is not a program - it is a VFS for Midnight Commander.
73 Put it in /usr/lib/mc/extfs.""")
76 def setup_transport():
77 """Setup transport parameters for the obexftp program"""
78 transport_file = open(sys.argv[2], 'r')
79 line = transport_file.readline().strip()
80 transport_file.close()
83 transport = parts[0].lower()
85 if transport == "bluetooth":
86 return ' '.join(["-b", parts[1], "-B", parts[2]])
87 elif transport == "tty":
88 return ' '.join(["-t", parts[1]])
89 elif transport == "irda":
92 error("Unknown transport '%s'; expected 'bluetooth', 'tty' or 'irda'" % base_filename)
95 # Parse ObexFTP XML directory listings
97 class DirectoryEntry(object):
98 def __init__(self, type):
102 self.perm = "-rw-rw-rw-"
103 elif type == "folder":
104 self.perm = "drwxrwxrwx"
106 raise ValueError, "unknown type '%s'; expected 'file' or 'folder'" % self.type
109 if not hasattr(self, "modified"): # telecom
110 return "01-01-70 0:0"
111 date, time = self.modified.split('T')
112 year, month, day = date[2:4], date[4:6], date[6:8]
113 hour, minute = time[:2], time[2:4]
114 return "%s-%s-%s %s:%s" % (month, day, year, hour, minute)
115 mtime = property(mtime)
118 if self.type == "file":
119 return """<%s: type=file, name=%s, size=%s, mtime=%s at 0x%x>""" % (
120 self.__class__.__name__, self.name, self.size, self.mtime, id(self)
122 if self.type == "folder":
123 if hasattr(self, "modified"):
124 return """<%s: type=directory, name=%s, mtime=%s at 0x%x>""" % (
125 self.__class__.__name__, self.name, self.mtime, id(self)
128 return """<%s: type=directory, name=%s at 0x%x>""" % (
129 self.__class__.__name__, self.name, id(self)
131 raise ValueError, "unknown type '%s'; expected 'file' or 'folder'" % self.type
133 def get_entries(dom, tag):
135 for subtag in dom.getElementsByTagName(tag):
136 entry = DirectoryEntry(tag)
137 attrs = subtag.attributes
138 for i in range(attrs.length):
140 setattr(entry, attr.name, attr.value)
141 entries.append(entry)
145 def recursive_list(obexftp_args, directory):
146 """List the directory recursively"""
147 pipe = os.popen("%s %s -l '%s' 2>/dev/null" % (obexftp_prog, obexftp_args, directory), 'r')
148 listing = pipe.read()
154 dom = xml.dom.minidom.parseString(listing)
155 directories = get_entries(dom, "folder")
156 files = get_entries(dom, "file")
158 for entry in directories + files:
159 fullpath = "%s/%s" % (directory, entry.name)
160 if fullpath.startswith('//'): fullpath = fullpath[1:]
161 print entry.perm, "1 user group", entry.size, entry.mtime, fullpath
163 for entry in directories:
164 fullpath = "%s/%s" % (directory, entry.name)
165 if fullpath.startswith('//'): fullpath = fullpath[1:]
167 recursive_list(obexftp_args, fullpath)
170 """List the entire VFS"""
171 obexftp_args = setup_transport()
172 recursive_list(obexftp_args, '/')
175 # A unique directory for temporary files
181 tmpdir_name = mkdtemp(".tmp", "mcobex-")
182 os.chdir(tmpdir_name)
184 def cleanup_tmpdir():
186 shutil.rmtree(tmpdir_name)
189 def mcobex_copyout():
190 """Get a file from the VFS"""
191 obexftp_args = setup_transport()
192 obex_filename = sys.argv[3]
193 real_filename = sys.argv[4]
196 os.system("%s %s -g '%s' 2>/dev/null" % (obexftp_prog, obexftp_args, obex_filename))
198 os.rename(os.path.basename(obex_filename), real_filename)
205 """Put a file to the VFS"""
206 obexftp_args = setup_transport()
207 obex_filename = sys.argv[3]
208 real_filename = sys.argv[4]
209 dirname, filename = os.path.split(obex_filename)
212 os.rename(real_filename, filename)
213 os.system("%s %s -c '%s' -p '%s' 2>/dev/null" % (obexftp_prog, obexftp_args,
216 os.rename(filename, real_filename) # by some reason MC wants the file back
221 """Remove a file from the VFS"""
222 obexftp_args = setup_transport()
223 obex_filename = sys.argv[3]
226 os.system("%s %s -k '%s' 2>/dev/null" % (obexftp_prog, obexftp_args, obex_filename))
231 """Create a directory in the VFS"""
232 obexftp_args = setup_transport()
233 obex_dirname = sys.argv[3]
236 os.system("%s %s -C '%s' 2>/dev/null" % (obexftp_prog, obexftp_args, obex_dirname))
240 mcobex_rmdir = mcobex_rm
244 command = sys.argv[1]
245 procname = "mcobex_" + command
247 if not g.has_key(procname):
248 error("Unknown command %s" % command)