forked from robertklep/ToggleProxy
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathToggleProxy.py
More file actions
163 lines (129 loc) · 6.62 KB
/
ToggleProxy.py
File metadata and controls
163 lines (129 loc) · 6.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#!/usr/bin/env python
from Foundation import *
from AppKit import *
from SystemConfiguration import *
import commands, re
class ToggleProxy(NSObject):
# This is a dictionary of the proxy-types we support, each with a
# dictionary of some unique attributes for each, namely:
#
# 'pref' : This is a constant defining which preference itemmarks if this proxy is enabled
# 'title' : This is what will appear in the menu
# 'action' : This is the method that will be called if the user toggles this proxies menuitem
# 'keyEquivalent' : Self-explanatory, but unused
# 'menuitem' : This will store the menu item for this proxy once it is created
proxies = {
'ftp' : { 'pref': kSCPropNetProxiesFTPEnable, 'title': 'FTP Proxy', 'action': 'toggleFtpProxy:', 'keyEquivalent': "", 'menuitem': None },
'http' : { 'pref': kSCPropNetProxiesHTTPEnable, 'title': 'HTTP Proxy', 'action': 'toggleHttpProxy:', 'keyEquivalent': "", 'menuitem': None },
'https': { 'pref': kSCPropNetProxiesHTTPSEnable, 'title': 'HTTPS Proxy', 'action': 'toggleHttpsProxy:', 'keyEquivalent': "", 'menuitem': None },
'rtsp' : { 'pref': kSCPropNetProxiesRTSPEnable, 'title': 'RTSP Proxy', 'action': 'toggleRtspProxy:', 'keyEquivalent': "", 'menuitem': None },
'socks': { 'pref': kSCPropNetProxiesSOCKSEnable, 'title': 'SOCKS Proxy', 'action': 'toggleSocksProxy:', 'keyEquivalent': "", 'menuitem': None },
}
def applicationDidFinishLaunching_(self, notification):
# load icon 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.setHighlightMode_(False)
self.statusitem.setEnabled_(True)
# insert a menu into the status bar item
self.menu = NSMenu.alloc().init()
self.statusitem.setMenu_(self.menu)
# open connection to the dynamic (configuration) store
self.store = SCDynamicStoreCreate(None, "name.klep.toggleproxy", self.dynamicStoreCallback, None)
proxyRef = SCNetworkServiceCopyProtocol(self.service, kSCNetworkProtocolTypeProxies)
prefDict = SCNetworkProtocolGetConfiguration(proxyRef)
separatorRequired = False
# For each of the proxies we are concerned with, check to see if any
# are configured. If so (even if not enabled), create a menuitem for
# that proxy type.
for proxy in self.proxies.values():
enabled = CFDictionaryGetValue(prefDict, proxy['pref'])
if enabled is not None:
proxy['menuitem'] = self.menu.addItemWithTitle_action_keyEquivalent_(
proxy['title'],
proxy['action'],
proxy['keyEquivalent']
)
separatorRequired = True
else:
proxy['menuitem'] = None
if separatorRequired:
self.menu.addItem_(NSMenuItem.separatorItem())
# Need a way to quit
self.menu.addItemWithTitle_action_keyEquivalent_("Quit", "quitApp:", "")
# Start working
# self.loadNetworkServices()
self.watchForProxyChanges()
self.updateProxyStatus()
@property
def interface(self):
# get primary interface
return SCDynamicStoreCopyValue(self.store, 'State:/Network/Global/IPv4')['PrimaryInterface']
@property
def service(self):
""" Returns the service relating to self.interface """
prefs = SCPreferencesCreate(kCFAllocatorDefault, 'PRG', None)
# Fetch the list of services
for serviceRef in SCNetworkServiceCopyAll(prefs):
interface = SCNetworkServiceGetInterface(serviceRef)
if self.interface == SCNetworkInterfaceGetBSDName(interface):
return serviceRef
return None
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]
# Are any proxies active now?
anyProxyEnabled = False
# update menu items according to their related proxy state
for proxy in self.proxies.values():
if proxy['menuitem']:
proxy['menuitem'].setState_(status.get(proxy['pref'], False) and NSOnState or NSOffState)
if status.get(proxy['pref'], False):
anyProxyEnabled = True
# set image
self.statusitem.setImage_(anyProxyEnabled and self.active_image or self.inactive_image)
def quitApp_(self, sender):
NSApp.terminate_(self)
def toggleFtpProxy_(self, sender):
self.toggleProxy(self.proxies['ftp']['menuitem'], 'ftpproxy')
def toggleHttpProxy_(self, sender):
self.toggleProxy(self.proxies['http']['menuitem'], 'webproxy')
def toggleHttpsProxy_(self, sender):
self.toggleProxy(self.proxies['https']['menuitem'], 'securewebproxy')
def toggleRtspProxy_(self, sender):
self.toggleProxy(self.proxies['socks']['menuitem'], 'streamingproxy')
def toggleSocksProxy_(self, sender):
self.toggleProxy(self.proxies['socks']['menuitem'], 'socksfirewallproxy')
def toggleProxy(self, item, target):
""" callback for clicks on menu item """
servicename = SCNetworkServiceGetName(self.service)
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()