#!/usr/bin/python # # Bluetooth PIN helper # Written by Maxim Krasnyansky # import sys, os, string, popen2, pygtk pygtk.require('2.0') # X Display initialization. # Find running X Server and parse its arguments. # Set environment variables DISPLAY and XAUTHORITY # using info extracted from X Server args. # def set_display(): disp = ":0" auth = "" proc = "-C X -C XFree86" ps = "/bin/ps " + proc + " --format args --no-headers" r,w = popen2.popen2(ps) arg = string.split(r.read()) for i in range(1, len(arg)): if arg[i][0] != '-' and i==1: disp = arg[i] elif arg[i] == "-auth": auth = arg[i+1] break os.environ['DISPLAY'] = disp os.environ['XAUTHORITY'] = auth # Set X display before initializing GTK set_display() # Some versions of fontconfig will segfault if HOME isn't set. os.environ['HOME'] = "" import gtk # Dialog Class DLG_OK = 1 DLG_CANCEL = 2 class Dialog(gtk.Dialog): result = DLG_CANCEL args = {} def __init__(self, modal=gtk.FALSE, mesg=None, args = {}): gtk.Dialog.__init__(self) self.args = args self.set_modal(modal) # self.set_usize(400, 0) # self.set_uposition(300,300) self.connect("destroy", self.quit) self.connect("delete_event", self.quit) self.action_area.set_border_width(2) ok = gtk.Button("Accept") ok.connect("clicked", self.ok) self.action_area.pack_start(ok, padding = 20) ok.show() cl = gtk.Button("Reject") cl.connect("clicked", self.cancel) self.action_area.pack_start(cl, padding = 20) cl.show() if mesg: msg = gtk.Label("") msg.set_text(mesg) self.vbox.pack_start(msg, padding = 10) msg.show() self.ents = [] for k in self.args.keys(): hbox = gtk.HBox() hbox.set_border_width(5) self.vbox.pack_start(hbox) hbox.show() l = gtk.Label("") e = gtk.Entry() l.set_text( k ) e.set_text( self.args[k] ) e.connect("key_press_event", self.key_press) hbox.pack_start(l, padding = 10, expand = gtk.FALSE) hbox.pack_start(e) l.show() e.show() self.ents.append( (k, e) ) self.ents[0][1].grab_focus() def key_press(self, entry, event): if event.keyval == gtk.keysyms.Return: entry.emit_stop_by_name("key_press_event") self.ok() elif event.keyval == gtk.keysyms.Escape: entry.emit_stop_by_name("key_press_event") self.cancel() def ok(self, *args): self.result = DLG_OK for e in self.ents: k = e[0] self.args[k] = e[1].get_text() self.quit() def cancel(self, *args): self.result = DLG_CANCEL self.quit() def quit(self, *args): self.hide() self.destroy() gtk.mainquit() def dialog(title, mesg, args, modal = gtk.FALSE): dlg = Dialog(args = args, mesg = mesg, modal = modal) dlg.set_title(title) dlg.show() gtk.mainloop() return dlg.result def main(*args): if len(sys.argv) < 2: print "ERR" sys.exit() dir = sys.argv[1] bdaddr = sys.argv[2] if len(sys.argv) > 3: name = sys.argv[3] else: name = "" title = "Bluetooth PIN Code" # Bluetooth spec recommends automatic strong random PIN generation. # So eventually we should implement that. pin = { "PIN": "" } if dir == "out": mesg = "Outgoing connection to " else: mesg = "Incoming connection from " mesg = mesg + name + "[" + bdaddr + "]" if dialog(title, mesg, pin) == DLG_OK: pin["PIN"] = string.strip(pin["PIN"]) if len(pin["PIN"]) >= 1 and len(pin["PIN"]) <= 16: print "PIN:" + pin["PIN"] else: print "ERR" else: print "ERR" # main()