Below is the file 'gtktftp.py' from this revision. You can also download the file.
#!/usr/bin/env python # Wraps my python TFTP server in a the Gtk main loop, with # classes that subclass gobject (and thus emit sensible # signals) import pygtk pygtk.require('2.0') import gobject import gtk import tftp class gTFTPServer(gobject.GObject): __gproperties__ = { } __gsignals__ = { 'data-received' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_INT)), 'data-sent' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_INT)), 'file-received' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_STRING, gobject.TYPE_STRING)), 'file-sent' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_STRING, gobject.TYPE_STRING)), 'error-received' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_STRING, gobject.TYPE_INT, gobject.TYPE_STRING)), 'error-sent' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_STRING, gobject.TYPE_INT, gobject.TYPE_STRING)), } def __init__(self, port=69): gobject.GObject.__init__(self) self.tags = {} self.port = port io = tftp.TFTPIOFunctions(self.set_read, self.set_write, self.clear_read, self.clear_write, self.set_timeout, self.remove_timeout, self.notify, self.authenticate) self.tftp = tftp.TFTPServer(io, port=self.port, verbose=False) def update_io(self, fd, watch, func, user_data): tag = gobject.io_add_watch(fd, watch, func, user_data) if not self.tags.has_key(fd): self.tags[fd] = [] self.tags[fd].append((watch, tag)) def clear_io(self, fd, watch): if not self.tags.has_key(fd): return tags = self.tags[fd] if watch: tags = filter(lambda x: x[0] == watch, tags) map(lambda x: gobject.source_remove(x[1]), tags) def set_read(self, fd, func, user_data=None): self.update_io(fd.fileno(), gobject.IO_IN, func, user_data) def clear_read(self, fd): self.clear_io(fd.fileno(), gobject.IO_IN) def clear_write(self, fd): self.clear_io(fd.fileno(), gobject.IO_OUT) def set_write(self, fd, func, user_data=None): self.update_io(fd.fileno(), gobject.IO_OUT, func, user_data) def set_timeout(self, time, func, user_data=None): return gobject.timeout_add(3000, func, user_data) def remove_timeout(self, tag): return gobject.source_remove(tag) def notify(self, name, tpl): if name == "data_received" or name == "data_sent": addr_tpl, filename, bytes = tpl self.emit(name, addr_tpl[0], filename, bytes) elif name == "file_sent" or name == "file_received": addr_tpl, filename = tpl self.emit(name, addr_tpl[0], filename) elif name == "error_sent" or name == "error_received": addr_tpl, code, mesg = tpl self.emit(name, addr_tpl[0], code, mesg) else: print name, tpl def authenticate(self, request, client_addr, filename): if request == "WRQ": dialog = gtk.Dialog(title="Accept file upload?", parent=None, flags=gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT, buttons=(gtk.STOCK_NO,gtk.RESPONSE_NO, gtk.STOCK_YES, gtk.RESPONSE_YES)) label = gtk.Label('<span size="large" weight="bold">The host "%s" is attempting to upload a file: "%s"</span>\n\nDo you wish to accept?' % (client_addr[0], filename)) label.set_use_markup(True) dialog.set_has_separator(False) dialog.set_border_width(12) dialog.vbox.pack_start(label, True, True, 0) label.show() response = dialog.run() dialog.destroy() return response == gtk.RESPONSE_YES elif request == "RRQ": return True # for now we don't need access control; if it's exported, it is exported to all # better to have some UI where you can specify a list of hosts really. # many clients will ask for the same file several times (esp. with timeouts.) else: return False gobject.type_register(gTFTPServer)