| #!/usr/bin/python |
| # |
| # Bluetooth PIN helper |
| # Written by Maxim Krasnyansky <maxk@qualcomm.com> |
| # |
| 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 Xorg -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() |