|
- #!/usr/bin/env python
-
- from Foundation import *
- from AppKit import *
- from SystemConfiguration import *
- import commands, re
-
- class ToggleProxy(NSObject):
-
- def applicationDidFinishLaunching_(self, notification):
- # load icon files
- self.icons = {
- '0-0-0' : NSImage.imageNamed_("icon-0-0-0"),
- '1-0-0' : NSImage.imageNamed_("icon-1-0-0"),
- '0-1-0' : NSImage.imageNamed_("icon-0-1-0"),
- '0-0-1' : NSImage.imageNamed_("icon-0-0-1"),
- '1-1-0' : NSImage.imageNamed_("icon-1-1-0"),
- '1-0-1' : NSImage.imageNamed_("icon-1-0-1"),
- '1-1-1' : NSImage.imageNamed_("icon-1-1-1")
- }
-
- # make status bar item
- self.statusitem = NSStatusBar.systemStatusBar().statusItemWithLength_(NSVariableStatusItemLength)
- self.statusitem.retain()
- self.statusitem.setHighlightMode_(False)
- self.statusitem.setEnabled_(True)
- self.statusitem.setImage_(self.icons['0-0-0'])
-
- # insert a menu into the status bar item
- self.menu = NSMenu.alloc().init()
- self.statusitem.setMenu_(self.menu)
-
- # add items to menu
- self.httpMenuItem = self.menu.addItemWithTitle_action_keyEquivalent_(
- "HTTP proxy",
- "toggleHttpProxy:",
- "")
- self.httpsMenuItem = self.menu.addItemWithTitle_action_keyEquivalent_(
- "HTTPS proxy",
- "toggleHttpsProxy:",
- "")
- self.socksMenuItem = self.menu.addItemWithTitle_action_keyEquivalent_(
- "SOCKS proxy",
- "toggleSocksProxy:",
- "")
- self.menu.addItem_(NSMenuItem.separatorItem())
- self.menu.addItemWithTitle_action_keyEquivalent_(
- "Quit",
- "quitApp:",
- "")
-
- # open connection to the dynamic (configuration) store
- self.store = SCDynamicStoreCreate(None, "name.klep.toggleproxy", self.dynamicStoreCallback, None)
-
- # start working
- self.loadNetworkServices()
- self.watchForProxyChanges()
- self.updateProxyStatus()
-
- @property
- def interface(self):
- # get primary interface
- return SCDynamicStoreCopyValue(self.store, 'State:/Network/Global/IPv4')['PrimaryInterface']
-
- def loadNetworkServices(self):
- """ load list of network services """
- self.services = {}
- output = commands.getoutput("/usr/sbin/networksetup listnetworkserviceorder")
- for servicename, service, device in re.findall(r'\(\d\)\s*(.*?)(?:\n|\r\n?)\(Hardware Port:\s*(.*?), Device:\s*(.*?)\)', output, re.MULTILINE):
- self.services[device] = servicename
-
- def watchForProxyChanges(self):
- """ install a watcher for proxy changes """
- SCDynamicStoreSetNotificationKeys(self.store, None, [ 'State:/Network/Global/Proxies' ])
-
- source = SCDynamicStoreCreateRunLoopSource(None, self.store, 0)
- loop = NSRunLoop.currentRunLoop().getCFRunLoop()
- CFRunLoopAddSource(loop, source, kCFRunLoopCommonModes)
-
- def dynamicStoreCallback(self, store, keys, info):
- """ callback for watcher """
- self.updateProxyStatus()
-
- def updateProxyStatus(self):
- """ update proxy status """
- # load proxy dictionary
- proxydict = SCDynamicStoreCopyProxies(None)
-
- # get status for primary interface
- status = proxydict['__SCOPED__'][self.interface]
-
- # update menu items according to their related proxy state
- self.httpMenuItem.setState_( status.get('HTTPEnable', False) and NSOnState or NSOffState )
- self.httpsMenuItem.setState_( status.get('HTTPSEnable', False) and NSOnState or NSOffState )
- self.socksMenuItem.setState_( status.get('SOCKSEnable', False) and NSOnState or NSOffState )
-
- # update icon
- self.statusitem.setImage_(
- self.icons['%d-%d-%d' % (
- status.get('HTTPEnable', False) and 1 or 0,
- status.get('HTTPSEnable', False) and 1 or 0,
- status.get('SOCKSEnable', False) and 1 or 0
- )]
- )
-
- def quitApp_(self, sender):
- NSApp.terminate_(self)
-
- def toggleHttpProxy_(self, sender):
- self.toggleProxy(self.httpMenuItem, 'webproxy')
-
- def toggleHttpsProxy_(self, sender):
- self.toggleProxy(self.httpsMenuItem, 'securewebproxy')
-
- def toggleSocksProxy_(self, sender):
- self.toggleProxy(self.socksMenuItem, 'socksfirewallproxy')
-
- def toggleProxy(self, item, target):
- """ callback for clicks on menu item """
- servicename = self.services.get(self.interface)
- if not servicename:
- NSLog("interface '%s' not found in services?" % self.interface)
- return
- newstate = item.state() == NSOffState and 'on' or 'off'
- commands.getoutput("/usr/sbin/networksetup -set%sstate '%s' %s" % (
- target,
- servicename,
- newstate
- ))
- self.updateProxyStatus()
-
- if __name__ == '__main__':
- sharedapp = NSApplication.sharedApplication()
- toggler = ToggleProxy.alloc().init()
- sharedapp.setDelegate_(toggler)
- sharedapp.run()
|