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.7 2004/06/13 22:04:56 phd Exp $"
47 __date__ = "$Date: 2004/06/13 22:04:56 $"[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. For more information read the source!""")
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 """Represent remote files and directories"""
100 def __init__(self, type):
104 self.perm = "-rw-rw-rw-"
105 elif type == "folder":
106 self.perm = "drwxrwxrwx"
108 raise ValueError, "unknown type '%s'; expected 'file' or 'folder'" % self.type
111 if not hasattr(self, "modified"): # telecom
112 return "01-01-70 0:0"
113 date, time = self.modified.split('T')
114 year, month, day = date[2:4], date[4:6], date[6:8]
115 hour, minute = time[:2], time[2:4]
116 return "%s-%s-%s %s:%s" % (month, day, year, hour, minute)
117 mtime = property(mtime)
120 if self.type == "file":
121 return """<%s: type=file, name=%s, size=%s, mtime=%s at 0x%x>""" % (
122 self.__class__.__name__, self.name, self.size, self.mtime, id(self)
124 if self.type == "folder":
125 if hasattr(self, "modified"):
126 return """<%s: type=directory, name=%s, mtime=%s at 0x%x>""" % (
127 self.__class__.__name__, self.name, self.mtime, id(self)
130 return """<%s: type=directory, name=%s at 0x%x>""" % (
131 self.__class__.__name__, self.name, id(self)
133 raise ValueError, "unknown type '%s'; expected 'file' or 'folder'" % self.type
135 def get_entries(dom, type):
137 for obj in dom.getElementsByTagName(type):
138 entry = DirectoryEntry(type)
139 attrs = obj.attributes
140 for i in range(attrs.length):
142 setattr(entry, attr.name, attr.value)
143 entries.append(entry)
147 def recursive_list(obexftp_args, directory):
148 """List the directory recursively"""
149 pipe = os.popen("%s %s -l '%s' 2>/dev/null" % (obexftp_prog, obexftp_args, directory), 'r')
150 listing = pipe.read()
156 dom = xml.dom.minidom.parseString(listing)
157 directories = get_entries(dom, "folder")
158 files = get_entries(dom, "file")
160 for entry in directories + files:
161 fullpath = "%s/%s" % (directory, entry.name)
162 if fullpath.startswith('//'): fullpath = fullpath[1:]
163 print entry.perm, "1 user group", entry.size, entry.mtime, fullpath
165 for entry in directories:
166 fullpath = "%s/%s" % (directory, entry.name)
167 if fullpath.startswith('//'): fullpath = fullpath[1:]
169 recursive_list(obexftp_args, fullpath)
172 """List the entire VFS"""
173 obexftp_args = setup_transport()
174 recursive_list(obexftp_args, '/')
177 # A unique directory for temporary files
183 tmpdir_name = mkdtemp(".tmp", "mcobex-")
184 os.chdir(tmpdir_name)
186 def cleanup_tmpdir():
188 shutil.rmtree(tmpdir_name)
191 def mcobex_copyout():
192 """Get a file from the VFS"""
193 obexftp_args = setup_transport()
194 obex_filename = sys.argv[3]
195 real_filename = sys.argv[4]
198 os.system("%s %s -g '%s' 2>/dev/null" % (obexftp_prog, obexftp_args, obex_filename))
200 os.rename(os.path.basename(obex_filename), real_filename)
207 """Put a file to the VFS"""
208 obexftp_args = setup_transport()
209 obex_filename = sys.argv[3]
210 real_filename = sys.argv[4]
211 dirname, filename = os.path.split(obex_filename)
214 os.rename(real_filename, filename)
215 os.system("%s %s -c '%s' -p '%s' 2>/dev/null" % (obexftp_prog, obexftp_args,
218 os.rename(filename, real_filename) # by some reason MC wants the file back
223 """Remove a file from the VFS"""
224 obexftp_args = setup_transport()
225 obex_filename = sys.argv[3]
226 os.system("%s %s -k '%s' 2>/dev/null" % (obexftp_prog, obexftp_args, obex_filename))
230 """Create a directory in the VFS"""
231 obexftp_args = setup_transport()
232 obex_dirname = sys.argv[3]
233 os.system("%s %s -C '%s' 2>/dev/null" % (obexftp_prog, obexftp_args, obex_dirname))
236 mcobex_rmdir = mcobex_rm
240 command = sys.argv[1]
241 procname = "mcobex_" + command
243 if not g.has_key(procname):
244 error("Unknown command %s" % command)