From: Oleg Broytman Date: Sun, 13 Jun 2004 13:27:47 +0000 (+0000) Subject: ObexFTP VFS for Midnight Commander. Manipulate a cell phone's filesystem using obexftp. X-Git-Url: https://git.phdru.name/?p=extfs.d.git;a=commitdiff_plain;h=70b0cfc9f83c030262eba602cc295555e571c6ca ObexFTP VFS for Midnight Commander. Manipulate a cell phone's filesystem using obexftp. git-svn-id: file:///home/phd/archive/SVN/mc-extfs/trunk@9 1a6e6372-1aea-0310-bd00-dc960550e1df --- diff --git a/obexftp b/obexftp new file mode 100755 index 0000000..9d69a20 --- /dev/null +++ b/obexftp @@ -0,0 +1,237 @@ +#! /usr/local/bin/python -O + +""" +ObexFTP VFS for Midnight Commander. Manipulate a cell phone's filesystem using obexftp. + +Author: Oleg BroytMann . +Copyright (C) 2004 PhiloSoft Design. +License: GPL. + +To use it install OpenOBEX (http://openobex.sourceforge.net/) and ObexFTP +(http://triq.net/obexftp) and edit the full path to the obexftp binary. + +Put the file to the /usr/[local/]lib/mc/extfs, and add a line "obexftp" to the +/usr/[local/]lib/mc/extfs/extfs.ini. Then create somewhere a file called +"irda", "bluetooth" or "tty" to connect to the device using IrDA, Bluetooth or +TTY transport. + +For the "bluetooth" put there a line "CP:AD:RE:SS channel", where CP:AD:RE:SS +is the hardware address of the device you want to connect to, and channel is +the OBEX File Transfer channel; you can discover the address and the channel +for your device by using commands like "hcitool scan" and "sdptool browse". +Other lines in the file are ignored. + +Put a device name like /dev/rfcomm0 into the "tty" file. + +The content for the "irda" file is ignored. + +Now run this "cd" command in the Midnight Commander (in the "bindings" files +the command is "%cd"): cd bluetooth#obexftp. The VFS script use obexftp to try +to connect to the device and list files and directories. It could be very slow... + +""" + +__version__ = "0.1.0" +__revision__ = "$Id: obexftp,v 1.1 2004/06/13 13:27:47 phd Exp $" +__date__ = "$Date: 2004/06/13 13:27:47 $"[7:-2] +__author__ = "Oleg Broytmann " +__copyright__ = "Copyright (C) 2004 PhiloSoft Design" + + +obexftp_prog = "/usr/local/obex/bin/obexftp" + + +import sys, os +import xml.dom.minidom + +def log_error(msg): + sys.stderr.write(msg + '\n') + +def error(msg): + log_error(msg + '\n') + sys.exit(1) + + +if len(sys.argv) < 2: + error("""\ +It is not a program - it is a VFS for Midnight Commander. +Put it in /usr/lib/mc/extfs.""") + + +def setup_transport(): + """Setup transport parameters for the obexftp program""" + transport_filename = sys.argv[2] + base_filename = os.path.basename(transport_filename) + + if base_filename == "bluetooth": + transport_file = open(transport_filename, 'r') + line = transport_file.readline().strip() + transport_file.close() + bdaddr, channel = line.split() + return ' '.join(["-b", bdaddr, "-B", channel]) + elif base_filename == "tty": + transport_file = open(transport_filename, 'r') + device = transport_file.readline().strip() + transport_file.close() + return ' '.join(["-t", device]) + elif base_filename == "irda": + return ' '.join(["-i"]) + else: + error("Unknown transport '%s'; expected 'bluetooth', 'tty' or 'irda'" % base_filename) + + +# Parse ObexFTP XML directory listings + +class DirectoryEntry(object): + def __init__(self, type): + self.type = type + self.size = 0 + if type == "file": + self.perm = "-rw-rw-rw-" + elif type == "folder": + self.perm = "drw-rw-rw-" + else: + raise ValueError, "unknown type '%s'; expected 'file' or 'folder'" % self.type + + def mtime(self): + if not hasattr(self, "modified"): # telecom + return "01-01-70 0:0" + date, time = self.modified.split('T') + year, month, day = date[2:4], date[4:6], date[6:8] + hour, minute = time[:2], time[2:4] + return "%s-%s-%s %s:%s" % (month, day, year, hour, minute) + mtime = property(mtime) + + def __repr__(self): + if self.type == "file": + return """<%s: type=file, name=%s, size=%s, mtime=%s at 0x%x>""" % ( + self.__class__.__name__, self.name, self.size, self.mtime, id(self) + ) + if self.type == "folder": + if hasattr(self, "modified"): + return """<%s: type=directory, name=%s, mtime=%s at 0x%x>""" % ( + self.__class__.__name__, self.name, self.mtime, id(self) + ) + else: # telecom + return """<%s: type=directory, name=%s at 0x%x>""" % ( + self.__class__.__name__, self.name, id(self) + ) + raise ValueError, "unknown type '%s'; expected 'file' or 'folder'" % self.type + +def get_entries(dom, tag): + entries = [] + for subtag in dom.getElementsByTagName(tag): + entry = DirectoryEntry(tag) + attrs = subtag.attributes + for i in range(attrs.length): + attr = attrs.item(i) + setattr(entry, attr.name, attr.value) + entries.append(entry) + return entries + + +def _recursive_list(obexftp_args, directory): + """List the directory recursively""" + pipe = os.popen("%s %s -l '%s' 2>/dev/null" % (obexftp_prog, obexftp_args, directory), 'r') + listing = pipe.read() + pipe.close() + + if not listing: + return + + try: + dom = xml.dom.minidom.parseString(listing) + except: + obex_xml = open("obex.xml", 'a') + obex_xml.write(listing) + obex_xml.close() + raise + + directories = get_entries(dom, "folder") + files = get_entries(dom, "file") + + prefix = directory[1:] # omit leading slash + debug = open("debug", 'a') + for entry in directories + files: + print >>debug, entry.perm, "1 user group", entry.size, entry.mtime, "%s/%s" % (prefix, entry.name) + print entry.perm, "1 user group", entry.size, entry.mtime, "%s/%s" % (prefix, entry.name) + debug.close() + + for entry in directories: + _recursive_list(obexftp_args, "%s/%s" % (directory, entry.name)) + +def mcobex_list(): + """List the entire VFS""" + obexftp_args = setup_transport() + _recursive_list(obexftp_args, '/') + + +def mcobex_copyout(): + """Get a file from the VFS""" + obexftp_args = setup_transport() + dummy_filename = sys.argv[3] + real_filename = sys.argv[4] + + real_file = open(real_filename, 'w') + real_file.write("Copied from %s\n" % dummy_filename) + real_file.write("Copied to %s\n" % real_filename) + real_file.close() + + +def mcobex_copyin(): + """Put a file to the VFS""" + obexftp_args = setup_transport() + dummy_filename = sys.argv[3] + real_filename = sys.argv[4] + + real_file = open(real_filename + "-dummy.tmp", 'w') + real_file.write("Copied from %s\n" % real_filename) + real_file.write("Copied to %s\n" % dummy_filename) + real_file.close() + + +def mcobex_rm(): + """Remove a file from the VFS""" + obexftp_args = setup_transport() + dummy_filename = sys.argv[3] + + real_file = open(".dummy.tmp", 'a') + real_file.write("Remove %s\n" % dummy_filename) + real_file.close() + + +def mcobex_mkdir(): + """Create a directory in the VFS""" + obexftp_args = setup_transport() + dummy_dirname = sys.argv[3] + + real_file = open(".dummy.tmp", 'a') + real_file.write("Create %s\n" % dummy_dirname) + real_file.close() + + +def mcobex_rmdir(): + """Remove a directory from the VFS""" + obexftp_args = setup_transport() + dummy_dirname = sys.argv[3] + + real_file = open(".dummy.tmp", 'a') + real_file.write("Remove %s\n" % dummy_dirname) + real_file.close() + + +g = globals() +command = sys.argv[1] +procname = "mcobex_" + command + +if not g.has_key(procname): + error("Unknown command %s" % command) + +try: + g[procname]() +except: + import traceback + error = open("error", 'a') + traceback.print_exc(file=error) + error.close() + sys.exit(1)