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
|
"""Helper methods for urllib to fetch the proxy configuration settings using
the SystemConfiguration framework.
"""
import sys
if sys.platform != 'darwin':
raise ImportError('Requires Mac OS X')
from ctypes import c_int32, c_int64, c_void_p, c_char_p, c_int, cdll
from ctypes import pointer, create_string_buffer
from ctypes.util import find_library
kCFNumberSInt32Type = 3
kCFStringEncodingUTF8 = 134217984
def _CFSetup():
sc = cdll.LoadLibrary(find_library("SystemConfiguration"))
cf = cdll.LoadLibrary(find_library("CoreFoundation"))
sctable = [
('SCDynamicStoreCopyProxies', [c_void_p], c_void_p),
]
cftable = [
('CFArrayGetCount', [c_void_p], c_int64),
('CFArrayGetValueAtIndex', [c_void_p, c_int64], c_void_p),
('CFDictionaryGetValue', [c_void_p, c_void_p], c_void_p),
('CFStringCreateWithCString', [c_void_p, c_char_p, c_int32], c_void_p),
('CFStringGetLength', [c_void_p], c_int32),
('CFStringGetCString', [c_void_p, c_char_p, c_int32, c_int32], c_int32),
('CFNumberGetValue', [c_void_p, c_int, c_void_p], c_int32),
('CFRelease', [c_void_p], None),
]
scconst = [
'kSCPropNetProxiesExceptionsList',
'kSCPropNetProxiesExcludeSimpleHostnames',
'kSCPropNetProxiesHTTPEnable',
'kSCPropNetProxiesHTTPProxy',
'kSCPropNetProxiesHTTPPort',
'kSCPropNetProxiesHTTPSEnable',
'kSCPropNetProxiesHTTPSProxy',
'kSCPropNetProxiesHTTPSPort',
'kSCPropNetProxiesFTPEnable',
'kSCPropNetProxiesFTPProxy',
'kSCPropNetProxiesFTPPort',
'kSCPropNetProxiesGopherEnable',
'kSCPropNetProxiesGopherProxy',
'kSCPropNetProxiesGopherPort',
]
class CFProxy(object):
def __init__(self):
for mod, table in [(sc, sctable), (cf, cftable)]:
for fname, argtypes, restype in table:
func = getattr(mod, fname)
func.argtypes = argtypes
func.restype = restype
setattr(self, fname, func)
for k in scconst:
v = None
try:
v = c_void_p.in_dll(sc, k)
except ValueError:
v = None
setattr(self, k, v)
return CFProxy()
ffi = _CFSetup()
def cfstring_to_pystring(value):
length = (ffi.CFStringGetLength(value) * 4) + 1
buff = create_string_buffer(length)
ffi.CFStringGetCString(value, buff, length * 4, kCFStringEncodingUTF8)
return unicode(buff.value, 'utf8')
def cfnum_to_int32(num):
result_ptr = pointer(c_int32(0))
ffi.CFNumberGetValue(num, kCFNumberSInt32Type, result_ptr)
return result_ptr[0]
def _get_proxy_settings():
result = {'exclude_simple': False}
cfdct = ffi.SCDynamicStoreCopyProxies(None)
if not cfdct:
return result
try:
k = ffi.kSCPropNetProxiesExcludeSimpleHostnames
if k:
cfnum = ffi.CFDictionaryGetValue(cfdct, k)
if cfnum:
result['exclude_simple'] = bool(cfnum_to_int32(cfnum))
k = ffi.kSCPropNetProxiesExceptionsList
if k:
cfarr = ffi.CFDictionaryGetValue(cfdct, k)
if cfarr:
lst = []
for i in range(ffi.CFArrayGetCount(cfarr)):
cfstr = ffi.CFArrayGetValueAtIndex(cfarr, i)
if cfstr:
v = cfstring_to_pystring(cfstr)
else:
v = None
lst.append(v)
result['exceptions'] = lst
return result
finally:
ffi.CFRelease(cfdct)
def _get_proxies():
result = {}
cfdct = ffi.SCDynamicStoreCopyProxies(None)
if not cfdct:
return result
try:
for proto in 'HTTP', 'HTTPS', 'FTP', 'Gopher':
enabled_key = getattr(ffi, 'kSCPropNetProxies' + proto + 'Enable')
proxy_key = getattr(ffi, 'kSCPropNetProxies' + proto + 'Proxy')
port_key = getattr(ffi, 'kSCPropNetProxies' + proto + 'Port')
cfnum = ffi.CFDictionaryGetValue(cfdct, enabled_key)
if cfnum and cfnum_to_int32(cfnum):
cfhoststr = ffi.CFDictionaryGetValue(cfdct, proxy_key)
cfportnum = ffi.CFDictionaryGetValue(cfdct, port_key)
if cfhoststr:
host = cfstring_to_pystring(cfhoststr)
if host:
if cfportnum:
port = cfnum_to_int32(cfportnum)
v = u'http://%s:%d' % (host, port)
else:
v = u'http://%s' % (host,)
result[proto.lower()] = v
return result
finally:
ffi.CFRelease(cfdct)
|