#!/usr/bin/env python from Foundation import * from AppKit import * from SystemConfiguration import * import commands, re, time class ToggleProxy(NSObject): def applicationDidFinishLaunching_(self, notification): # define some title-related stuff self.active_color = NSColor.colorWithSRGBRed_green_blue_alpha_(0, 0.5, 0, 1) self.inactive_color = NSColor.colorWithSRGBRed_green_blue_alpha_(0.6, 0, 0, 1) self.title_font = NSFont.fontWithName_size_('HelveticaNeue-Bold', 12.0) # find image files self.active_image = NSImage.imageNamed_("active") self.inactive_image = NSImage.imageNamed_("inactive") # make status bar item self.statusitem = NSStatusBar.systemStatusBar().statusItemWithLength_(NSVariableStatusItemLength) self.statusitem.retain() self.statusitem.setAction_("toggleProxy:") self.statusitem.setTarget_(self) self.statusitem.setHighlightMode_(False) self.statusitem.setEnabled_(True) # 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 = {} for key, dictionary in SCDynamicStoreCopyMultiple(self.store, None, [ 'Setup:/Network/Service/.*/Interface' ]).items(): self.services[dictionary['DeviceName']] = dictionary['UserDefinedName'] 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] self.active = status.get('HTTPEnable', False) and True or False # set image self.statusitem.setImage_( self.active and self.active_image or self.inactive_image ) # set tooltip if self.active: tooltip = "[%s] proxy active on %s:%s" % ( self.interface, proxydict.get('HTTPProxy', '??'), proxydict.get('HTTPPort', '??'), ) else: tooltip = "[%s] proxy not active" % self.interface self.statusitem.setToolTip_(tooltip) def toggleProxy_(self, sender): """ callback for clicks on menu item """ event = NSApp.currentEvent() # Ctrl pressed? if so, quit if event.modifierFlags() & NSControlKeyMask: NSApp.terminate_(self) return servicename = self.services.get(self.interface) if not servicename: NSLog("interface '%s' not found in services?" % self.interface) return newstate = self.active and "off" or "on" commands.getoutput("networksetup setwebproxystate %s %s" % ( servicename, newstate )) self.updateProxyStatus() if __name__ == '__main__': sharedapp = NSApplication.sharedApplication() toggler = ToggleProxy.alloc().init() sharedapp.setDelegate_(toggler) sharedapp.run()